zlib_rs/
lib.rs

1#![doc = core::include_str!("../README.md")]
2#![cfg_attr(not(any(test, feature = "rust-allocator")), no_std)]
3
4#[cfg(any(feature = "rust-allocator", feature = "c-allocator"))]
5extern crate alloc;
6
7pub mod adler32;
8pub mod crc32;
9
10cfg_select! {
11    feature = "__internal-api" => {
12        pub mod allocate;
13        pub mod c_api;
14        pub mod deflate;
15        pub mod inflate;
16
17        pub const MIN_WBITS: i32 = 8; // 256b LZ77 window
18        pub const MAX_WBITS: i32 = 15; // 32kb LZ77 window
19    }
20    _ => {
21        pub(crate) mod allocate;
22        pub(crate) mod c_api;
23        pub(crate) mod deflate;
24        pub(crate) mod inflate;
25
26        pub(crate) const MIN_WBITS: i32 = 8; // 256b LZ77 window
27        pub(crate) const MAX_WBITS: i32 = 15; // 32kb LZ77 window
28    }
29}
30
31mod cpu_features;
32mod stable;
33mod weak_slice;
34
35pub use stable::{Deflate, DeflateError, Inflate, InflateError, Status};
36
37pub use deflate::{DeflateConfig, Method, Strategy};
38pub use inflate::InflateConfig;
39
40pub use deflate::{compress_bound, compress_slice};
41pub use inflate::decompress_slice;
42
43macro_rules! trace {
44    ($($arg:tt)*) => {
45        #[cfg(feature = "ZLIB_DEBUG")]
46        {
47            eprint!($($arg)*)
48        }
49    };
50}
51pub(crate) use trace;
52
53macro_rules! cfg_select {
54    ({ $($tt:tt)* }) => {{
55        $crate::cfg_select! { $($tt)* }
56    }};
57    (_ => { $($output:tt)* }) => {
58        $($output)*
59    };
60    (
61        $cfg:meta => $output:tt
62        $($( $rest:tt )+)?
63    ) => {
64        #[cfg($cfg)]
65        $crate::cfg_select! { _ => $output }
66        $(
67            #[cfg(not($cfg))]
68            $crate::cfg_select! { $($rest)+ }
69        )?
70    }
71}
72use cfg_select;
73
74/// Maximum size of the dynamic table.  The maximum number of code structures is
75/// 1924, which is the sum of 1332 for literal/length codes and 592 for distance
76/// codes.  These values were found by exhaustive searches using the program
77/// examples/enough.c found in the zlib distributions.  The arguments to that
78/// program are the number of symbols, the initial root table size, and the
79/// maximum bit length of a code.  "enough 286 10 15" for literal/length codes
80/// returns 1332, and "enough 30 9 15" for distance codes returns 592.
81/// The initial root table size (10 or 9) is found in the fifth argument of the
82/// inflate_table() calls in inflate.c and infback.c.  If the root table size is
83/// changed, then these maximum sizes would be need to be recalculated and
84/// updated.
85#[allow(unused)]
86pub(crate) const ENOUGH: usize = ENOUGH_LENS + ENOUGH_DISTS;
87pub(crate) const ENOUGH_LENS: usize = 1332;
88pub(crate) const ENOUGH_DISTS: usize = 592;
89
90/// initial adler-32 hash value
91pub(crate) const ADLER32_INITIAL_VALUE: usize = 1;
92/// initial crc-32 hash value
93pub(crate) const CRC32_INITIAL_VALUE: u32 = 0;
94
95pub(crate) const DEF_WBITS: i32 = MAX_WBITS;
96
97#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
98#[cfg_attr(feature = "__internal-fuzz", derive(arbitrary::Arbitrary))]
99pub enum DeflateFlush {
100    #[default]
101    /// if flush is set to `NoFlush`, that allows deflate to decide how much data
102    /// to accumulate before producing output, in order to maximize compression.
103    NoFlush = 0,
104
105    /// If flush is set to `PartialFlush`, all pending output is flushed to the
106    /// output buffer, but the output is not aligned to a byte boundary.  All of the
107    /// input data so far will be available to the decompressor, as for Z_SYNC_FLUSH.
108    /// This completes the current deflate block and follows it with an empty fixed
109    /// codes block that is 10 bits long.  This assures that enough bytes are output
110    /// in order for the decompressor to finish the block before the empty fixed
111    /// codes block.
112    PartialFlush = 1,
113
114    /// If the parameter flush is set to `SyncFlush`, all pending output is
115    /// flushed to the output buffer and the output is aligned on a byte boundary, so
116    /// that the decompressor can get all input data available so far.  (In
117    /// particular avail_in is zero after the call if enough output space has been
118    /// provided before the call.) Flushing may degrade compression for some
119    /// compression algorithms and so it should be used only when necessary.  This
120    /// completes the current deflate block and follows it with an empty stored block
121    /// that is three bits plus filler bits to the next byte, followed by four bytes
122    /// (00 00 ff ff).
123    SyncFlush = 2,
124
125    /// If flush is set to `FullFlush`, all output is flushed as with
126    /// Z_SYNC_FLUSH, and the compression state is reset so that decompression can
127    /// restart from this point if previous compressed data has been damaged or if
128    /// random access is desired.  Using `FullFlush` too often can seriously degrade
129    /// compression.
130    FullFlush = 3,
131
132    /// If the parameter flush is set to `Finish`, pending input is processed,
133    /// pending output is flushed and deflate returns with `StreamEnd` if there was
134    /// enough output space.  If deflate returns with `Ok` or `BufError`, this
135    /// function must be called again with `Finish` and more output space (updated
136    /// avail_out) but no more input data, until it returns with `StreamEnd` or an
137    /// error.  After deflate has returned `StreamEnd`, the only possible operations
138    /// on the stream are deflateReset or deflateEnd.
139    ///
140    /// `Finish` can be used in the first deflate call after deflateInit if all the
141    /// compression is to be done in a single step.  In order to complete in one
142    /// call, avail_out must be at least the value returned by deflateBound (see
143    /// below).  Then deflate is guaranteed to return `StreamEnd`.  If not enough
144    /// output space is provided, deflate will not return `StreamEnd`, and it must
145    /// be called again as described above.
146    Finish = 4,
147
148    /// If flush is set to `Block`, a deflate block is completed and emitted, as
149    /// for `SyncFlush`, but the output is not aligned on a byte boundary, and up to
150    /// seven bits of the current block are held to be written as the next byte after
151    /// the next deflate block is completed.  In this case, the decompressor may not
152    /// be provided enough bits at this point in order to complete decompression of
153    /// the data provided so far to the compressor.  It may need to wait for the next
154    /// block to be emitted.  This is for advanced applications that need to control
155    /// the emission of deflate blocks.
156    Block = 5,
157}
158
159impl TryFrom<i32> for DeflateFlush {
160    type Error = ();
161
162    fn try_from(value: i32) -> Result<Self, Self::Error> {
163        match value {
164            0 => Ok(Self::NoFlush),
165            1 => Ok(Self::PartialFlush),
166            2 => Ok(Self::SyncFlush),
167            3 => Ok(Self::FullFlush),
168            4 => Ok(Self::Finish),
169            5 => Ok(Self::Block),
170            _ => Err(()),
171        }
172    }
173}
174
175#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
176pub enum InflateFlush {
177    #[default]
178    NoFlush = 0,
179    SyncFlush = 2,
180    Finish = 4,
181    Block = 5,
182    Trees = 6,
183}
184
185impl TryFrom<i32> for InflateFlush {
186    type Error = ();
187
188    fn try_from(value: i32) -> Result<Self, Self::Error> {
189        match value {
190            0 => Ok(Self::NoFlush),
191            2 => Ok(Self::SyncFlush),
192            4 => Ok(Self::Finish),
193            5 => Ok(Self::Block),
194            6 => Ok(Self::Trees),
195            _ => Err(()),
196        }
197    }
198}
199
200#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
201pub(crate) struct Code {
202    /// operation, extra bits, table bits
203    pub op: u8,
204    /// bits in this part of the code
205    pub bits: u8,
206    /// offset in table or code value
207    pub val: u16,
208}
209
210#[derive(Debug, Copy, Clone, PartialEq, Eq)]
211#[repr(i32)]
212pub enum ReturnCode {
213    Ok = 0,
214    StreamEnd = 1,
215    NeedDict = 2,
216    ErrNo = -1,
217    StreamError = -2,
218    DataError = -3,
219    MemError = -4,
220    BufError = -5,
221    VersionError = -6,
222}
223
224impl From<i32> for ReturnCode {
225    fn from(value: i32) -> Self {
226        match Self::try_from_c_int(value) {
227            Some(value) => value,
228            None => panic!("invalid return code {value}"),
229        }
230    }
231}
232
233impl ReturnCode {
234    fn error_message_str(self) -> &'static str {
235        self.error_message_str_with_null().trim_end_matches('\0')
236    }
237
238    const fn error_message_str_with_null(self) -> &'static str {
239        match self {
240            ReturnCode::Ok => "\0",
241            ReturnCode::StreamEnd => "stream end\0",
242            ReturnCode::NeedDict => "need dictionary\0",
243            ReturnCode::ErrNo => "file error\0",
244            ReturnCode::StreamError => "stream error\0",
245            ReturnCode::DataError => "data error\0",
246            ReturnCode::MemError => "insufficient memory\0",
247            ReturnCode::BufError => "buffer error\0",
248            ReturnCode::VersionError => "incompatible version\0",
249        }
250    }
251
252    pub const fn error_message(self) -> *const core::ffi::c_char {
253        let msg = self.error_message_str_with_null();
254        msg.as_ptr().cast::<core::ffi::c_char>()
255    }
256
257    pub const fn try_from_c_int(err: core::ffi::c_int) -> Option<Self> {
258        match err {
259            0 => Some(Self::Ok),
260            1 => Some(Self::StreamEnd),
261            2 => Some(Self::NeedDict),
262            -1 => Some(Self::ErrNo),
263            -2 => Some(Self::StreamError),
264            -3 => Some(Self::DataError),
265            -4 => Some(Self::MemError),
266            -5 => Some(Self::BufError),
267            -6 => Some(Self::VersionError),
268            _ => None,
269        }
270    }
271}