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