| 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 | |