1 | //! A pure rust replacement for the [miniz](https://github.com/richgel999/miniz) |
2 | //! DEFLATE/zlib encoder/decoder. |
3 | //! Used a rust back-end for the |
4 | //! [flate2](https://github.com/alexcrichton/flate2-rs) crate. |
5 | //! |
6 | #![cfg_attr ( |
7 | feature = "with-alloc" , |
8 | doc = r##" |
9 | # Usage |
10 | ## Simple compression/decompression: |
11 | ``` rust |
12 | |
13 | use miniz_oxide::inflate::decompress_to_vec; |
14 | use miniz_oxide::deflate::compress_to_vec; |
15 | |
16 | fn roundtrip(data: &[u8]) { |
17 | let compressed = compress_to_vec(data, 6); |
18 | let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!"); |
19 | # let _ = decompressed; |
20 | } |
21 | |
22 | # roundtrip(b"Test_data test data lalalal blabla"); |
23 | "## |
24 | )] |
25 | #![forbid (unsafe_code)] |
26 | #![cfg_attr (not(feature = "std" ), no_std)] |
27 | |
28 | #[cfg (feature = "with-alloc" )] |
29 | extern crate alloc; |
30 | |
31 | #[cfg (feature = "with-alloc" )] |
32 | pub mod deflate; |
33 | pub mod inflate; |
34 | mod shared; |
35 | |
36 | pub use crate::shared::update_adler32 as mz_adler32_oxide; |
37 | pub use crate::shared::{MZ_ADLER32_INIT, MZ_DEFAULT_WINDOW_BITS}; |
38 | |
39 | /// A list of flush types. |
40 | /// |
41 | /// See <http://www.bolet.org/~pornin/deflate-flush.html> for more in-depth info. |
42 | #[repr (i32)] |
43 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Hash)] |
44 | pub enum MZFlush { |
45 | /// Don't force any flushing. |
46 | /// Used when more input data is expected. |
47 | None = 0, |
48 | /// Zlib partial flush. |
49 | /// Currently treated as [`Sync`]. |
50 | Partial = 1, |
51 | /// Finish compressing the currently buffered data, and output an empty raw block. |
52 | /// Has no use in decompression. |
53 | Sync = 2, |
54 | /// Same as [`Sync`], but resets the compression dictionary so that further compressed |
55 | /// data does not depend on data compressed before the flush. |
56 | /// |
57 | /// Has no use in decompression, and is an error to supply in that case. |
58 | Full = 3, |
59 | /// Attempt to flush the remaining data and end the stream. |
60 | Finish = 4, |
61 | /// Not implemented. |
62 | Block = 5, |
63 | } |
64 | |
65 | impl MZFlush { |
66 | /// Create an MZFlush value from an integer value. |
67 | /// |
68 | /// Returns `MZError::Param` on invalid values. |
69 | pub fn new(flush: i32) -> Result<Self, MZError> { |
70 | match flush { |
71 | 0 => Ok(MZFlush::None), |
72 | 1 | 2 => Ok(MZFlush::Sync), |
73 | 3 => Ok(MZFlush::Full), |
74 | 4 => Ok(MZFlush::Finish), |
75 | _ => Err(MZError::Param), |
76 | } |
77 | } |
78 | } |
79 | |
80 | /// A list of miniz successful status codes. |
81 | /// |
82 | /// These are emitted as the [`Ok`] side of a [`MZResult`] in the [`StreamResult`] returned from |
83 | /// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`]. |
84 | #[repr (i32)] |
85 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Hash)] |
86 | pub enum MZStatus { |
87 | /// Operation succeeded. |
88 | /// |
89 | /// Some data was decompressed or compressed; see the byte counters in the [`StreamResult`] for |
90 | /// details. |
91 | Ok = 0, |
92 | |
93 | /// Operation succeeded and end of deflate stream was found. |
94 | /// |
95 | /// X-ref [`TINFLStatus::Done`][inflate::TINFLStatus::Done] or |
96 | /// [`TDEFLStatus::Done`][deflate::core::TDEFLStatus::Done] for `inflate` or `deflate` |
97 | /// respectively. |
98 | StreamEnd = 1, |
99 | |
100 | /// Unused |
101 | NeedDict = 2, |
102 | } |
103 | |
104 | /// A list of miniz failed status codes. |
105 | /// |
106 | /// These are emitted as the [`Err`] side of a [`MZResult`] in the [`StreamResult`] returned from |
107 | /// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`]. |
108 | #[repr (i32)] |
109 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Hash)] |
110 | pub enum MZError { |
111 | /// Unused |
112 | ErrNo = -1, |
113 | |
114 | /// General stream error. |
115 | /// |
116 | /// See [`inflate::stream::inflate()`] docs for details of how it can occur there. |
117 | /// |
118 | /// See [`deflate::stream::deflate()`] docs for how it can in principle occur there, though it's |
119 | /// believed impossible in practice. |
120 | Stream = -2, |
121 | |
122 | /// Error in inflation; see [`inflate::stream::inflate()`] for details. |
123 | /// |
124 | /// Not returned from [`deflate::stream::deflate()`]. |
125 | Data = -3, |
126 | |
127 | /// Unused |
128 | Mem = -4, |
129 | |
130 | /// Buffer-related error. |
131 | /// |
132 | /// See the docs of [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`] for details |
133 | /// of when it would trigger in the one you're using. |
134 | Buf = -5, |
135 | |
136 | /// Unused |
137 | Version = -6, |
138 | |
139 | /// Bad parameters. |
140 | /// |
141 | /// This can be returned from [`deflate::stream::deflate()`] in the case of bad parameters. See |
142 | /// [`TDEFLStatus::BadParam`][deflate::core::TDEFLStatus::BadParam]. |
143 | Param = -10_000, |
144 | } |
145 | |
146 | /// How compressed data is wrapped. |
147 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Hash)] |
148 | #[non_exhaustive ] |
149 | pub enum DataFormat { |
150 | /// Wrapped using the [zlib](http://www.zlib.org/rfc-zlib.html) format. |
151 | Zlib, |
152 | /// Zlib wrapped but ignore and don't compute the adler32 checksum. |
153 | /// Currently only used for inflate, behaves the same as Zlib for compression. |
154 | ZLibIgnoreChecksum, |
155 | /// Raw DEFLATE. |
156 | Raw, |
157 | } |
158 | |
159 | impl DataFormat { |
160 | pub fn from_window_bits(window_bits: i32) -> DataFormat { |
161 | if window_bits > 0 { |
162 | DataFormat::Zlib |
163 | } else { |
164 | DataFormat::Raw |
165 | } |
166 | } |
167 | |
168 | pub fn to_window_bits(self) -> i32 { |
169 | match self { |
170 | DataFormat::Zlib | DataFormat::ZLibIgnoreChecksum => shared::MZ_DEFAULT_WINDOW_BITS, |
171 | DataFormat::Raw => -shared::MZ_DEFAULT_WINDOW_BITS, |
172 | } |
173 | } |
174 | } |
175 | |
176 | /// `Result` alias for all miniz status codes both successful and failed. |
177 | pub type MZResult = Result<MZStatus, MZError>; |
178 | |
179 | /// A structure containing the result of a call to the inflate or deflate streaming functions. |
180 | #[derive (Debug, Copy, Clone, PartialEq, Eq, Hash)] |
181 | pub struct StreamResult { |
182 | /// The number of bytes consumed from the input slice. |
183 | pub bytes_consumed: usize, |
184 | /// The number of bytes written to the output slice. |
185 | pub bytes_written: usize, |
186 | /// The return status of the call. |
187 | pub status: MZResult, |
188 | } |
189 | |
190 | impl StreamResult { |
191 | #[inline ] |
192 | pub const fn error(error: MZError) -> StreamResult { |
193 | StreamResult { |
194 | bytes_consumed: 0, |
195 | bytes_written: 0, |
196 | status: Err(error), |
197 | } |
198 | } |
199 | } |
200 | |
201 | impl core::convert::From<StreamResult> for MZResult { |
202 | fn from(res: StreamResult) -> Self { |
203 | res.status |
204 | } |
205 | } |
206 | |
207 | impl core::convert::From<&StreamResult> for MZResult { |
208 | fn from(res: &StreamResult) -> Self { |
209 | res.status |
210 | } |
211 | } |
212 | |