Skip to main content

zlib_rs/
deflate.rs

1use core::{ffi::CStr, marker::PhantomData, mem::MaybeUninit, ops::ControlFlow, ptr::NonNull};
2
3use crate::{
4    adler32::adler32,
5    allocate::Allocator,
6    c_api::{gz_header, internal_state, z_checksum, z_stream},
7    crc32::{crc32, Crc32Fold},
8    trace,
9    weak_slice::{WeakArrayMut, WeakSliceMut},
10    DeflateFlush, ReturnCode, ADLER32_INITIAL_VALUE, CRC32_INITIAL_VALUE, MAX_WBITS, MIN_WBITS,
11};
12
13use self::{
14    algorithm::CONFIGURATION_TABLE,
15    hash_calc::{HashCalcVariant, RollHashCalc, StandardHashCalc},
16    pending::Pending,
17    sym_buf::SymBuf,
18    trees_tbl::STATIC_LTREE,
19    window::Window,
20};
21
22mod algorithm;
23mod compare256;
24mod hash_calc;
25mod longest_match;
26mod pending;
27mod slide_hash;
28mod sym_buf;
29mod trees_tbl;
30mod window;
31
32// Position relative to the current window
33pub(crate) type Pos = u16;
34
35// SAFETY: This struct must have the same layout as [`z_stream`], so that casts and transmutations
36// between the two can work without UB.
37#[repr(C)]
38pub struct DeflateStream<'a> {
39    pub(crate) next_in: *mut crate::c_api::Bytef,
40    pub(crate) avail_in: crate::c_api::uInt,
41    pub(crate) total_in: crate::c_api::z_size,
42    pub(crate) next_out: *mut crate::c_api::Bytef,
43    pub(crate) avail_out: crate::c_api::uInt,
44    pub(crate) total_out: crate::c_api::z_size,
45    pub(crate) msg: *const core::ffi::c_char,
46    pub(crate) state: &'a mut State<'a>,
47    pub(crate) alloc: Allocator<'a>,
48    pub(crate) data_type: core::ffi::c_int,
49    pub(crate) adler: crate::c_api::z_checksum,
50    pub(crate) reserved: crate::c_api::uLong,
51}
52
53unsafe impl Sync for DeflateStream<'_> {}
54unsafe impl Send for DeflateStream<'_> {}
55
56impl<'a> DeflateStream<'a> {
57    // z_stream and DeflateStream must have the same layout. Do our best to check if this is true.
58    // (imperfect check, but should catch most mistakes.)
59    const _S: () = assert!(core::mem::size_of::<z_stream>() == core::mem::size_of::<Self>());
60    const _A: () = assert!(core::mem::align_of::<z_stream>() == core::mem::align_of::<Self>());
61
62    /// # Safety
63    ///
64    /// Behavior is undefined if any of the following conditions are violated:
65    ///
66    /// - `strm` satisfies the conditions of [`pointer::as_mut`]
67    /// - if not `NULL`, `strm` as initialized using [`init`] or similar
68    ///
69    /// [`pointer::as_mut`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_mut
70    #[inline(always)]
71    pub unsafe fn from_stream_mut(strm: *mut z_stream) -> Option<&'a mut Self> {
72        {
73            // Safety: ptr points to a valid value of type z_stream (if non-null)
74            let stream = unsafe { strm.as_ref() }?;
75
76            if stream.zalloc.is_none() || stream.zfree.is_none() {
77                return None;
78            }
79
80            if stream.state.is_null() {
81                return None;
82            }
83        }
84
85        // SAFETY: DeflateStream has an equivalent layout as z_stream
86        unsafe { strm.cast::<DeflateStream>().as_mut() }
87    }
88
89    /// # Safety
90    ///
91    /// Behavior is undefined if any of the following conditions are violated:
92    ///
93    /// - `strm` satisfies the conditions of [`pointer::as_ref`]
94    /// - if not `NULL`, `strm` as initialized using [`init`] or similar
95    ///
96    /// [`pointer::as_ref`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_ref
97    #[inline(always)]
98    pub unsafe fn from_stream_ref(strm: *const z_stream) -> Option<&'a Self> {
99        {
100            // Safety: ptr points to a valid value of type z_stream (if non-null)
101            let stream = unsafe { strm.as_ref() }?;
102
103            if stream.zalloc.is_none() || stream.zfree.is_none() {
104                return None;
105            }
106
107            if stream.state.is_null() {
108                return None;
109            }
110        }
111
112        // SAFETY: DeflateStream has an equivalent layout as z_stream
113        unsafe { strm.cast::<DeflateStream>().as_ref() }
114    }
115
116    fn as_z_stream_mut(&mut self) -> &mut z_stream {
117        // SAFETY: a valid &mut DeflateStream is also a valid &mut z_stream
118        unsafe { &mut *(self as *mut DeflateStream as *mut z_stream) }
119    }
120
121    pub fn pending(&self) -> (usize, u8) {
122        (
123            self.state.bit_writer.pending.pending,
124            self.state.bit_writer.bits_valid,
125        )
126    }
127
128    /// Last number of used bits when going to a byte boundary.
129    pub fn bits_used(&self) -> u8 {
130        self.state.bit_writer.bits_used
131    }
132
133    pub fn new(config: DeflateConfig) -> Self {
134        let mut inner = crate::c_api::z_stream::default();
135
136        let ret = crate::deflate::init(&mut inner, config);
137        assert_eq!(ret, ReturnCode::Ok);
138
139        unsafe { core::mem::transmute(inner) }
140    }
141}
142
143/// number of elements in hash table
144pub(crate) const HASH_SIZE: usize = 65536;
145/// log2(HASH_SIZE)
146const HASH_BITS: usize = 16;
147
148/// Maximum value for memLevel in deflateInit2
149const MAX_MEM_LEVEL: i32 = 9;
150pub const DEF_MEM_LEVEL: i32 = if MAX_MEM_LEVEL > 8 { 8 } else { MAX_MEM_LEVEL };
151
152#[repr(i32)]
153#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
154#[cfg_attr(feature = "__internal-fuzz", derive(arbitrary::Arbitrary))]
155pub enum Method {
156    #[default]
157    Deflated = 8,
158}
159
160impl TryFrom<i32> for Method {
161    type Error = ();
162
163    fn try_from(value: i32) -> Result<Self, Self::Error> {
164        match value {
165            8 => Ok(Self::Deflated),
166            _ => Err(()),
167        }
168    }
169}
170
171/// Configuration for compression.
172///
173/// Used with [`compress_slice`].
174///
175/// In most cases only the compression level is relevant. We provide three profiles:
176///
177/// - [`DeflateConfig::best_speed`] provides the fastest compression (at the cost of compression
178///   quality)
179/// - [`DeflateConfig::default`] tries to find a happy middle
180/// - [`DeflateConfig::best_compression`] provides the best compression (at the cost of longer
181///   runtime)
182#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
183#[cfg_attr(feature = "__internal-fuzz", derive(arbitrary::Arbitrary))]
184pub struct DeflateConfig {
185    pub level: i32,
186    pub method: Method,
187    pub window_bits: i32,
188    pub mem_level: i32,
189    pub strategy: Strategy,
190}
191
192#[cfg(any(test, feature = "__internal-test"))]
193impl quickcheck::Arbitrary for DeflateConfig {
194    fn arbitrary(g: &mut quickcheck::Gen) -> Self {
195        let mem_levels: Vec<_> = (1..=9).collect();
196        let levels: Vec<_> = (0..=9).collect();
197
198        let mut window_bits = Vec::new();
199        window_bits.extend(9..=15); // zlib
200        window_bits.extend(9 + 16..=15 + 16); // gzip
201        window_bits.extend(-15..=-9); // raw
202
203        Self {
204            level: *g.choose(&levels).unwrap(),
205            method: Method::Deflated,
206            window_bits: *g.choose(&window_bits).unwrap(),
207            mem_level: *g.choose(&mem_levels).unwrap(),
208            strategy: *g
209                .choose(&[
210                    Strategy::Default,
211                    Strategy::Filtered,
212                    Strategy::HuffmanOnly,
213                    Strategy::Rle,
214                    Strategy::Fixed,
215                ])
216                .unwrap(),
217        }
218    }
219}
220
221impl DeflateConfig {
222    pub fn new(level: i32) -> Self {
223        Self {
224            level,
225            ..Self::default()
226        }
227    }
228
229    /// Configure for the best compression (takes longer).
230    pub fn best_compression() -> Self {
231        Self::new(crate::c_api::Z_BEST_COMPRESSION)
232    }
233
234    /// Configure for the fastest compression (compresses less well).
235    pub fn best_speed() -> Self {
236        Self::new(crate::c_api::Z_BEST_SPEED)
237    }
238}
239
240impl Default for DeflateConfig {
241    fn default() -> Self {
242        Self {
243            level: crate::c_api::Z_DEFAULT_COMPRESSION,
244            method: Method::Deflated,
245            window_bits: MAX_WBITS,
246            mem_level: DEF_MEM_LEVEL,
247            strategy: Strategy::Default,
248        }
249    }
250}
251
252pub fn init(stream: &mut z_stream, config: DeflateConfig) -> ReturnCode {
253    let DeflateConfig {
254        mut level,
255        method: _,
256        mut window_bits,
257        mem_level,
258        strategy,
259    } = config;
260
261    /* Todo: ignore strm->next_in if we use it as window */
262    stream.msg = core::ptr::null_mut();
263
264    // for safety we  must really make sure that alloc and free are consistent
265    // this is a (slight) deviation from stock zlib. In this crate we pick the rust
266    // allocator as the default, but `libz-rs-sys` always explicitly sets an allocator,
267    // and can configure the C allocator
268    #[cfg(feature = "rust-allocator")]
269    if stream.zalloc.is_none() || stream.zfree.is_none() {
270        stream.configure_default_rust_allocator()
271    }
272
273    #[cfg(feature = "c-allocator")]
274    if stream.zalloc.is_none() || stream.zfree.is_none() {
275        stream.configure_default_c_allocator()
276    }
277
278    if stream.zalloc.is_none() || stream.zfree.is_none() {
279        return ReturnCode::StreamError;
280    }
281
282    if level == crate::c_api::Z_DEFAULT_COMPRESSION {
283        level = 6;
284    }
285
286    let wrap = if window_bits < 0 {
287        if window_bits < -MAX_WBITS {
288            return ReturnCode::StreamError;
289        }
290        window_bits = -window_bits;
291
292        0
293    } else if window_bits > MAX_WBITS {
294        window_bits -= 16;
295        2
296    } else {
297        1
298    };
299
300    if (!(1..=MAX_MEM_LEVEL).contains(&mem_level))
301        || !(MIN_WBITS..=MAX_WBITS).contains(&window_bits)
302        || !(0..=9).contains(&level)
303        || (window_bits == 8 && wrap != 1)
304    {
305        return ReturnCode::StreamError;
306    }
307
308    let window_bits = if window_bits == 8 {
309        9 /* until 256-byte window bug fixed */
310    } else {
311        window_bits as usize
312    };
313
314    let alloc = Allocator {
315        zalloc: stream.zalloc.unwrap(),
316        zfree: stream.zfree.unwrap(),
317        opaque: stream.opaque,
318        _marker: PhantomData,
319    };
320
321    let lit_bufsize = 1 << (mem_level + 6); // 16K elements by default
322    let allocs = DeflateAllocOffsets::new(window_bits, lit_bufsize);
323
324    // FIXME: pointer methods on NonNull are stable since 1.80.0
325    let Some(allocation_start) = alloc.allocate_slice_raw::<u8>(allocs.total_size) else {
326        return ReturnCode::MemError;
327    };
328
329    let w_size = 1 << window_bits;
330    let align_offset = (allocation_start.as_ptr() as usize).next_multiple_of(64)
331        - (allocation_start.as_ptr() as usize);
332    let buf = unsafe { allocation_start.as_ptr().add(align_offset) };
333
334    let (window, prev, head, pending, sym_buf) = unsafe {
335        let window_ptr: *mut u8 = buf.add(allocs.window_pos);
336        window_ptr.write_bytes(0u8, 2 * w_size);
337        let window = Window::from_raw_parts(window_ptr, window_bits);
338
339        // FIXME: write_bytes is stable for NonNull since 1.80.0
340        let prev_ptr = buf.add(allocs.prev_pos).cast::<Pos>();
341        prev_ptr.write_bytes(0, w_size);
342        let prev = WeakSliceMut::from_raw_parts_mut(prev_ptr, w_size);
343
344        let head_ptr = buf.add(allocs.head_pos).cast::<[Pos; HASH_SIZE]>();
345        // Zero out the full array. `write_bytes` will write `1 * size_of<[Pos; HASH_SIZE]>` bytes.
346        head_ptr.write_bytes(0, 1);
347        let head = WeakArrayMut::<Pos, HASH_SIZE>::from_ptr(head_ptr);
348
349        let pending_ptr = buf.add(allocs.pending_pos).cast::<MaybeUninit<u8>>();
350        let pending = Pending::from_raw_parts(pending_ptr, 4 * lit_bufsize);
351
352        let sym_buf_ptr = buf.add(allocs.sym_buf_pos);
353        let sym_buf = SymBuf::from_raw_parts(sym_buf_ptr, lit_bufsize);
354
355        (window, prev, head, pending, sym_buf)
356    };
357
358    let state = State {
359        status: Status::Init,
360
361        // window
362        w_size,
363
364        // allocated values
365        window,
366        prev,
367        head,
368        bit_writer: BitWriter::from_pending(pending),
369
370        //
371        lit_bufsize,
372
373        //
374        sym_buf,
375
376        //
377        level: level as i8, // set to zero again for testing?
378        strategy,
379
380        // these fields are not set explicitly at this point
381        last_flush: 0,
382        wrap,
383        strstart: 0,
384        block_start: 0,
385        block_open: 0,
386        window_size: 0,
387        insert: 0,
388        matches: 0,
389        opt_len: 0,
390        static_len: 0,
391        lookahead: 0,
392        ins_h: 0,
393        max_chain_length: 0,
394        max_lazy_match: 0,
395        good_match: 0,
396        nice_match: 0,
397
398        //
399        l_desc: TreeDesc::EMPTY,
400        d_desc: TreeDesc::EMPTY,
401        bl_desc: TreeDesc::EMPTY,
402
403        //
404        crc_fold: Crc32Fold::new(),
405        gzhead: None,
406        gzindex: 0,
407
408        //
409        match_start: 0,
410        prev_match: 0,
411        match_available: false,
412        prev_length: 0,
413
414        allocation_start,
415        total_allocation_size: allocs.total_size,
416
417        // just provide a valid default; gets set properly later
418        hash_calc_variant: HashCalcVariant::Standard,
419        _cache_line_0: (),
420        _cache_line_1: (),
421        _cache_line_2: (),
422        _cache_line_3: (),
423        _padding_0: [0; 16],
424    };
425
426    let state_allocation = unsafe { buf.add(allocs.state_pos).cast::<State>() };
427    unsafe { state_allocation.write(state) };
428
429    stream.state = state_allocation.cast::<internal_state>();
430
431    let Some(stream) = (unsafe { DeflateStream::from_stream_mut(stream) }) else {
432        if cfg!(debug_assertions) {
433            unreachable!("we should have initialized the stream properly");
434        }
435        return ReturnCode::StreamError;
436    };
437
438    reset(stream)
439}
440
441pub fn params(stream: &mut DeflateStream, level: i32, strategy: Strategy) -> ReturnCode {
442    let level = if level == crate::c_api::Z_DEFAULT_COMPRESSION {
443        6
444    } else {
445        level
446    };
447
448    if !(0..=9).contains(&level) {
449        return ReturnCode::StreamError;
450    }
451
452    let level = level as i8;
453
454    let func = CONFIGURATION_TABLE[stream.state.level as usize].func;
455
456    let state = &mut stream.state;
457
458    // FIXME: use fn_addr_eq when it's available in our MSRV. The comparison returning false here
459    // is not functionally incorrect, but would be inconsistent with zlib-ng.
460    #[allow(unpredictable_function_pointer_comparisons)]
461    if (strategy != state.strategy || func != CONFIGURATION_TABLE[level as usize].func)
462        && state.last_flush != -2
463    {
464        // Flush the last buffer.
465        let err = deflate(stream, DeflateFlush::Block);
466        if err == ReturnCode::StreamError {
467            return err;
468        }
469
470        let state = &mut stream.state;
471
472        if stream.avail_in != 0
473            || ((state.strstart as isize - state.block_start) + state.lookahead as isize) != 0
474        {
475            return ReturnCode::BufError;
476        }
477    }
478
479    let state = &mut stream.state;
480
481    if state.level != level {
482        if state.level == 0 && state.matches != 0 {
483            if state.matches == 1 {
484                self::slide_hash::slide_hash(state);
485            } else {
486                state.head.as_mut_slice().fill(0);
487            }
488            state.matches = 0;
489        }
490
491        lm_set_level(state, level);
492    }
493
494    state.strategy = strategy;
495
496    ReturnCode::Ok
497}
498
499pub fn set_dictionary(stream: &mut DeflateStream, mut dictionary: &[u8]) -> ReturnCode {
500    let state = &mut stream.state;
501
502    let wrap = state.wrap;
503
504    if wrap == 2 || (wrap == 1 && state.status != Status::Init) || state.lookahead != 0 {
505        return ReturnCode::StreamError;
506    }
507
508    // when using zlib wrappers, compute Adler-32 for provided dictionary
509    if wrap == 1 {
510        stream.adler = adler32(stream.adler as u32, dictionary) as z_checksum;
511    }
512
513    // avoid computing Adler-32 in read_buf
514    state.wrap = 0;
515
516    // if dictionary would fill window, just replace the history
517    if dictionary.len() >= state.window.capacity() {
518        if wrap == 0 {
519            // clear the hash table
520            state.head.as_mut_slice().fill(0);
521
522            state.strstart = 0;
523            state.block_start = 0;
524            state.insert = 0;
525        } else {
526            /* already empty otherwise */
527        }
528
529        // use the tail
530        dictionary = &dictionary[dictionary.len() - state.w_size..];
531    }
532
533    // insert dictionary into window and hash
534    let avail = stream.avail_in;
535    let next = stream.next_in;
536    stream.avail_in = dictionary.len() as _;
537    stream.next_in = dictionary.as_ptr() as *mut u8;
538    fill_window(stream);
539
540    while stream.state.lookahead >= STD_MIN_MATCH {
541        let str = stream.state.strstart;
542        let n = stream.state.lookahead - (STD_MIN_MATCH - 1);
543        stream.state.insert_string(str, n);
544        stream.state.strstart = str + n;
545        stream.state.lookahead = STD_MIN_MATCH - 1;
546        fill_window(stream);
547    }
548
549    let state = &mut stream.state;
550
551    state.strstart += state.lookahead;
552    state.block_start = state.strstart as _;
553    state.insert = state.lookahead;
554    state.lookahead = 0;
555    state.prev_length = 0;
556    state.match_available = false;
557
558    // restore the state
559    stream.next_in = next;
560    stream.avail_in = avail;
561    state.wrap = wrap;
562
563    ReturnCode::Ok
564}
565
566pub fn prime(stream: &mut DeflateStream, mut bits: i32, value: i32) -> ReturnCode {
567    // our logic actually supports up to 32 bits.
568    debug_assert!(bits <= 16, "zlib only supports up to 16 bits here");
569
570    let mut value64 = value as u64;
571
572    let state = &mut stream.state;
573
574    if bits < 0
575        || bits > BitWriter::BIT_BUF_SIZE as i32
576        || bits > (core::mem::size_of_val(&value) << 3) as i32
577    {
578        return ReturnCode::BufError;
579    }
580
581    let mut put;
582
583    loop {
584        put = BitWriter::BIT_BUF_SIZE - state.bit_writer.bits_valid;
585        let put = Ord::min(put as i32, bits);
586
587        if state.bit_writer.bits_valid == 0 {
588            state.bit_writer.bit_buffer = value64;
589        } else {
590            state.bit_writer.bit_buffer |=
591                (value64 & ((1 << put) - 1)) << state.bit_writer.bits_valid;
592        }
593
594        state.bit_writer.bits_valid += put as u8;
595        state.bit_writer.flush_bits();
596        value64 >>= put;
597        bits -= put;
598
599        if bits == 0 {
600            break;
601        }
602    }
603
604    ReturnCode::Ok
605}
606
607pub fn copy<'a>(
608    dest: &mut MaybeUninit<DeflateStream<'a>>,
609    source: &mut DeflateStream<'a>,
610) -> ReturnCode {
611    let w_size = source.state.w_size;
612    let window_bits = source.state.w_bits() as usize;
613    let lit_bufsize = source.state.lit_bufsize;
614
615    // SAFETY: source and dest are both mutable references, so guaranteed not to overlap.
616    // dest being a reference to maybe uninitialized memory makes a copy of 1 DeflateStream valid.
617    unsafe { core::ptr::copy_nonoverlapping(source, dest.as_mut_ptr(), 1) };
618
619    let source_state = &source.state;
620    let alloc = &source.alloc;
621
622    let allocs = DeflateAllocOffsets::new(window_bits, lit_bufsize);
623
624    let Some(allocation_start) = alloc.allocate_slice_raw::<u8>(allocs.total_size) else {
625        return ReturnCode::MemError;
626    };
627
628    let align_offset = (allocation_start.as_ptr() as usize).next_multiple_of(64)
629        - (allocation_start.as_ptr() as usize);
630    let buf = unsafe { allocation_start.as_ptr().add(align_offset) };
631
632    let (window, prev, head, pending, sym_buf) = unsafe {
633        let window_ptr: *mut u8 = buf.add(allocs.window_pos);
634        window_ptr
635            .copy_from_nonoverlapping(source_state.window.as_ptr(), source_state.window.capacity());
636        let window = Window::from_raw_parts(window_ptr, window_bits);
637
638        // FIXME: write_bytes is stable for NonNull since 1.80.0
639        let prev_ptr = buf.add(allocs.prev_pos).cast::<Pos>();
640        prev_ptr.copy_from_nonoverlapping(source_state.prev.as_ptr(), source_state.prev.len());
641        let prev = WeakSliceMut::from_raw_parts_mut(prev_ptr, w_size);
642
643        // zero out head's first element
644        let head_ptr = buf.add(allocs.head_pos).cast::<[Pos; HASH_SIZE]>();
645        head_ptr.copy_from_nonoverlapping(source_state.head.as_ptr(), 1);
646        let head = WeakArrayMut::<Pos, HASH_SIZE>::from_ptr(head_ptr);
647
648        let pending_ptr = buf.add(allocs.pending_pos);
649        let pending = source_state.bit_writer.pending.clone_to(pending_ptr);
650
651        let sym_buf_ptr = buf.add(allocs.sym_buf_pos);
652        let sym_buf = source_state.sym_buf.clone_to(sym_buf_ptr);
653
654        (window, prev, head, pending, sym_buf)
655    };
656
657    let mut bit_writer = BitWriter::from_pending(pending);
658    bit_writer.bit_buffer = source_state.bit_writer.bit_buffer;
659    bit_writer.bits_valid = source_state.bit_writer.bits_valid;
660    bit_writer.bits_used = source_state.bit_writer.bits_used;
661
662    let dest_state = State {
663        status: source_state.status,
664        bit_writer,
665        last_flush: source_state.last_flush,
666        wrap: source_state.wrap,
667        strategy: source_state.strategy,
668        level: source_state.level,
669        good_match: source_state.good_match,
670        nice_match: source_state.nice_match,
671        l_desc: source_state.l_desc.clone(),
672        d_desc: source_state.d_desc.clone(),
673        bl_desc: source_state.bl_desc.clone(),
674        prev_match: source_state.prev_match,
675        match_available: source_state.match_available,
676        strstart: source_state.strstart,
677        match_start: source_state.match_start,
678        prev_length: source_state.prev_length,
679        max_chain_length: source_state.max_chain_length,
680        max_lazy_match: source_state.max_lazy_match,
681        block_start: source_state.block_start,
682        block_open: source_state.block_open,
683        window,
684        sym_buf,
685        lit_bufsize: source_state.lit_bufsize,
686        window_size: source_state.window_size,
687        matches: source_state.matches,
688        opt_len: source_state.opt_len,
689        static_len: source_state.static_len,
690        insert: source_state.insert,
691        w_size: source_state.w_size,
692        lookahead: source_state.lookahead,
693        prev,
694        head,
695        ins_h: source_state.ins_h,
696        hash_calc_variant: source_state.hash_calc_variant,
697        crc_fold: source_state.crc_fold,
698        gzhead: None,
699        gzindex: source_state.gzindex,
700        allocation_start,
701        total_allocation_size: allocs.total_size,
702        _cache_line_0: (),
703        _cache_line_1: (),
704        _cache_line_2: (),
705        _cache_line_3: (),
706        _padding_0: source_state._padding_0,
707    };
708
709    // write the cloned state into state_ptr
710    let state_allocation = unsafe { buf.add(allocs.state_pos).cast::<State>() };
711    unsafe { state_allocation.write(dest_state) }; // FIXME: write is stable for NonNull since 1.80.0
712
713    // insert the state_ptr into `dest`
714    let field_ptr = unsafe { core::ptr::addr_of_mut!((*dest.as_mut_ptr()).state) };
715    unsafe { core::ptr::write(field_ptr as *mut *mut State, state_allocation) };
716
717    // update the gzhead field (it contains a mutable reference so we need to be careful
718    let field_ptr = unsafe { core::ptr::addr_of_mut!((*dest.as_mut_ptr()).state.gzhead) };
719    unsafe { core::ptr::copy(&source_state.gzhead, field_ptr, 1) };
720
721    ReturnCode::Ok
722}
723
724/// # Returns
725///
726/// - Err when deflate is not done. A common cause is insufficient output space
727/// - Ok otherwise
728pub fn end<'a>(stream: &'a mut DeflateStream) -> Result<&'a mut z_stream, &'a mut z_stream> {
729    let status = stream.state.status;
730    let allocation_start = stream.state.allocation_start;
731    let total_allocation_size = stream.state.total_allocation_size;
732    let alloc = stream.alloc;
733
734    let stream = stream.as_z_stream_mut();
735    let _ = core::mem::replace(&mut stream.state, core::ptr::null_mut());
736
737    unsafe { alloc.deallocate(allocation_start.as_ptr(), total_allocation_size) };
738
739    match status {
740        Status::Busy => Err(stream),
741        _ => Ok(stream),
742    }
743}
744
745pub fn reset(stream: &mut DeflateStream) -> ReturnCode {
746    let ret = reset_keep(stream);
747
748    if ret == ReturnCode::Ok {
749        lm_init(stream.state);
750    }
751
752    ret
753}
754
755pub fn reset_keep(stream: &mut DeflateStream) -> ReturnCode {
756    stream.total_in = 0;
757    stream.total_out = 0;
758    stream.msg = core::ptr::null_mut();
759    stream.data_type = crate::c_api::Z_UNKNOWN;
760
761    let state = &mut stream.state;
762
763    state.bit_writer.pending.reset_keep();
764
765    // can be made negative by deflate(..., Z_FINISH);
766    state.wrap = state.wrap.abs();
767
768    state.status = match state.wrap {
769        2 => Status::GZip,
770        _ => Status::Init,
771    };
772
773    stream.adler = match state.wrap {
774        2 => {
775            state.crc_fold = Crc32Fold::new();
776            CRC32_INITIAL_VALUE as _
777        }
778        _ => ADLER32_INITIAL_VALUE as _,
779    };
780
781    state.last_flush = -2;
782
783    state.zng_tr_init();
784
785    ReturnCode::Ok
786}
787
788fn lm_init(state: &mut State) {
789    state.window_size = 2 * state.w_size;
790
791    // zlib uses CLEAR_HASH here
792    state.head.as_mut_slice().fill(0);
793
794    // Set the default configuration parameters:
795    lm_set_level(state, state.level);
796
797    state.strstart = 0;
798    state.block_start = 0;
799    state.lookahead = 0;
800    state.insert = 0;
801    state.prev_length = 0;
802    state.match_available = false;
803    state.match_start = 0;
804    state.ins_h = 0;
805}
806
807fn lm_set_level(state: &mut State, level: i8) {
808    state.max_lazy_match = CONFIGURATION_TABLE[level as usize].max_lazy;
809    state.good_match = CONFIGURATION_TABLE[level as usize].good_length;
810    state.nice_match = CONFIGURATION_TABLE[level as usize].nice_length;
811    state.max_chain_length = CONFIGURATION_TABLE[level as usize].max_chain;
812
813    state.hash_calc_variant = HashCalcVariant::for_max_chain_length(state.max_chain_length);
814    state.level = level;
815}
816
817pub fn tune(
818    stream: &mut DeflateStream,
819    good_length: usize,
820    max_lazy: usize,
821    nice_length: usize,
822    max_chain: usize,
823) -> ReturnCode {
824    stream.state.good_match = good_length as u16;
825    stream.state.max_lazy_match = max_lazy as u16;
826    stream.state.nice_match = nice_length as u16;
827    stream.state.max_chain_length = max_chain as u16;
828
829    ReturnCode::Ok
830}
831
832#[repr(C)]
833#[derive(Debug, Clone, Copy, PartialEq, Eq)]
834pub(crate) struct Value {
835    a: u16,
836    b: u16,
837}
838
839impl Value {
840    pub(crate) const fn new(a: u16, b: u16) -> Self {
841        Self { a, b }
842    }
843
844    pub(crate) fn freq_mut(&mut self) -> &mut u16 {
845        &mut self.a
846    }
847
848    pub(crate) fn code_mut(&mut self) -> &mut u16 {
849        &mut self.a
850    }
851
852    pub(crate) fn dad_mut(&mut self) -> &mut u16 {
853        &mut self.b
854    }
855
856    pub(crate) fn len_mut(&mut self) -> &mut u16 {
857        &mut self.b
858    }
859
860    #[inline(always)]
861    pub(crate) const fn freq(self) -> u16 {
862        self.a
863    }
864
865    #[inline(always)]
866    pub(crate) const fn code(self) -> u16 {
867        self.a
868    }
869
870    #[inline(always)]
871    pub(crate) const fn dad(self) -> u16 {
872        self.b
873    }
874
875    #[inline(always)]
876    pub(crate) const fn len(self) -> u16 {
877        self.b
878    }
879}
880
881/// number of length codes, not counting the special END_BLOCK code
882pub(crate) const LENGTH_CODES: usize = 29;
883
884/// number of literal bytes 0..255
885const LITERALS: usize = 256;
886
887/// number of Literal or Length codes, including the END_BLOCK code
888pub(crate) const L_CODES: usize = LITERALS + 1 + LENGTH_CODES;
889
890/// number of distance codes
891pub(crate) const D_CODES: usize = 30;
892
893/// number of codes used to transfer the bit lengths
894const BL_CODES: usize = 19;
895
896/// maximum heap size
897const HEAP_SIZE: usize = 2 * L_CODES + 1;
898
899/// all codes must not exceed MAX_BITS bits
900const MAX_BITS: usize = 15;
901
902/// Bit length codes must not exceed MAX_BL_BITS bits
903const MAX_BL_BITS: usize = 7;
904
905pub(crate) const DIST_CODE_LEN: usize = 512;
906
907struct BitWriter<'a> {
908    pub(crate) pending: Pending<'a>, // output still pending
909
910    /// Output buffer. bits are inserted starting at the bottom (least significant bits).
911    pub(crate) bit_buffer: u64,
912
913    /// Number of valid bits in bit_buffer. All bits above the last valid bit are always zero.
914    pub(crate) bits_valid: u8,
915
916    /// Last number of used bits when going to a byte boundary.
917    pub(crate) bits_used: u8,
918
919    /// total bit length of compressed file (NOTE: zlib-ng uses a 32-bit integer here)
920    #[cfg(feature = "ZLIB_DEBUG")]
921    compressed_len: usize,
922    /// bit length of compressed data sent (NOTE: zlib-ng uses a 32-bit integer here)
923    #[cfg(feature = "ZLIB_DEBUG")]
924    bits_sent: usize,
925}
926
927#[inline]
928const fn encode_len(ltree: &[Value], lc: u8) -> (u64, usize) {
929    let mut lc = lc as usize;
930
931    /* Send the length code, len is the match length - STD_MIN_MATCH */
932    let code = self::trees_tbl::LENGTH_CODE[lc] as usize;
933    let c = code + LITERALS + 1;
934    assert!(c < L_CODES, "bad l_code");
935    // send_code_trace(s, c);
936
937    let lnode = ltree[c];
938    let mut match_bits: u64 = lnode.code() as u64;
939    let mut match_bits_len = lnode.len() as usize;
940    let extra = StaticTreeDesc::EXTRA_LBITS[code] as usize;
941    if extra != 0 {
942        lc -= self::trees_tbl::BASE_LENGTH[code] as usize;
943        match_bits |= (lc as u64) << match_bits_len;
944        match_bits_len += extra;
945    }
946
947    (match_bits, match_bits_len)
948}
949
950#[inline]
951const fn encode_dist(dtree: &[Value], mut dist: u16) -> (u64, usize) {
952    dist -= 1; /* dist is now the match distance - 1 */
953    let code = State::d_code(dist as usize) as usize;
954    assert!(code < D_CODES, "bad d_code");
955    // send_code_trace(s, code);
956
957    /* Send the distance code */
958    let dnode = dtree[code];
959    let mut match_bits = dnode.code() as u64;
960    let mut match_bits_len = dnode.len() as usize;
961    let extra = StaticTreeDesc::EXTRA_DBITS[code] as usize;
962    if extra != 0 {
963        dist -= self::trees_tbl::BASE_DIST[code];
964        match_bits |= (dist as u64) << match_bits_len;
965        match_bits_len += extra;
966    }
967
968    (match_bits, match_bits_len)
969}
970
971impl<'a> BitWriter<'a> {
972    pub(crate) const BIT_BUF_SIZE: u8 = 64;
973
974    fn from_pending(pending: Pending<'a>) -> Self {
975        Self {
976            pending,
977            bit_buffer: 0,
978            bits_valid: 0,
979            bits_used: 0,
980
981            #[cfg(feature = "ZLIB_DEBUG")]
982            compressed_len: 0,
983            #[cfg(feature = "ZLIB_DEBUG")]
984            bits_sent: 0,
985        }
986    }
987
988    fn flush_bits(&mut self) {
989        debug_assert!(self.bits_valid <= 64);
990        let removed = self.bits_valid.saturating_sub(7).next_multiple_of(8);
991        let keep_bytes = self.bits_valid / 8; // can never divide by zero
992
993        let src = &self.bit_buffer.to_le_bytes();
994        self.pending.extend(&src[..keep_bytes as usize]);
995
996        self.bits_valid -= removed;
997        self.bit_buffer = self.bit_buffer.checked_shr(removed as u32).unwrap_or(0);
998    }
999
1000    fn emit_align(&mut self) {
1001        debug_assert!(self.bits_valid <= 64);
1002        let keep_bytes = self.bits_valid.div_ceil(8);
1003        let src = &self.bit_buffer.to_le_bytes();
1004        self.pending.extend(&src[..keep_bytes as usize]);
1005
1006        self.bits_used = match self.bits_valid {
1007            0 => 8,
1008            _ => ((self.bits_valid - 1) & 7) + 1,
1009        };
1010        self.bit_buffer = 0;
1011        self.bits_valid = 0;
1012
1013        self.sent_bits_align();
1014    }
1015
1016    fn send_bits_trace(&self, _value: u64, _len: u8) {
1017        trace!(" l {:>2} v {:>4x} ", _len, _value);
1018    }
1019
1020    fn cmpr_bits_add(&mut self, _len: usize) {
1021        #[cfg(feature = "ZLIB_DEBUG")]
1022        {
1023            self.compressed_len += _len;
1024        }
1025    }
1026
1027    fn cmpr_bits_align(&mut self) {
1028        #[cfg(feature = "ZLIB_DEBUG")]
1029        {
1030            self.compressed_len = self.compressed_len.next_multiple_of(8);
1031        }
1032    }
1033
1034    fn sent_bits_add(&mut self, _len: usize) {
1035        #[cfg(feature = "ZLIB_DEBUG")]
1036        {
1037            self.bits_sent += _len;
1038        }
1039    }
1040
1041    fn sent_bits_align(&mut self) {
1042        #[cfg(feature = "ZLIB_DEBUG")]
1043        {
1044            self.bits_sent = self.bits_sent.next_multiple_of(8);
1045        }
1046    }
1047
1048    #[inline(always)]
1049    fn send_bits(&mut self, val: u64, len: u8) {
1050        debug_assert!(len <= 64);
1051        debug_assert!(self.bits_valid <= 64);
1052
1053        let total_bits = len + self.bits_valid;
1054
1055        self.send_bits_trace(val, len);
1056        self.sent_bits_add(len as usize);
1057
1058        if total_bits < Self::BIT_BUF_SIZE {
1059            self.bit_buffer |= val << self.bits_valid;
1060            self.bits_valid = total_bits;
1061        } else {
1062            self.send_bits_overflow(val, total_bits);
1063        }
1064    }
1065
1066    fn send_bits_overflow(&mut self, val: u64, total_bits: u8) {
1067        if self.bits_valid == Self::BIT_BUF_SIZE {
1068            self.pending.extend(&self.bit_buffer.to_le_bytes());
1069            self.bit_buffer = val;
1070            self.bits_valid = total_bits - Self::BIT_BUF_SIZE;
1071        } else {
1072            self.bit_buffer |= val << self.bits_valid;
1073            self.pending.extend(&self.bit_buffer.to_le_bytes());
1074            self.bit_buffer = val >> (Self::BIT_BUF_SIZE - self.bits_valid);
1075            self.bits_valid = total_bits - Self::BIT_BUF_SIZE;
1076        }
1077    }
1078
1079    fn send_code(&mut self, code: usize, tree: &[Value]) {
1080        let node = tree[code];
1081        self.send_bits(node.code() as u64, node.len() as u8)
1082    }
1083
1084    /// Send one empty static block to give enough lookahead for inflate.
1085    /// This takes 10 bits, of which 7 may remain in the bit buffer.
1086    pub fn align(&mut self) {
1087        self.emit_tree(BlockType::StaticTrees, false);
1088        self.emit_end_block(&STATIC_LTREE, false);
1089        self.flush_bits();
1090    }
1091
1092    pub(crate) fn emit_tree(&mut self, block_type: BlockType, is_last_block: bool) {
1093        let header_bits = ((block_type as u64) << 1) | (is_last_block as u64);
1094        self.send_bits(header_bits, 3);
1095        trace!("\n--- Emit Tree: Last: {}\n", is_last_block as u8);
1096    }
1097
1098    pub(crate) fn emit_end_block_and_align(&mut self, ltree: &[Value], is_last_block: bool) {
1099        self.emit_end_block(ltree, is_last_block);
1100
1101        if is_last_block {
1102            self.emit_align();
1103        }
1104    }
1105
1106    fn emit_end_block(&mut self, ltree: &[Value], _is_last_block: bool) {
1107        const END_BLOCK: usize = 256;
1108        self.send_code(END_BLOCK, ltree);
1109
1110        trace!(
1111            "\n+++ Emit End Block: Last: {} Pending: {} Total Out: {}\n",
1112            _is_last_block as u8,
1113            self.pending.pending().len(),
1114            "<unknown>"
1115        );
1116    }
1117
1118    pub(crate) fn emit_lit(&mut self, ltree: &[Value], c: u8) -> u16 {
1119        self.send_code(c as usize, ltree);
1120
1121        #[cfg(feature = "ZLIB_DEBUG")]
1122        if let Some(c) = char::from_u32(c as u32) {
1123            if isgraph(c as u8) {
1124                trace!(" '{}' ", c);
1125            }
1126        }
1127
1128        ltree[c as usize].len()
1129    }
1130
1131    pub(crate) fn emit_dist(
1132        &mut self,
1133        ltree: &[Value],
1134        dtree: &[Value],
1135        lc: u8,
1136        dist: u16,
1137    ) -> usize {
1138        let (mut match_bits, mut match_bits_len) = encode_len(ltree, lc);
1139
1140        let (dist_match_bits, dist_match_bits_len) = encode_dist(dtree, dist);
1141
1142        match_bits |= dist_match_bits << match_bits_len;
1143        match_bits_len += dist_match_bits_len;
1144
1145        self.send_bits(match_bits, match_bits_len as u8);
1146
1147        match_bits_len
1148    }
1149
1150    pub(crate) fn emit_dist_static(&mut self, lc: u8, dist: u16) -> usize {
1151        let precomputed_len = trees_tbl::STATIC_LTREE_ENCODINGS[lc as usize];
1152        let mut match_bits = precomputed_len.code() as u64;
1153        let mut match_bits_len = precomputed_len.len() as usize;
1154
1155        let dtree = self::trees_tbl::STATIC_DTREE.as_slice();
1156        let (dist_match_bits, dist_match_bits_len) = encode_dist(dtree, dist);
1157
1158        match_bits |= dist_match_bits << match_bits_len;
1159        match_bits_len += dist_match_bits_len;
1160
1161        self.send_bits(match_bits, match_bits_len as u8);
1162
1163        match_bits_len
1164    }
1165
1166    fn compress_block_help(&mut self, sym_buf: &SymBuf, ltree: &[Value], dtree: &[Value]) {
1167        for (dist, lc) in sym_buf.iter() {
1168            match dist {
1169                0 => self.emit_lit(ltree, lc) as usize,
1170                _ => self.emit_dist(ltree, dtree, lc, dist),
1171            };
1172        }
1173
1174        self.emit_end_block(ltree, false)
1175    }
1176
1177    fn send_tree(&mut self, tree: &[Value], bl_tree: &[Value], max_code: usize) {
1178        /* tree: the tree to be scanned */
1179        /* max_code and its largest code of non zero frequency */
1180        let mut prevlen: isize = -1; /* last emitted length */
1181        let mut curlen; /* length of current code */
1182        let mut nextlen = tree[0].len(); /* length of next code */
1183        let mut count = 0; /* repeat count of the current code */
1184        let mut max_count = 7; /* max repeat count */
1185        let mut min_count = 4; /* min repeat count */
1186
1187        /* tree[max_code+1].Len = -1; */
1188        /* guard already set */
1189        if nextlen == 0 {
1190            max_count = 138;
1191            min_count = 3;
1192        }
1193
1194        for n in 0..=max_code {
1195            curlen = nextlen;
1196            nextlen = tree[n + 1].len();
1197            count += 1;
1198            if count < max_count && curlen == nextlen {
1199                continue;
1200            } else if count < min_count {
1201                loop {
1202                    self.send_code(curlen as usize, bl_tree);
1203
1204                    count -= 1;
1205                    if count == 0 {
1206                        break;
1207                    }
1208                }
1209            } else if curlen != 0 {
1210                if curlen as isize != prevlen {
1211                    self.send_code(curlen as usize, bl_tree);
1212                    count -= 1;
1213                }
1214                assert!((3..=6).contains(&count), " 3_6?");
1215                self.send_code(REP_3_6, bl_tree);
1216                self.send_bits(count - 3, 2);
1217            } else if count <= 10 {
1218                self.send_code(REPZ_3_10, bl_tree);
1219                self.send_bits(count - 3, 3);
1220            } else {
1221                self.send_code(REPZ_11_138, bl_tree);
1222                self.send_bits(count - 11, 7);
1223            }
1224
1225            count = 0;
1226            prevlen = curlen as isize;
1227
1228            if nextlen == 0 {
1229                max_count = 138;
1230                min_count = 3;
1231            } else if curlen == nextlen {
1232                max_count = 6;
1233                min_count = 3;
1234            } else {
1235                max_count = 7;
1236                min_count = 4;
1237            }
1238        }
1239    }
1240}
1241
1242#[repr(C, align(64))]
1243pub(crate) struct State<'a> {
1244    status: Status,
1245
1246    last_flush: i8, /* value of flush param for previous deflate call */
1247
1248    pub(crate) wrap: i8, /* bit 0 true for zlib, bit 1 true for gzip */
1249
1250    pub(crate) strategy: Strategy,
1251    pub(crate) level: i8,
1252
1253    /// Whether or not a block is currently open for the QUICK deflation scheme.
1254    /// 0 if the block is closed, 1 if there is an active block, or 2 if there
1255    /// is an active block and it is the last block.
1256    pub(crate) block_open: u8,
1257
1258    pub(crate) hash_calc_variant: HashCalcVariant,
1259
1260    pub(crate) match_available: bool, /* set if previous match exists */
1261
1262    /// Use a faster search when the previous match is longer than this
1263    pub(crate) good_match: u16,
1264
1265    /// Stop searching when current match exceeds this
1266    pub(crate) nice_match: u16,
1267
1268    pub(crate) match_start: Pos, /* start of matching string */
1269    pub(crate) prev_match: Pos,  /* previous match */
1270    pub(crate) strstart: usize,  /* start of string to insert */
1271
1272    pub(crate) window: Window<'a>,
1273    pub(crate) w_size: usize, /* LZ77 window size (32K by default) */
1274
1275    pub(crate) lookahead: usize, /* number of valid bytes ahead in window */
1276
1277    _cache_line_0: (),
1278
1279    /// prev[N], where N is an offset in the current window, contains the offset in the window
1280    /// of the previous 4-byte sequence that hashes to the same value as the 4-byte sequence
1281    /// starting at N. Together with head, prev forms a chained hash table that can be used
1282    /// to find earlier strings in the window that are potential matches for new input being
1283    /// deflated.
1284    pub(crate) prev: WeakSliceMut<'a, u16>,
1285    /// head[H] contains the offset of the last 4-character sequence seen so far in
1286    /// the current window that hashes to H (as calculated using the hash_calc_variant).
1287    pub(crate) head: WeakArrayMut<'a, u16, HASH_SIZE>,
1288
1289    /// Length of the best match at previous step. Matches not greater than this
1290    /// are discarded. This is used in the lazy match evaluation.
1291    pub(crate) prev_length: u16,
1292
1293    /// To speed up deflation, hash chains are never searched beyond this length.
1294    /// A higher limit improves compression ratio but degrades the speed.
1295    pub(crate) max_chain_length: u16,
1296
1297    // TODO untangle this mess! zlib uses the same field differently based on compression level
1298    // we should just have 2 fields for clarity!
1299    //
1300    // Insert new strings in the hash table only if the match length is not
1301    // greater than this length. This saves time but degrades compression.
1302    // max_insert_length is used only for compression levels <= 6.
1303    // define max_insert_length  max_lazy_match
1304    /// Attempt to find a better match only when the current match is strictly smaller
1305    /// than this value. This mechanism is used only for compression levels >= 4.
1306    pub(crate) max_lazy_match: u16,
1307
1308    /// number of string matches in current block
1309    /// NOTE: this is a saturating 8-bit counter, to help keep the struct compact. The code that
1310    /// makes decisions based on this field only cares whether the count is greater than 2, so
1311    /// an 8-bit counter is sufficient.
1312    pub(crate) matches: u8,
1313
1314    /// Window position at the beginning of the current output block. Gets
1315    /// negative when the window is moved backwards.
1316    pub(crate) block_start: isize,
1317
1318    pub(crate) sym_buf: SymBuf<'a>,
1319
1320    _cache_line_1: (),
1321
1322    /// Size of match buffer for literals/lengths.  There are 4 reasons for
1323    /// limiting lit_bufsize to 64K:
1324    ///   - frequencies can be kept in 16 bit counters
1325    ///   - if compression is not successful for the first block, all input
1326    ///     data is still in the window so we can still emit a stored block even
1327    ///     when input comes from standard input.  (This can also be done for
1328    ///     all blocks if lit_bufsize is not greater than 32K.)
1329    ///   - if compression is not successful for a file smaller than 64K, we can
1330    ///     even emit a stored file instead of a stored block (saving 5 bytes).
1331    ///     This is applicable only for zip (not gzip or zlib).
1332    ///   - creating new Huffman trees less frequently may not provide fast
1333    ///     adaptation to changes in the input data statistics. (Take for
1334    ///     example a binary file with poorly compressible code followed by
1335    ///     a highly compressible string table.) Smaller buffer sizes give
1336    ///     fast adaptation but have of course the overhead of transmitting
1337    ///     trees more frequently.
1338    ///   - I can't count above 4
1339    lit_bufsize: usize,
1340
1341    /// Actual size of window: 2*w_size, except when the user input buffer is directly used as sliding window.
1342    pub(crate) window_size: usize,
1343
1344    bit_writer: BitWriter<'a>,
1345
1346    _cache_line_2: (),
1347
1348    /// bit length of current block with optimal trees
1349    opt_len: usize,
1350    /// bit length of current block with static trees
1351    static_len: usize,
1352
1353    /// bytes at end of window left to insert
1354    pub(crate) insert: usize,
1355
1356    ///  hash index of string to be inserted
1357    pub(crate) ins_h: u32,
1358
1359    gzhead: Option<&'a mut gz_header>,
1360    gzindex: usize,
1361
1362    _padding_0: [u8; 16],
1363
1364    _cache_line_3: (),
1365
1366    crc_fold: crate::crc32::Crc32Fold,
1367
1368    /// The (unaligned) address of the state allocation that can be passed to zfree.
1369    allocation_start: NonNull<u8>,
1370    /// Total size of the allocation in bytes.
1371    total_allocation_size: usize,
1372
1373    l_desc: TreeDesc<HEAP_SIZE>,             /* literal and length tree */
1374    d_desc: TreeDesc<{ 2 * D_CODES + 1 }>,   /* distance tree */
1375    bl_desc: TreeDesc<{ 2 * BL_CODES + 1 }>, /* Huffman tree for bit lengths */
1376}
1377
1378#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Default)]
1379#[cfg_attr(feature = "__internal-fuzz", derive(arbitrary::Arbitrary))]
1380pub enum Strategy {
1381    #[default]
1382    Default = 0,
1383    Filtered = 1,
1384    HuffmanOnly = 2,
1385    Rle = 3,
1386    Fixed = 4,
1387}
1388
1389impl TryFrom<i32> for Strategy {
1390    type Error = ();
1391
1392    fn try_from(value: i32) -> Result<Self, Self::Error> {
1393        match value {
1394            0 => Ok(Strategy::Default),
1395            1 => Ok(Strategy::Filtered),
1396            2 => Ok(Strategy::HuffmanOnly),
1397            3 => Ok(Strategy::Rle),
1398            4 => Ok(Strategy::Fixed),
1399            _ => Err(()),
1400        }
1401    }
1402}
1403
1404#[derive(Debug, PartialEq, Eq)]
1405enum DataType {
1406    Binary = 0,
1407    Text = 1,
1408    Unknown = 2,
1409}
1410
1411impl<'a> State<'a> {
1412    pub const BIT_BUF_SIZE: u8 = BitWriter::BIT_BUF_SIZE;
1413
1414    // log2(w_size)  (in the range MIN_WBITS..=MAX_WBITS)
1415    pub(crate) fn w_bits(&self) -> u32 {
1416        self.w_size.trailing_zeros()
1417    }
1418
1419    pub(crate) fn w_mask(&self) -> usize {
1420        self.w_size - 1
1421    }
1422
1423    pub(crate) fn max_dist(&self) -> usize {
1424        self.w_size - MIN_LOOKAHEAD
1425    }
1426
1427    // TODO untangle this mess! zlib uses the same field differently based on compression level
1428    // we should just have 2 fields for clarity!
1429    pub(crate) fn max_insert_length(&self) -> usize {
1430        self.max_lazy_match as usize
1431    }
1432
1433    /// Total size of the pending buf. But because `pending` shares memory with `sym_buf`, this is
1434    /// not the number of bytes that are actually in `pending`!
1435    pub(crate) fn pending_buf_size(&self) -> usize {
1436        self.lit_bufsize * 4
1437    }
1438
1439    #[inline(always)]
1440    pub(crate) fn update_hash(&self, h: u32, val: u32) -> u32 {
1441        match self.hash_calc_variant {
1442            HashCalcVariant::Standard => StandardHashCalc::update_hash(h, val),
1443            HashCalcVariant::Roll => RollHashCalc::update_hash(h, val),
1444        }
1445    }
1446
1447    #[inline(always)]
1448    pub(crate) fn quick_insert_string(&mut self, string: usize) -> u16 {
1449        match self.hash_calc_variant {
1450            HashCalcVariant::Standard => StandardHashCalc::quick_insert_string(self, string),
1451            HashCalcVariant::Roll => RollHashCalc::quick_insert_string(self, string),
1452        }
1453    }
1454
1455    #[inline(always)]
1456    pub(crate) fn insert_string(&mut self, string: usize, count: usize) {
1457        match self.hash_calc_variant {
1458            HashCalcVariant::Standard => StandardHashCalc::insert_string(self, string, count),
1459            HashCalcVariant::Roll => RollHashCalc::insert_string(self, string, count),
1460        }
1461    }
1462
1463    #[inline(always)]
1464    pub(crate) fn tally_lit(&mut self, unmatched: u8) -> bool {
1465        Self::tally_lit_help(&mut self.sym_buf, &mut self.l_desc, unmatched)
1466    }
1467
1468    // This helper is to work around an ownership issue in algorithm/medium.
1469    pub(crate) fn tally_lit_help(
1470        sym_buf: &mut SymBuf,
1471        l_desc: &mut TreeDesc<HEAP_SIZE>,
1472        unmatched: u8,
1473    ) -> bool {
1474        const _VERIFY: () = {
1475            // Verify during compilation that even the largest possible value
1476            // of unmatched will fit within the expected range.
1477            assert!(
1478                u8::MAX as usize <= STD_MAX_MATCH - STD_MIN_MATCH,
1479                "tally_lit: bad literal"
1480            );
1481        };
1482
1483        sym_buf.push_lit(unmatched);
1484
1485        *l_desc.dyn_tree[unmatched as usize].freq_mut() += 1;
1486
1487        // signal that the current block should be flushed
1488        sym_buf.should_flush_block()
1489    }
1490
1491    const fn d_code(dist: usize) -> u8 {
1492        const _VERIFY: () = {
1493            // Verify during compilation that every DIST_CODE value is < D_CODES.
1494            let mut i = 0;
1495            while i < trees_tbl::DIST_CODE.len() {
1496                assert!(trees_tbl::DIST_CODE[i] < D_CODES as u8);
1497                i += 1;
1498            }
1499        };
1500
1501        let index = if dist < 256 { dist } else { 256 + (dist >> 7) };
1502        self::trees_tbl::DIST_CODE[index]
1503    }
1504
1505    #[inline(always)]
1506    pub(crate) fn tally_dist(&mut self, mut dist: usize, len: usize) -> bool {
1507        self.sym_buf.push_dist(dist as u16, len as u8);
1508
1509        self.matches = self.matches.saturating_add(1);
1510        dist -= 1;
1511
1512        assert!(dist < self.max_dist(), "tally_dist: bad match");
1513
1514        let index = self::trees_tbl::LENGTH_CODE[len] as usize + LITERALS + 1;
1515        *self.l_desc.dyn_tree[index].freq_mut() += 1;
1516
1517        *self.d_desc.dyn_tree[Self::d_code(dist) as usize].freq_mut() += 1;
1518
1519        // signal that the current block should be flushed
1520        self.sym_buf.should_flush_block()
1521    }
1522
1523    fn detect_data_type(dyn_tree: &[Value]) -> DataType {
1524        // set bits 0..6, 14..25, and 28..31
1525        // 0xf3ffc07f = binary 11110011111111111100000001111111
1526        const NON_TEXT: u64 = 0xf3ffc07f;
1527        let mut mask = NON_TEXT;
1528
1529        /* Check for non-textual bytes. */
1530        for value in &dyn_tree[0..32] {
1531            if (mask & 1) != 0 && value.freq() != 0 {
1532                return DataType::Binary;
1533            }
1534
1535            mask >>= 1;
1536        }
1537
1538        /* Check for textual bytes. */
1539        if dyn_tree[9].freq() != 0 || dyn_tree[10].freq() != 0 || dyn_tree[13].freq() != 0 {
1540            return DataType::Text;
1541        }
1542
1543        if dyn_tree[32..LITERALS].iter().any(|v| v.freq() != 0) {
1544            return DataType::Text;
1545        }
1546
1547        // there are no explicit text or non-text bytes. The stream is either empty or has only
1548        // tolerated bytes
1549        DataType::Binary
1550    }
1551
1552    fn compress_block_static_trees(&mut self) {
1553        let ltree = self::trees_tbl::STATIC_LTREE.as_slice();
1554        for (dist, lc) in self.sym_buf.iter() {
1555            match dist {
1556                0 => self.bit_writer.emit_lit(ltree, lc) as usize,
1557                _ => self.bit_writer.emit_dist_static(lc, dist),
1558            };
1559        }
1560
1561        self.bit_writer.emit_end_block(ltree, false)
1562    }
1563
1564    fn compress_block_dynamic_trees(&mut self) {
1565        self.bit_writer.compress_block_help(
1566            &self.sym_buf,
1567            &self.l_desc.dyn_tree,
1568            &self.d_desc.dyn_tree,
1569        );
1570    }
1571
1572    fn header(&self) -> u16 {
1573        // preset dictionary flag in zlib header
1574        const PRESET_DICT: u16 = 0x20;
1575
1576        // The deflate compression method (the only one supported in this version)
1577        const Z_DEFLATED: u16 = 8;
1578
1579        let dict = match self.strstart {
1580            0 => 0,
1581            _ => PRESET_DICT,
1582        };
1583
1584        let h = ((Z_DEFLATED + ((self.w_bits() as u16 - 8) << 4)) << 8)
1585            | (self.level_flags() << 6)
1586            | dict;
1587
1588        h + 31 - (h % 31)
1589    }
1590
1591    fn level_flags(&self) -> u16 {
1592        if self.strategy >= Strategy::HuffmanOnly || self.level < 2 {
1593            0
1594        } else if self.level < 6 {
1595            1
1596        } else if self.level == 6 {
1597            2
1598        } else {
1599            3
1600        }
1601    }
1602
1603    fn zng_tr_init(&mut self) {
1604        self.l_desc.stat_desc = &StaticTreeDesc::L;
1605
1606        self.d_desc.stat_desc = &StaticTreeDesc::D;
1607
1608        self.bl_desc.stat_desc = &StaticTreeDesc::BL;
1609
1610        self.bit_writer.bit_buffer = 0;
1611        self.bit_writer.bits_valid = 0;
1612        self.bit_writer.bits_used = 0;
1613
1614        #[cfg(feature = "ZLIB_DEBUG")]
1615        {
1616            self.bit_writer.compressed_len = 0;
1617            self.bit_writer.bits_sent = 0;
1618        }
1619
1620        // Initialize the first block of the first file:
1621        self.init_block();
1622    }
1623
1624    /// initializes a new block
1625    fn init_block(&mut self) {
1626        // Initialize the trees.
1627        // TODO would a memset also work here?
1628
1629        for value in &mut self.l_desc.dyn_tree[..L_CODES] {
1630            *value.freq_mut() = 0;
1631        }
1632
1633        for value in &mut self.d_desc.dyn_tree[..D_CODES] {
1634            *value.freq_mut() = 0;
1635        }
1636
1637        for value in &mut self.bl_desc.dyn_tree[..BL_CODES] {
1638            *value.freq_mut() = 0;
1639        }
1640
1641        // end of block literal code
1642        const END_BLOCK: usize = 256;
1643
1644        *self.l_desc.dyn_tree[END_BLOCK].freq_mut() = 1;
1645        self.opt_len = 0;
1646        self.static_len = 0;
1647        self.sym_buf.clear();
1648        self.matches = 0;
1649    }
1650}
1651
1652#[repr(u8)]
1653#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1654enum Status {
1655    Init = 1,
1656
1657    GZip = 4,
1658    Extra = 5,
1659    Name = 6,
1660    Comment = 7,
1661    Hcrc = 8,
1662
1663    Busy = 2,
1664    Finish = 3,
1665}
1666
1667const fn rank_flush(f: i8) -> i8 {
1668    // rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH
1669    ((f) * 2) - (if (f) > 4 { 9 } else { 0 })
1670}
1671
1672#[derive(Debug)]
1673pub(crate) enum BlockState {
1674    /// block not completed, need more input or more output
1675    NeedMore = 0,
1676    /// block flush performed
1677    BlockDone = 1,
1678    /// finish started, need only more output at next deflate
1679    FinishStarted = 2,
1680    /// finish done, accept no more input or output
1681    FinishDone = 3,
1682}
1683
1684// Maximum stored block length in deflate format (not including header).
1685pub(crate) const MAX_STORED: usize = 65535; // so u16::max
1686
1687pub(crate) fn read_buf_window(stream: &mut DeflateStream, offset: usize, size: usize) -> usize {
1688    let len = Ord::min(stream.avail_in as usize, size);
1689
1690    if len == 0 {
1691        return 0;
1692    }
1693
1694    stream.avail_in -= len as u32;
1695
1696    if stream.state.wrap == 2 {
1697        // we likely cannot fuse the crc32 and the copy here because the input can be changed by
1698        // a concurrent thread. Therefore it cannot be converted into a slice!
1699        let window = &mut stream.state.window;
1700        // SAFETY: len is bounded by avail_in, so this copy is in bounds.
1701        unsafe { window.copy_and_initialize(offset..offset + len, stream.next_in) };
1702
1703        let data = &stream.state.window.filled()[offset..][..len];
1704        stream.state.crc_fold.fold(data, CRC32_INITIAL_VALUE);
1705    } else if stream.state.wrap == 1 {
1706        // we likely cannot fuse the adler32 and the copy here because the input can be changed by
1707        // a concurrent thread. Therefore it cannot be converted into a slice!
1708        let window = &mut stream.state.window;
1709        // SAFETY: len is bounded by avail_in, so this copy is in bounds.
1710        unsafe { window.copy_and_initialize(offset..offset + len, stream.next_in) };
1711
1712        let data = &stream.state.window.filled()[offset..][..len];
1713        stream.adler = adler32(stream.adler as u32, data) as _;
1714    } else {
1715        let window = &mut stream.state.window;
1716        // SAFETY: len is bounded by avail_in, so this copy is in bounds.
1717        unsafe { window.copy_and_initialize(offset..offset + len, stream.next_in) };
1718    }
1719
1720    // These can overflow, especially on windows where the integer type is u32 and input/output are
1721    // larger than 4GB.
1722    stream.next_in = stream.next_in.wrapping_add(len);
1723    stream.total_in = stream.total_in.wrapping_add(len as crate::c_api::z_size);
1724
1725    len
1726}
1727
1728pub(crate) enum BlockType {
1729    StoredBlock = 0,
1730    StaticTrees = 1,
1731    DynamicTrees = 2,
1732}
1733
1734pub(crate) fn zng_tr_stored_block(
1735    state: &mut State,
1736    window_range: core::ops::Range<usize>,
1737    is_last: bool,
1738) {
1739    // send block type
1740    state.bit_writer.emit_tree(BlockType::StoredBlock, is_last);
1741
1742    // align on byte boundary
1743    state.bit_writer.emit_align();
1744
1745    state.bit_writer.cmpr_bits_align();
1746
1747    let input_block: &[u8] = &state.window.filled()[window_range];
1748    let stored_len = input_block.len() as u16;
1749
1750    state.bit_writer.pending.extend(&stored_len.to_le_bytes());
1751    state
1752        .bit_writer
1753        .pending
1754        .extend(&(!stored_len).to_le_bytes());
1755
1756    state.bit_writer.cmpr_bits_add(32);
1757    state.bit_writer.sent_bits_add(32);
1758    if stored_len > 0 {
1759        state.bit_writer.pending.extend(input_block);
1760        state.bit_writer.cmpr_bits_add((stored_len << 3) as usize);
1761        state.bit_writer.sent_bits_add((stored_len << 3) as usize);
1762    }
1763}
1764
1765/// The minimum match length mandated by the deflate standard
1766pub(crate) const STD_MIN_MATCH: usize = 3;
1767/// The maximum match length mandated by the deflate standard
1768pub(crate) const STD_MAX_MATCH: usize = 258;
1769
1770/// The minimum wanted match length, affects deflate_quick, deflate_fast, deflate_medium and deflate_slow
1771pub(crate) const WANT_MIN_MATCH: usize = 4;
1772
1773pub(crate) const MIN_LOOKAHEAD: usize = STD_MAX_MATCH + STD_MIN_MATCH + 1;
1774
1775#[inline]
1776pub(crate) fn fill_window(stream: &mut DeflateStream) {
1777    debug_assert!(stream.state.lookahead < MIN_LOOKAHEAD);
1778
1779    let wsize = stream.state.w_size;
1780
1781    loop {
1782        let state = &mut *stream.state;
1783        let mut more = state.window_size - state.lookahead - state.strstart;
1784
1785        // If the window is almost full and there is insufficient lookahead,
1786        // move the upper half to the lower one to make room in the upper half.
1787        if state.strstart >= wsize + state.max_dist() {
1788            // shift the window to the left
1789            let (old, new) = state.window.filled_mut()[..2 * wsize].split_at_mut(wsize);
1790            old.copy_from_slice(new);
1791
1792            if state.match_start >= wsize as u16 {
1793                state.match_start -= wsize as u16;
1794            } else {
1795                state.match_start = 0;
1796                state.prev_length = 0;
1797            }
1798
1799            state.strstart -= wsize; /* we now have strstart >= MAX_DIST */
1800            state.block_start = state.block_start.wrapping_sub_unsigned(wsize);
1801            state.insert = Ord::min(state.insert, state.strstart);
1802
1803            self::slide_hash::slide_hash(state);
1804
1805            more += wsize;
1806        }
1807
1808        if stream.avail_in == 0 {
1809            break;
1810        }
1811
1812        // If there was no sliding:
1813        //    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
1814        //    more == window_size - lookahead - strstart
1815        // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
1816        // => more >= window_size - 2*WSIZE + 2
1817        // In the BIG_MEM or MMAP case (not yet supported),
1818        //   window_size == input_size + MIN_LOOKAHEAD  &&
1819        //   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
1820        // Otherwise, window_size == 2*WSIZE so more >= 2.
1821        // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
1822        assert!(more >= 2, "more < 2");
1823
1824        let n = read_buf_window(stream, stream.state.strstart + stream.state.lookahead, more);
1825
1826        let state = &mut *stream.state;
1827        state.lookahead += n;
1828
1829        // Initialize the hash value now that we have some input:
1830        if state.lookahead + state.insert >= STD_MIN_MATCH {
1831            let string = state.strstart - state.insert;
1832            if state.max_chain_length > 1024 {
1833                let v0 = state.window.filled()[string] as u32;
1834                let v1 = state.window.filled()[string + 1] as u32;
1835                state.ins_h = state.update_hash(v0, v1);
1836            } else if string >= 1 {
1837                state.quick_insert_string(string + 2 - STD_MIN_MATCH);
1838            }
1839            let mut count = state.insert;
1840            if state.lookahead == 1 {
1841                count -= 1;
1842            }
1843            if count > 0 {
1844                state.insert_string(string, count);
1845                state.insert -= count;
1846            }
1847        }
1848
1849        // If the whole input has less than STD_MIN_MATCH bytes, ins_h is garbage,
1850        // but this is not important since only literal bytes will be emitted.
1851
1852        if !(stream.state.lookahead < MIN_LOOKAHEAD && stream.avail_in != 0) {
1853            break;
1854        }
1855    }
1856
1857    assert!(
1858        stream.state.strstart <= stream.state.window_size - MIN_LOOKAHEAD,
1859        "not enough room for search"
1860    );
1861}
1862
1863pub(crate) struct StaticTreeDesc {
1864    /// static tree or NULL
1865    pub(crate) static_tree: &'static [Value],
1866    /// extra bits for each code or NULL
1867    extra_bits: &'static [u8],
1868    /// base index for extra_bits
1869    extra_base: usize,
1870    /// max number of elements in the tree
1871    elems: usize,
1872    /// max bit length for the codes
1873    max_length: u16,
1874}
1875
1876impl StaticTreeDesc {
1877    const EMPTY: Self = Self {
1878        static_tree: &[],
1879        extra_bits: &[],
1880        extra_base: 0,
1881        elems: 0,
1882        max_length: 0,
1883    };
1884
1885    /// extra bits for each length code
1886    const EXTRA_LBITS: [u8; LENGTH_CODES] = [
1887        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
1888    ];
1889
1890    /// extra bits for each distance code
1891    const EXTRA_DBITS: [u8; D_CODES] = [
1892        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12,
1893        13, 13,
1894    ];
1895
1896    /// extra bits for each bit length code
1897    const EXTRA_BLBITS: [u8; BL_CODES] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7];
1898
1899    /// The lengths of the bit length codes are sent in order of decreasing
1900    /// probability, to avoid transmitting the lengths for unused bit length codes.
1901    const BL_ORDER: [u8; BL_CODES] = [
1902        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
1903    ];
1904
1905    pub(crate) const L: Self = Self {
1906        static_tree: &self::trees_tbl::STATIC_LTREE,
1907        extra_bits: &Self::EXTRA_LBITS,
1908        extra_base: LITERALS + 1,
1909        elems: L_CODES,
1910        max_length: MAX_BITS as u16,
1911    };
1912
1913    pub(crate) const D: Self = Self {
1914        static_tree: &self::trees_tbl::STATIC_DTREE,
1915        extra_bits: &Self::EXTRA_DBITS,
1916        extra_base: 0,
1917        elems: D_CODES,
1918        max_length: MAX_BITS as u16,
1919    };
1920
1921    pub(crate) const BL: Self = Self {
1922        static_tree: &[],
1923        extra_bits: &Self::EXTRA_BLBITS,
1924        extra_base: 0,
1925        elems: BL_CODES,
1926        max_length: MAX_BL_BITS as u16,
1927    };
1928}
1929
1930#[derive(Clone)]
1931pub(crate) struct TreeDesc<const N: usize> {
1932    dyn_tree: [Value; N],
1933    max_code: usize,
1934    stat_desc: &'static StaticTreeDesc,
1935}
1936
1937impl<const N: usize> TreeDesc<N> {
1938    const EMPTY: Self = Self {
1939        dyn_tree: [Value::new(0, 0); N],
1940        max_code: 0,
1941        stat_desc: &StaticTreeDesc::EMPTY,
1942    };
1943}
1944
1945fn build_tree<const N: usize>(state: &mut State, desc: &mut TreeDesc<N>) {
1946    let tree = &mut desc.dyn_tree;
1947    let stree = desc.stat_desc.static_tree;
1948    let elements = desc.stat_desc.elems;
1949
1950    let mut heap = Heap::new();
1951    let mut max_code = heap.initialize(&mut tree[..elements]);
1952
1953    // The pkzip format requires that at least one distance code exists,
1954    // and that at least one bit should be sent even if there is only one
1955    // possible code. So to avoid special checks later on we force at least
1956    // two codes of non zero frequency.
1957    while heap.heap_len < 2 {
1958        heap.heap_len += 1;
1959        let node = if max_code < 2 {
1960            max_code += 1;
1961            max_code
1962        } else {
1963            0
1964        };
1965
1966        debug_assert!(node >= 0);
1967        let node = node as usize;
1968
1969        heap.heap[heap.heap_len] = node as u32;
1970        *tree[node].freq_mut() = 1;
1971        heap.depth[node] = 0;
1972        state.opt_len -= 1;
1973        if !stree.is_empty() {
1974            state.static_len -= stree[node].len() as usize;
1975        }
1976        /* node is 0 or 1 so it does not have extra bits */
1977    }
1978
1979    debug_assert!(max_code >= 0);
1980    let max_code = max_code as usize;
1981    desc.max_code = max_code;
1982
1983    // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
1984    // establish sub-heaps of increasing lengths:
1985    let mut n = heap.heap_len / 2;
1986    while n >= 1 {
1987        heap.pqdownheap(tree, n);
1988        n -= 1;
1989    }
1990
1991    heap.construct_huffman_tree(tree, elements);
1992
1993    // At this point, the fields freq and dad are set. We can now
1994    // generate the bit lengths.
1995    let bl_count = gen_bitlen(state, &mut heap, desc);
1996
1997    // The field len is now set, we can generate the bit codes
1998    gen_codes(&mut desc.dyn_tree, max_code, &bl_count);
1999}
2000
2001fn gen_bitlen<const N: usize>(
2002    state: &mut State,
2003    heap: &mut Heap,
2004    desc: &mut TreeDesc<N>,
2005) -> [u16; MAX_BITS + 1] {
2006    let tree = &mut desc.dyn_tree;
2007    let max_code = desc.max_code;
2008    let stree = desc.stat_desc.static_tree;
2009    let extra = desc.stat_desc.extra_bits;
2010    let base = desc.stat_desc.extra_base;
2011    let max_length = desc.stat_desc.max_length;
2012
2013    let mut bl_count = [0u16; MAX_BITS + 1];
2014
2015    // In a first pass, compute the optimal bit lengths (which may
2016    // overflow in the case of the bit length tree).
2017    *tree[heap.heap[heap.heap_max] as usize].len_mut() = 0; /* root of the heap */
2018
2019    // number of elements with bit length too large
2020    let mut overflow: i32 = 0;
2021
2022    for h in heap.heap_max + 1..HEAP_SIZE {
2023        let n = heap.heap[h] as usize;
2024        let mut bits = tree[tree[n].dad() as usize].len() + 1;
2025
2026        if bits > max_length {
2027            bits = max_length;
2028            overflow += 1;
2029        }
2030
2031        // We overwrite tree[n].Dad which is no longer needed
2032        *tree[n].len_mut() = bits;
2033
2034        // not a leaf node
2035        if n > max_code {
2036            continue;
2037        }
2038
2039        bl_count[bits as usize] += 1;
2040        let mut xbits = 0;
2041        if n >= base {
2042            xbits = extra[n - base] as usize;
2043        }
2044
2045        let f = tree[n].freq() as usize;
2046        state.opt_len += f * (bits as usize + xbits);
2047
2048        if !stree.is_empty() {
2049            state.static_len += f * (stree[n].len() as usize + xbits);
2050        }
2051    }
2052
2053    if overflow == 0 {
2054        return bl_count;
2055    }
2056
2057    /* Find the first bit length which could increase: */
2058    loop {
2059        let mut bits = max_length as usize - 1;
2060        while bl_count[bits] == 0 {
2061            bits -= 1;
2062        }
2063        bl_count[bits] -= 1; /* move one leaf down the tree */
2064        bl_count[bits + 1] += 2; /* move one overflow item as its brother */
2065        bl_count[max_length as usize] -= 1;
2066        /* The brother of the overflow item also moves one step up,
2067         * but this does not affect bl_count[max_length]
2068         */
2069        overflow -= 2;
2070
2071        if overflow <= 0 {
2072            break;
2073        }
2074    }
2075
2076    // Now recompute all bit lengths, scanning in increasing frequency.
2077    // h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
2078    // lengths instead of fixing only the wrong ones. This idea is taken
2079    // from 'ar' written by Haruhiko Okumura.)
2080    let mut h = HEAP_SIZE;
2081    for bits in (1..=max_length).rev() {
2082        let mut n = bl_count[bits as usize];
2083        while n != 0 {
2084            h -= 1;
2085            let m = heap.heap[h] as usize;
2086            if m > max_code {
2087                continue;
2088            }
2089
2090            if tree[m].len() != bits {
2091                // Tracev((stderr, "code %d bits %d->%u\n", m, tree[m].Len, bits));
2092                state.opt_len += (bits * tree[m].freq()) as usize;
2093                state.opt_len -= (tree[m].len() * tree[m].freq()) as usize;
2094                *tree[m].len_mut() = bits;
2095            }
2096
2097            n -= 1;
2098        }
2099    }
2100    bl_count
2101}
2102
2103/// Checks that symbol is a printing character (excluding space)
2104#[allow(unused)]
2105fn isgraph(c: u8) -> bool {
2106    (c > 0x20) && (c <= 0x7E)
2107}
2108
2109fn gen_codes(tree: &mut [Value], max_code: usize, bl_count: &[u16]) {
2110    /* tree: the tree to decorate */
2111    /* max_code: largest code with non zero frequency */
2112    /* bl_count: number of codes at each bit length */
2113    let mut next_code = [0; MAX_BITS + 1]; /* next code value for each bit length */
2114    let mut code = 0; /* running code value */
2115
2116    /* The distribution counts are first used to generate the code values
2117     * without bit reversal.
2118     */
2119    for bits in 1..=MAX_BITS {
2120        code = (code + bl_count[bits - 1]) << 1;
2121        next_code[bits] = code;
2122    }
2123
2124    /* Check that the bit counts in bl_count are consistent. The last code
2125     * must be all ones.
2126     */
2127    assert!(
2128        code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
2129        "inconsistent bit counts"
2130    );
2131
2132    trace!("\ngen_codes: max_code {max_code} ");
2133
2134    for n in 0..=max_code {
2135        let len = tree[n].len();
2136        if len == 0 {
2137            continue;
2138        }
2139
2140        /* Now reverse the bits */
2141        assert!((1..=15).contains(&len), "code length must be 1-15");
2142        *tree[n].code_mut() = next_code[len as usize].reverse_bits() >> (16 - len);
2143        next_code[len as usize] += 1;
2144
2145        if tree != self::trees_tbl::STATIC_LTREE.as_slice() {
2146            trace!(
2147                "\nn {:>3} {} l {:>2} c {:>4x} ({:x}) ",
2148                n,
2149                if isgraph(n as u8) {
2150                    char::from_u32(n as u32).unwrap()
2151                } else {
2152                    ' '
2153                },
2154                len,
2155                tree[n].code(),
2156                next_code[len as usize] - 1
2157            );
2158        }
2159    }
2160}
2161
2162/// repeat previous bit length 3-6 times (2 bits of repeat count)
2163const REP_3_6: usize = 16;
2164
2165/// repeat a zero length 3-10 times  (3 bits of repeat count)
2166const REPZ_3_10: usize = 17;
2167
2168/// repeat a zero length 11-138 times  (7 bits of repeat count)
2169const REPZ_11_138: usize = 18;
2170
2171fn scan_tree(bl_desc: &mut TreeDesc<{ 2 * BL_CODES + 1 }>, tree: &mut [Value], max_code: usize) {
2172    /* tree: the tree to be scanned */
2173    /* max_code: and its largest code of non zero frequency */
2174    let mut prevlen = -1isize; /* last emitted length */
2175    let mut curlen: isize; /* length of current code */
2176    let mut nextlen = tree[0].len(); /* length of next code */
2177    let mut count = 0; /* repeat count of the current code */
2178    let mut max_count = 7; /* max repeat count */
2179    let mut min_count = 4; /* min repeat count */
2180
2181    if nextlen == 0 {
2182        max_count = 138;
2183        min_count = 3;
2184    }
2185
2186    *tree[max_code + 1].len_mut() = 0xffff; /* guard */
2187
2188    let bl_tree = &mut bl_desc.dyn_tree;
2189
2190    for n in 0..=max_code {
2191        curlen = nextlen as isize;
2192        nextlen = tree[n + 1].len();
2193        count += 1;
2194        if count < max_count && curlen == nextlen as isize {
2195            continue;
2196        } else if count < min_count {
2197            *bl_tree[curlen as usize].freq_mut() += count;
2198        } else if curlen != 0 {
2199            if curlen != prevlen {
2200                *bl_tree[curlen as usize].freq_mut() += 1;
2201            }
2202            *bl_tree[REP_3_6].freq_mut() += 1;
2203        } else if count <= 10 {
2204            *bl_tree[REPZ_3_10].freq_mut() += 1;
2205        } else {
2206            *bl_tree[REPZ_11_138].freq_mut() += 1;
2207        }
2208
2209        count = 0;
2210        prevlen = curlen;
2211
2212        if nextlen == 0 {
2213            max_count = 138;
2214            min_count = 3;
2215        } else if curlen == nextlen as isize {
2216            max_count = 6;
2217            min_count = 3;
2218        } else {
2219            max_count = 7;
2220            min_count = 4;
2221        }
2222    }
2223}
2224
2225fn send_all_trees(state: &mut State, lcodes: usize, dcodes: usize, blcodes: usize) {
2226    assert!(
2227        lcodes >= 257 && dcodes >= 1 && blcodes >= 4,
2228        "not enough codes"
2229    );
2230    assert!(
2231        lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
2232        "too many codes"
2233    );
2234
2235    trace!("\nbl counts: ");
2236    state.bit_writer.send_bits(lcodes as u64 - 257, 5); /* not +255 as stated in appnote.txt */
2237    state.bit_writer.send_bits(dcodes as u64 - 1, 5);
2238    state.bit_writer.send_bits(blcodes as u64 - 4, 4); /* not -3 as stated in appnote.txt */
2239
2240    for rank in 0..blcodes {
2241        trace!("\nbl code {:>2} ", StaticTreeDesc::BL_ORDER[rank]);
2242        state.bit_writer.send_bits(
2243            state.bl_desc.dyn_tree[StaticTreeDesc::BL_ORDER[rank] as usize].len() as u64,
2244            3,
2245        );
2246    }
2247    trace!("\nbl tree: sent {}", state.bit_writer.bits_sent);
2248
2249    // literal tree
2250    state
2251        .bit_writer
2252        .send_tree(&state.l_desc.dyn_tree, &state.bl_desc.dyn_tree, lcodes - 1);
2253    trace!("\nlit tree: sent {}", state.bit_writer.bits_sent);
2254
2255    // distance tree
2256    state
2257        .bit_writer
2258        .send_tree(&state.d_desc.dyn_tree, &state.bl_desc.dyn_tree, dcodes - 1);
2259    trace!("\ndist tree: sent {}", state.bit_writer.bits_sent);
2260}
2261
2262/// Construct the Huffman tree for the bit lengths and return the index in
2263/// bl_order of the last bit length code to send.
2264fn build_bl_tree(state: &mut State) -> usize {
2265    /* Determine the bit length frequencies for literal and distance trees */
2266
2267    scan_tree(
2268        &mut state.bl_desc,
2269        &mut state.l_desc.dyn_tree,
2270        state.l_desc.max_code,
2271    );
2272
2273    scan_tree(
2274        &mut state.bl_desc,
2275        &mut state.d_desc.dyn_tree,
2276        state.d_desc.max_code,
2277    );
2278
2279    /* Build the bit length tree: */
2280    {
2281        let mut tmp = TreeDesc::EMPTY;
2282        core::mem::swap(&mut tmp, &mut state.bl_desc);
2283        build_tree(state, &mut tmp);
2284        core::mem::swap(&mut tmp, &mut state.bl_desc);
2285    }
2286
2287    /* opt_len now includes the length of the tree representations, except
2288     * the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
2289     */
2290
2291    /* Determine the number of bit length codes to send. The pkzip format
2292     * requires that at least 4 bit length codes be sent. (appnote.txt says
2293     * 3 but the actual value used is 4.)
2294     */
2295    let mut max_blindex = BL_CODES - 1;
2296    while max_blindex >= 3 {
2297        let index = StaticTreeDesc::BL_ORDER[max_blindex] as usize;
2298        if state.bl_desc.dyn_tree[index].len() != 0 {
2299            break;
2300        }
2301
2302        max_blindex -= 1;
2303    }
2304
2305    /* Update opt_len to include the bit length tree and counts */
2306    state.opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
2307    trace!(
2308        "\ndyn trees: dyn {}, stat {}",
2309        state.opt_len,
2310        state.static_len
2311    );
2312
2313    max_blindex
2314}
2315
2316fn zng_tr_flush_block(
2317    stream: &mut DeflateStream,
2318    window_offset: Option<usize>,
2319    stored_len: u32,
2320    last: bool,
2321) {
2322    /* window_offset: offset of the input block into the window */
2323    /* stored_len: length of input block */
2324    /* last: one if this is the last block for a file */
2325
2326    let mut opt_lenb;
2327    let static_lenb;
2328    let mut max_blindex = 0;
2329
2330    let state = &mut stream.state;
2331
2332    if state.sym_buf.is_empty() {
2333        opt_lenb = 0;
2334        static_lenb = 0;
2335        state.static_len = 7;
2336    } else if state.level > 0 {
2337        if stream.data_type == DataType::Unknown as i32 {
2338            stream.data_type = State::detect_data_type(&state.l_desc.dyn_tree) as i32;
2339        }
2340
2341        {
2342            let mut tmp = TreeDesc::EMPTY;
2343            core::mem::swap(&mut tmp, &mut state.l_desc);
2344
2345            build_tree(state, &mut tmp);
2346            core::mem::swap(&mut tmp, &mut state.l_desc);
2347
2348            trace!(
2349                "\nlit data: dyn {}, stat {}",
2350                state.opt_len,
2351                state.static_len
2352            );
2353        }
2354
2355        {
2356            let mut tmp = TreeDesc::EMPTY;
2357            core::mem::swap(&mut tmp, &mut state.d_desc);
2358            build_tree(state, &mut tmp);
2359            core::mem::swap(&mut tmp, &mut state.d_desc);
2360
2361            trace!(
2362                "\ndist data: dyn {}, stat {}",
2363                state.opt_len,
2364                state.static_len
2365            );
2366        }
2367
2368        // Build the bit length tree for the above two trees, and get the index
2369        // in bl_order of the last bit length code to send.
2370        max_blindex = build_bl_tree(state);
2371
2372        // Determine the best encoding. Compute the block lengths in bytes.
2373        opt_lenb = (state.opt_len + 3 + 7) >> 3;
2374        static_lenb = (state.static_len + 3 + 7) >> 3;
2375
2376        trace!(
2377            "\nopt {}({}) stat {}({}) stored {} lit {} ",
2378            opt_lenb,
2379            state.opt_len,
2380            static_lenb,
2381            state.static_len,
2382            stored_len,
2383            state.sym_buf.iter().count()
2384        );
2385
2386        if static_lenb <= opt_lenb || state.strategy == Strategy::Fixed {
2387            opt_lenb = static_lenb;
2388        }
2389    } else {
2390        assert!(window_offset.is_some(), "lost buf");
2391        /* force a stored block */
2392        opt_lenb = stored_len as usize + 5;
2393        static_lenb = stored_len as usize + 5;
2394    }
2395
2396    #[allow(clippy::unnecessary_unwrap)]
2397    if stored_len as usize + 4 <= opt_lenb && window_offset.is_some() {
2398        /* 4: two words for the lengths
2399         * The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
2400         * Otherwise we can't have processed more than WSIZE input bytes since
2401         * the last block flush, because compression would have been
2402         * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
2403         * transform a block into a stored block.
2404         */
2405        let window_offset = window_offset.unwrap();
2406        let range = window_offset..window_offset + stored_len as usize;
2407        zng_tr_stored_block(state, range, last);
2408    } else if static_lenb == opt_lenb {
2409        state.bit_writer.emit_tree(BlockType::StaticTrees, last);
2410        state.compress_block_static_trees();
2411    // cmpr_bits_add(s, s.static_len);
2412    } else {
2413        state.bit_writer.emit_tree(BlockType::DynamicTrees, last);
2414        send_all_trees(
2415            state,
2416            state.l_desc.max_code + 1,
2417            state.d_desc.max_code + 1,
2418            max_blindex + 1,
2419        );
2420
2421        state.compress_block_dynamic_trees();
2422    }
2423
2424    // TODO
2425    // This check is made mod 2^32, for files larger than 512 MB and unsigned long implemented on 32 bits.
2426    // assert_eq!(state.compressed_len, state.bits_sent, "bad compressed size");
2427
2428    state.init_block();
2429    if last {
2430        state.bit_writer.emit_align();
2431    }
2432
2433    // Tracev((stderr, "\ncomprlen {}(%lu) ", s->compressed_len>>3, s->compressed_len-7*last));
2434}
2435
2436pub(crate) fn flush_block_only(stream: &mut DeflateStream, is_last: bool) {
2437    zng_tr_flush_block(
2438        stream,
2439        (stream.state.block_start >= 0).then_some(stream.state.block_start as usize),
2440        (stream.state.strstart as isize - stream.state.block_start) as u32,
2441        is_last,
2442    );
2443
2444    stream.state.block_start = stream.state.strstart as isize;
2445    flush_pending(stream)
2446}
2447
2448fn flush_bytes(stream: &mut DeflateStream, mut bytes: &[u8]) -> ControlFlow<ReturnCode> {
2449    let mut state = &mut stream.state;
2450
2451    // we'll be using the pending buffer as temporary storage
2452    let mut beg = state.bit_writer.pending.pending().len(); /* start of bytes to update crc */
2453
2454    while state.bit_writer.pending.remaining() < bytes.len() {
2455        let copy = state.bit_writer.pending.remaining();
2456
2457        state.bit_writer.pending.extend(&bytes[..copy]);
2458
2459        stream.adler = crc32(
2460            stream.adler as u32,
2461            &state.bit_writer.pending.pending()[beg..],
2462        ) as z_checksum;
2463
2464        state.gzindex += copy;
2465        flush_pending(stream);
2466        state = &mut stream.state;
2467
2468        // could not flush all the pending output
2469        if !state.bit_writer.pending.pending().is_empty() {
2470            state.last_flush = -1;
2471            return ControlFlow::Break(ReturnCode::Ok);
2472        }
2473
2474        beg = 0;
2475        bytes = &bytes[copy..];
2476    }
2477
2478    state.bit_writer.pending.extend(bytes);
2479
2480    stream.adler = crc32(
2481        stream.adler as u32,
2482        &state.bit_writer.pending.pending()[beg..],
2483    ) as z_checksum;
2484    state.gzindex = 0;
2485
2486    ControlFlow::Continue(())
2487}
2488
2489pub fn deflate(stream: &mut DeflateStream, flush: DeflateFlush) -> ReturnCode {
2490    if stream.next_out.is_null()
2491        || (stream.avail_in != 0 && stream.next_in.is_null())
2492        || (stream.state.status == Status::Finish && flush != DeflateFlush::Finish)
2493    {
2494        let err = ReturnCode::StreamError;
2495        stream.msg = err.error_message();
2496        return err;
2497    }
2498
2499    if stream.avail_out == 0 {
2500        let err = ReturnCode::BufError;
2501        stream.msg = err.error_message();
2502        return err;
2503    }
2504
2505    let old_flush = stream.state.last_flush;
2506    stream.state.last_flush = flush as i8;
2507
2508    /* Flush as much pending output as possible */
2509    if !stream.state.bit_writer.pending.pending().is_empty() {
2510        flush_pending(stream);
2511        if stream.avail_out == 0 {
2512            /* Since avail_out is 0, deflate will be called again with
2513             * more output space, but possibly with both pending and
2514             * avail_in equal to zero. There won't be anything to do,
2515             * but this is not an error situation so make sure we
2516             * return OK instead of BUF_ERROR at next call of deflate:
2517             */
2518            stream.state.last_flush = -1;
2519            return ReturnCode::Ok;
2520        }
2521
2522        /* Make sure there is something to do and avoid duplicate consecutive
2523         * flushes. For repeated and useless calls with Z_FINISH, we keep
2524         * returning Z_STREAM_END instead of Z_BUF_ERROR.
2525         */
2526    } else if stream.avail_in == 0
2527        && rank_flush(flush as i8) <= rank_flush(old_flush)
2528        && flush != DeflateFlush::Finish
2529    {
2530        let err = ReturnCode::BufError;
2531        stream.msg = err.error_message();
2532        return err;
2533    }
2534
2535    /* User must not provide more input after the first FINISH: */
2536    if stream.state.status == Status::Finish && stream.avail_in != 0 {
2537        let err = ReturnCode::BufError;
2538        stream.msg = err.error_message();
2539        return err;
2540    }
2541
2542    /* Write the header */
2543    if stream.state.status == Status::Init && stream.state.wrap == 0 {
2544        stream.state.status = Status::Busy;
2545    }
2546
2547    if stream.state.status == Status::Init {
2548        let header = stream.state.header();
2549        stream
2550            .state
2551            .bit_writer
2552            .pending
2553            .extend(&header.to_be_bytes());
2554
2555        /* Save the adler32 of the preset dictionary: */
2556        if stream.state.strstart != 0 {
2557            let adler = stream.adler as u32;
2558            stream.state.bit_writer.pending.extend(&adler.to_be_bytes());
2559        }
2560
2561        stream.adler = ADLER32_INITIAL_VALUE as _;
2562        stream.state.status = Status::Busy;
2563
2564        // compression must start with an empty pending buffer
2565        flush_pending(stream);
2566
2567        if !stream.state.bit_writer.pending.pending().is_empty() {
2568            stream.state.last_flush = -1;
2569
2570            return ReturnCode::Ok;
2571        }
2572    }
2573
2574    if stream.state.status == Status::GZip {
2575        /* gzip header */
2576        stream.state.crc_fold = Crc32Fold::new();
2577
2578        stream.state.bit_writer.pending.extend(&[31, 139, 8]);
2579
2580        let extra_flags = if stream.state.level == 9 {
2581            2
2582        } else if stream.state.strategy >= Strategy::HuffmanOnly || stream.state.level < 2 {
2583            4
2584        } else {
2585            0
2586        };
2587
2588        match &stream.state.gzhead {
2589            None => {
2590                let bytes = [0, 0, 0, 0, 0, extra_flags, gz_header::OS_CODE];
2591                stream.state.bit_writer.pending.extend(&bytes);
2592                stream.state.status = Status::Busy;
2593
2594                /* Compression must start with an empty pending buffer */
2595                flush_pending(stream);
2596                if !stream.state.bit_writer.pending.pending().is_empty() {
2597                    stream.state.last_flush = -1;
2598                    return ReturnCode::Ok;
2599                }
2600            }
2601            Some(gzhead) => {
2602                stream.state.bit_writer.pending.extend(&[gzhead.flags()]);
2603                let bytes = (gzhead.time as u32).to_le_bytes();
2604                stream.state.bit_writer.pending.extend(&bytes);
2605                stream
2606                    .state
2607                    .bit_writer
2608                    .pending
2609                    .extend(&[extra_flags, gzhead.os as u8]);
2610
2611                if !gzhead.extra.is_null() {
2612                    let bytes = (gzhead.extra_len as u16).to_le_bytes();
2613                    stream.state.bit_writer.pending.extend(&bytes);
2614                }
2615
2616                if gzhead.hcrc != 0 {
2617                    stream.adler = crc32(
2618                        stream.adler as u32,
2619                        stream.state.bit_writer.pending.pending(),
2620                    ) as z_checksum
2621                }
2622
2623                stream.state.gzindex = 0;
2624                stream.state.status = Status::Extra;
2625            }
2626        }
2627    }
2628
2629    if stream.state.status == Status::Extra {
2630        if let Some(gzhead) = stream.state.gzhead.as_ref() {
2631            if !gzhead.extra.is_null() {
2632                let gzhead_extra = gzhead.extra;
2633
2634                let extra = unsafe {
2635                    core::slice::from_raw_parts(
2636                        // SAFETY: gzindex is always less than extra_len, and the user
2637                        // guarantees the pointer is valid for extra_len.
2638                        gzhead_extra.add(stream.state.gzindex),
2639                        (gzhead.extra_len & 0xffff) as usize - stream.state.gzindex,
2640                    )
2641                };
2642
2643                if let ControlFlow::Break(err) = flush_bytes(stream, extra) {
2644                    return err;
2645                }
2646            }
2647        }
2648        stream.state.status = Status::Name;
2649    }
2650
2651    if stream.state.status == Status::Name {
2652        if let Some(gzhead) = stream.state.gzhead.as_ref() {
2653            if !gzhead.name.is_null() {
2654                // SAFETY: user satisfies precondition that gzhead.name is a C string.
2655                let gzhead_name = unsafe { CStr::from_ptr(gzhead.name.cast()) };
2656                let bytes = gzhead_name.to_bytes_with_nul();
2657                if let ControlFlow::Break(err) = flush_bytes(stream, bytes) {
2658                    return err;
2659                }
2660            }
2661            stream.state.status = Status::Comment;
2662        }
2663    }
2664
2665    if stream.state.status == Status::Comment {
2666        if let Some(gzhead) = stream.state.gzhead.as_ref() {
2667            if !gzhead.comment.is_null() {
2668                // SAFETY: user satisfies precondition that gzhead.name is a C string.
2669                let gzhead_comment = unsafe { CStr::from_ptr(gzhead.comment.cast()) };
2670                let bytes = gzhead_comment.to_bytes_with_nul();
2671                if let ControlFlow::Break(err) = flush_bytes(stream, bytes) {
2672                    return err;
2673                }
2674            }
2675            stream.state.status = Status::Hcrc;
2676        }
2677    }
2678
2679    if stream.state.status == Status::Hcrc {
2680        if let Some(gzhead) = stream.state.gzhead.as_ref() {
2681            if gzhead.hcrc != 0 {
2682                let bytes = (stream.adler as u16).to_le_bytes();
2683                if let ControlFlow::Break(err) = flush_bytes(stream, &bytes) {
2684                    return err;
2685                }
2686            }
2687        }
2688
2689        stream.state.status = Status::Busy;
2690
2691        // compression must start with an empty pending buffer
2692        flush_pending(stream);
2693        if !stream.state.bit_writer.pending.pending().is_empty() {
2694            stream.state.last_flush = -1;
2695            return ReturnCode::Ok;
2696        }
2697    }
2698
2699    // Start a new block or continue the current one.
2700    let state = &mut stream.state;
2701    if stream.avail_in != 0
2702        || state.lookahead != 0
2703        || (flush != DeflateFlush::NoFlush && state.status != Status::Finish)
2704    {
2705        let bstate = self::algorithm::run(stream, flush);
2706
2707        let state = &mut stream.state;
2708
2709        if matches!(bstate, BlockState::FinishStarted | BlockState::FinishDone) {
2710            state.status = Status::Finish;
2711        }
2712
2713        match bstate {
2714            BlockState::NeedMore | BlockState::FinishStarted => {
2715                if stream.avail_out == 0 {
2716                    state.last_flush = -1; /* avoid BUF_ERROR next call, see above */
2717                }
2718                return ReturnCode::Ok;
2719                /* If flush != Z_NO_FLUSH && avail_out == 0, the next call
2720                 * of deflate should use the same flush parameter to make sure
2721                 * that the flush is complete. So we don't have to output an
2722                 * empty block here, this will be done at next call. This also
2723                 * ensures that for a very small output buffer, we emit at most
2724                 * one empty block.
2725                 */
2726            }
2727            BlockState::BlockDone => {
2728                match flush {
2729                    DeflateFlush::NoFlush => unreachable!("condition of inner surrounding if"),
2730                    DeflateFlush::PartialFlush => {
2731                        state.bit_writer.align();
2732                    }
2733                    DeflateFlush::SyncFlush => {
2734                        // add an empty stored block that is marked as not final. This is useful for
2735                        // parallel deflate where we want to make sure the intermediate blocks are not
2736                        // marked as "last block".
2737                        zng_tr_stored_block(state, 0..0, false);
2738                    }
2739                    DeflateFlush::FullFlush => {
2740                        // add an empty stored block that is marked as not final. This is useful for
2741                        // parallel deflate where we want to make sure the intermediate blocks are not
2742                        // marked as "last block".
2743                        zng_tr_stored_block(state, 0..0, false);
2744
2745                        state.head.as_mut_slice().fill(0); // forget history
2746
2747                        if state.lookahead == 0 {
2748                            state.strstart = 0;
2749                            state.block_start = 0;
2750                            state.insert = 0;
2751                        }
2752                    }
2753                    DeflateFlush::Block => { /* fall through */ }
2754                    DeflateFlush::Finish => unreachable!("condition of outer surrounding if"),
2755                }
2756
2757                flush_pending(stream);
2758
2759                if stream.avail_out == 0 {
2760                    stream.state.last_flush = -1; /* avoid BUF_ERROR at next call, see above */
2761                    return ReturnCode::Ok;
2762                }
2763            }
2764            BlockState::FinishDone => { /* do nothing */ }
2765        }
2766    }
2767
2768    if flush != DeflateFlush::Finish {
2769        return ReturnCode::Ok;
2770    }
2771
2772    // write the trailer
2773    if stream.state.wrap == 2 {
2774        let crc_fold = core::mem::take(&mut stream.state.crc_fold);
2775        stream.adler = crc_fold.finish() as z_checksum;
2776
2777        let adler = stream.adler as u32;
2778        stream.state.bit_writer.pending.extend(&adler.to_le_bytes());
2779
2780        let total_in = stream.total_in as u32;
2781        stream
2782            .state
2783            .bit_writer
2784            .pending
2785            .extend(&total_in.to_le_bytes());
2786    } else if stream.state.wrap == 1 {
2787        let adler = stream.adler as u32;
2788        stream.state.bit_writer.pending.extend(&adler.to_be_bytes());
2789    }
2790
2791    flush_pending(stream);
2792
2793    // If avail_out is zero, the application will call deflate again to flush the rest.
2794    if stream.state.wrap > 0 {
2795        stream.state.wrap = -stream.state.wrap; /* write the trailer only once! */
2796    }
2797
2798    if stream.state.bit_writer.pending.pending().is_empty() {
2799        assert_eq!(stream.state.bit_writer.bits_valid, 0, "bi_buf not flushed");
2800        return ReturnCode::StreamEnd;
2801    }
2802    ReturnCode::Ok
2803}
2804
2805pub(crate) fn flush_pending(stream: &mut DeflateStream) {
2806    let state = &mut stream.state;
2807
2808    state.bit_writer.flush_bits();
2809
2810    let pending = state.bit_writer.pending.pending();
2811    let len = Ord::min(pending.len(), stream.avail_out as usize);
2812
2813    if len == 0 {
2814        return;
2815    }
2816
2817    trace!("\n[FLUSH {len} bytes]");
2818    // SAFETY: len is min(pending, stream.avail_out), so we won't overrun next_out.
2819    unsafe { core::ptr::copy_nonoverlapping(pending.as_ptr(), stream.next_out, len) };
2820
2821    stream.next_out = stream.next_out.wrapping_add(len);
2822    stream.total_out += len as crate::c_api::z_size;
2823    stream.avail_out -= len as crate::c_api::uInt;
2824
2825    state.bit_writer.pending.advance(len);
2826}
2827
2828/// Compresses `input` into the provided `output` buffer.
2829///
2830/// Returns a subslice of `output` containing the compressed bytes and a
2831/// [`ReturnCode`] indicating the result of the operation. Returns [`ReturnCode::BufError`] if
2832/// there is insufficient output space.
2833///
2834/// Use [`compress_bound`] for an upper bound on how large the output buffer needs to be.
2835///
2836/// # Example
2837///
2838/// ```
2839/// # use zlib_rs::*;
2840/// # fn foo(input: &[u8]) {
2841/// let mut buf = vec![0u8; compress_bound(input.len())];
2842/// let (compressed, rc) = compress_slice(&mut buf, input, DeflateConfig::default());
2843/// # }
2844/// ```
2845pub fn compress_slice<'a>(
2846    output: &'a mut [u8],
2847    input: &[u8],
2848    config: DeflateConfig,
2849) -> (&'a mut [u8], ReturnCode) {
2850    // SAFETY: a [u8] is a valid [MaybeUninit<u8>].
2851    let output_uninit = unsafe {
2852        core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut MaybeUninit<u8>, output.len())
2853    };
2854
2855    compress(output_uninit, input, config)
2856}
2857
2858pub fn compress<'a>(
2859    output: &'a mut [MaybeUninit<u8>],
2860    input: &[u8],
2861    config: DeflateConfig,
2862) -> (&'a mut [u8], ReturnCode) {
2863    compress_with_flush(output, input, config, DeflateFlush::Finish)
2864}
2865
2866pub fn compress_slice_with_flush<'a>(
2867    output: &'a mut [u8],
2868    input: &[u8],
2869    config: DeflateConfig,
2870    flush: DeflateFlush,
2871) -> (&'a mut [u8], ReturnCode) {
2872    // SAFETY: a [u8] is a valid [MaybeUninit<u8>], and `compress_with_flush` never uninitializes previously initialized memory.
2873    let output_uninit = unsafe {
2874        core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut MaybeUninit<u8>, output.len())
2875    };
2876
2877    compress_with_flush(output_uninit, input, config, flush)
2878}
2879
2880pub fn compress_with_flush<'a>(
2881    output: &'a mut [MaybeUninit<u8>],
2882    input: &[u8],
2883    config: DeflateConfig,
2884    final_flush: DeflateFlush,
2885) -> (&'a mut [u8], ReturnCode) {
2886    let mut stream = z_stream {
2887        next_in: input.as_ptr() as *mut u8,
2888        avail_in: 0, // for special logic in the first  iteration
2889        total_in: 0,
2890        next_out: output.as_mut_ptr() as *mut u8,
2891        avail_out: 0, // for special logic on the first iteration
2892        total_out: 0,
2893        msg: core::ptr::null_mut(),
2894        state: core::ptr::null_mut(),
2895        zalloc: None,
2896        zfree: None,
2897        opaque: core::ptr::null_mut(),
2898        data_type: 0,
2899        adler: 0,
2900        reserved: 0,
2901    };
2902
2903    let err = init(&mut stream, config);
2904    if err != ReturnCode::Ok {
2905        return (&mut [], err);
2906    }
2907
2908    let max = core::ffi::c_uint::MAX as usize;
2909
2910    let mut left = output.len();
2911    let mut source_len = input.len();
2912
2913    let return_code = loop {
2914        if stream.avail_out == 0 {
2915            stream.avail_out = Ord::min(left, max) as _;
2916            left -= stream.avail_out as usize;
2917        }
2918
2919        if stream.avail_in == 0 {
2920            stream.avail_in = Ord::min(source_len, max) as _;
2921            source_len -= stream.avail_in as usize;
2922        }
2923
2924        let flush = if source_len > 0 {
2925            DeflateFlush::NoFlush
2926        } else {
2927            final_flush
2928        };
2929
2930        let err = if let Some(stream) = unsafe { DeflateStream::from_stream_mut(&mut stream) } {
2931            deflate(stream, flush)
2932        } else {
2933            ReturnCode::StreamError
2934        };
2935
2936        match err {
2937            ReturnCode::Ok => continue,
2938            ReturnCode::StreamEnd => break ReturnCode::Ok,
2939            _ => break err,
2940        }
2941    };
2942
2943    // SAFETY: we have now initialized these bytes
2944    let output_slice = unsafe {
2945        core::slice::from_raw_parts_mut(output.as_mut_ptr() as *mut u8, stream.total_out as usize)
2946    };
2947
2948    // may DataError if insufficient output space
2949    if let Some(stream) = unsafe { DeflateStream::from_stream_mut(&mut stream) } {
2950        let _ = end(stream);
2951    }
2952
2953    (output_slice, return_code)
2954}
2955
2956/// Returns the upper bound on the compressed size for an input of `source_len` bytes.
2957///
2958/// When compression has this much space available, it will never fail because of insufficient
2959/// output space.
2960///
2961/// # Example
2962///
2963/// ```
2964/// # use zlib_rs::*;
2965///
2966/// assert_eq!(compress_bound(1024), 1161);
2967/// assert_eq!(compress_bound(4096), 4617);
2968/// assert_eq!(compress_bound(65536), 73737);
2969///
2970/// # fn foo(input: &[u8]) {
2971/// let mut buf = vec![0u8; compress_bound(input.len())];
2972/// let (compressed, rc) = compress_slice(&mut buf, input, DeflateConfig::default());
2973/// # }
2974/// ```
2975pub const fn compress_bound(source_len: usize) -> usize {
2976    compress_bound_help(source_len, ZLIB_WRAPLEN)
2977}
2978
2979const fn compress_bound_help(source_len: usize, wrap_len: usize) -> usize {
2980    source_len // The source size itself */
2981        // Always at least one byte for any input
2982        .wrapping_add(if source_len == 0 { 1 } else { 0 })
2983        // One extra byte for lengths less than 9
2984        .wrapping_add(if source_len < 9 { 1 } else { 0 })
2985        // Source encoding overhead, padded to next full byte
2986        .wrapping_add(deflate_quick_overhead(source_len))
2987        // Deflate block overhead bytes
2988        .wrapping_add(DEFLATE_BLOCK_OVERHEAD)
2989        // none, zlib or gzip wrapper
2990        .wrapping_add(wrap_len)
2991}
2992
2993///  heap used to build the Huffman trees
2994///
2995/// The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
2996/// The same heap array is used to build all trees.
2997#[derive(Clone)]
2998struct Heap {
2999    heap: [u32; 2 * L_CODES + 1],
3000
3001    /// number of elements in the heap
3002    heap_len: usize,
3003
3004    /// element of the largest frequency
3005    heap_max: usize,
3006
3007    depth: [u8; 2 * L_CODES + 1],
3008}
3009
3010impl Heap {
3011    // an empty heap
3012    fn new() -> Self {
3013        Self {
3014            heap: [0; 2 * L_CODES + 1],
3015            heap_len: 0,
3016            heap_max: 0,
3017            depth: [0; 2 * L_CODES + 1],
3018        }
3019    }
3020
3021    /// Construct the initial heap, with least frequent element in
3022    /// heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
3023    fn initialize(&mut self, tree: &mut [Value]) -> isize {
3024        let mut max_code = -1;
3025
3026        self.heap_len = 0;
3027        self.heap_max = HEAP_SIZE;
3028
3029        for (n, node) in tree.iter_mut().enumerate() {
3030            if node.freq() > 0 {
3031                self.heap_len += 1;
3032                self.heap[self.heap_len] = n as u32;
3033                max_code = n as isize;
3034                self.depth[n] = 0;
3035            } else {
3036                *node.len_mut() = 0;
3037            }
3038        }
3039
3040        max_code
3041    }
3042
3043    /// Index within the heap array of least frequent node in the Huffman tree
3044    const SMALLEST: usize = 1;
3045
3046    fn pqdownheap(&mut self, tree: &[Value], mut k: usize) {
3047        /* tree: the tree to restore */
3048        /* k: node to move down */
3049
3050        // Given the index $i of a node in the tree, pack the node's frequency and depth
3051        // into a single integer. The heap ordering logic uses a primary sort on frequency
3052        // and a secondary sort on depth, so packing both into one integer makes it
3053        // possible to sort with fewer comparison operations.
3054        macro_rules! freq_and_depth {
3055            ($i:expr) => {
3056                (tree[$i as usize].freq() as u32) << 8 | self.depth[$i as usize] as u32
3057            };
3058        }
3059
3060        let v = self.heap[k];
3061        let v_val = freq_and_depth!(v);
3062        let mut j = k << 1; /* left son of k */
3063
3064        while j <= self.heap_len {
3065            /* Set j to the smallest of the two sons: */
3066            let mut j_val = freq_and_depth!(self.heap[j]);
3067            if j < self.heap_len {
3068                let j1_val = freq_and_depth!(self.heap[j + 1]);
3069                if j1_val <= j_val {
3070                    j += 1;
3071                    j_val = j1_val;
3072                }
3073            }
3074
3075            /* Exit if v is smaller than both sons */
3076            if v_val <= j_val {
3077                break;
3078            }
3079
3080            /* Exchange v with the smallest son */
3081            self.heap[k] = self.heap[j];
3082            k = j;
3083
3084            /* And continue down the tree, setting j to the left son of k */
3085            j <<= 1;
3086        }
3087
3088        self.heap[k] = v;
3089    }
3090
3091    /// Remove the smallest element from the heap and recreate the heap with
3092    /// one less element. Updates heap and heap_len.
3093    fn pqremove(&mut self, tree: &[Value]) -> u32 {
3094        let top = self.heap[Self::SMALLEST];
3095        self.heap[Self::SMALLEST] = self.heap[self.heap_len];
3096        self.heap_len -= 1;
3097
3098        self.pqdownheap(tree, Self::SMALLEST);
3099
3100        top
3101    }
3102
3103    /// Construct the Huffman tree by repeatedly combining the least two frequent nodes.
3104    fn construct_huffman_tree(&mut self, tree: &mut [Value], mut node: usize) {
3105        loop {
3106            let n = self.pqremove(tree) as usize; /* n = node of least frequency */
3107            let m = self.heap[Heap::SMALLEST] as usize; /* m = node of next least frequency */
3108
3109            self.heap_max -= 1;
3110            self.heap[self.heap_max] = n as u32; /* keep the nodes sorted by frequency */
3111            self.heap_max -= 1;
3112            self.heap[self.heap_max] = m as u32;
3113
3114            /* Create a new node father of n and m */
3115            *tree[node].freq_mut() = tree[n].freq() + tree[m].freq();
3116            self.depth[node] = Ord::max(self.depth[n], self.depth[m]) + 1;
3117
3118            *tree[n].dad_mut() = node as u16;
3119            *tree[m].dad_mut() = node as u16;
3120
3121            /* and insert the new node in the heap */
3122            self.heap[Heap::SMALLEST] = node as u32;
3123            node += 1;
3124
3125            self.pqdownheap(tree, Heap::SMALLEST);
3126
3127            if self.heap_len < 2 {
3128                break;
3129            }
3130        }
3131
3132        self.heap_max -= 1;
3133        self.heap[self.heap_max] = self.heap[Heap::SMALLEST];
3134    }
3135}
3136
3137/// # Safety
3138///
3139/// The caller must guarantee:
3140///
3141/// * If `head` is `Some`
3142///     - `head.extra` is `NULL` or is readable for at least `head.extra_len` bytes
3143///     - `head.name` is `NULL` or satisfies the requirements of [`core::ffi::CStr::from_ptr`]
3144///     - `head.comment` is `NULL` or satisfies the requirements of [`core::ffi::CStr::from_ptr`]
3145pub unsafe fn set_header<'a>(
3146    stream: &mut DeflateStream<'a>,
3147    head: Option<&'a mut gz_header>,
3148) -> ReturnCode {
3149    if stream.state.wrap != 2 {
3150        ReturnCode::StreamError
3151    } else {
3152        stream.state.gzhead = head;
3153        ReturnCode::Ok
3154    }
3155}
3156
3157// zlib format overhead
3158const ZLIB_WRAPLEN: usize = 6;
3159// gzip format overhead
3160const GZIP_WRAPLEN: usize = 18;
3161
3162const DEFLATE_HEADER_BITS: usize = 3;
3163const DEFLATE_EOBS_BITS: usize = 15;
3164const DEFLATE_PAD_BITS: usize = 6;
3165const DEFLATE_BLOCK_OVERHEAD: usize =
3166    (DEFLATE_HEADER_BITS + DEFLATE_EOBS_BITS + DEFLATE_PAD_BITS) >> 3;
3167
3168const DEFLATE_QUICK_LIT_MAX_BITS: usize = 9;
3169const fn deflate_quick_overhead(x: usize) -> usize {
3170    let sum = x
3171        .wrapping_mul(DEFLATE_QUICK_LIT_MAX_BITS - 8)
3172        .wrapping_add(7);
3173
3174    // imitate zlib-ng rounding behavior (on windows, c_ulong is 32 bits)
3175    (sum as core::ffi::c_ulong >> 3) as usize
3176}
3177
3178/// For the default windowBits of 15 and memLevel of 8, this function returns
3179/// a close to exact, as well as small, upper bound on the compressed size.
3180/// They are coded as constants here for a reason--if the #define's are
3181/// changed, then this function needs to be changed as well.  The return
3182/// value for 15 and 8 only works for those exact settings.
3183///
3184/// For any setting other than those defaults for windowBits and memLevel,
3185/// the value returned is a conservative worst case for the maximum expansion
3186/// resulting from using fixed blocks instead of stored blocks, which deflate
3187/// can emit on compressed data for some combinations of the parameters.
3188///
3189/// This function could be more sophisticated to provide closer upper bounds for
3190/// every combination of windowBits and memLevel.  But even the conservative
3191/// upper bound of about 14% expansion does not seem onerous for output buffer
3192/// allocation.
3193pub fn bound(stream: Option<&mut DeflateStream>, source_len: usize) -> usize {
3194    // on windows, c_ulong is only a 32-bit integer
3195    let mask = core::ffi::c_ulong::MAX as usize;
3196
3197    // conservative upper bound for compressed data
3198    let comp_len = source_len
3199        .wrapping_add((source_len.wrapping_add(7) & mask) >> 3)
3200        .wrapping_add((source_len.wrapping_add(63) & mask) >> 6)
3201        .wrapping_add(5);
3202
3203    let Some(stream) = stream else {
3204        // return conservative bound plus zlib wrapper
3205        return comp_len.wrapping_add(6);
3206    };
3207
3208    /* compute wrapper length */
3209    let wrap_len = match stream.state.wrap {
3210        0 => {
3211            // raw deflate
3212            0
3213        }
3214        1 => {
3215            // zlib wrapper
3216            if stream.state.strstart != 0 {
3217                ZLIB_WRAPLEN + 4
3218            } else {
3219                ZLIB_WRAPLEN
3220            }
3221        }
3222        2 => {
3223            // gzip wrapper
3224            let mut gz_wrap_len = GZIP_WRAPLEN;
3225
3226            if let Some(header) = &stream.state.gzhead {
3227                if !header.extra.is_null() {
3228                    gz_wrap_len += 2 + header.extra_len as usize;
3229                }
3230
3231                let mut c_string = header.name;
3232                if !c_string.is_null() {
3233                    loop {
3234                        gz_wrap_len += 1;
3235                        // SAFETY: user guarantees header.name is a valid C string.
3236                        unsafe {
3237                            if *c_string == 0 {
3238                                break;
3239                            }
3240                            c_string = c_string.add(1);
3241                        }
3242                    }
3243                }
3244
3245                let mut c_string = header.comment;
3246                if !c_string.is_null() {
3247                    loop {
3248                        gz_wrap_len += 1;
3249                        // SAFETY: user guarantees header.comment is a valid C string.
3250                        unsafe {
3251                            if *c_string == 0 {
3252                                break;
3253                            }
3254                            c_string = c_string.add(1);
3255                        }
3256                    }
3257                }
3258
3259                if header.hcrc != 0 {
3260                    gz_wrap_len += 2;
3261                }
3262            }
3263
3264            gz_wrap_len
3265        }
3266        _ => {
3267            // default
3268            ZLIB_WRAPLEN
3269        }
3270    };
3271
3272    if stream.state.w_bits() != MAX_WBITS as u32 || HASH_BITS < 15 {
3273        if stream.state.level == 0 {
3274            /* upper bound for stored blocks with length 127 (memLevel == 1) ~4% overhead plus a small constant */
3275            source_len
3276                .wrapping_add(source_len >> 5)
3277                .wrapping_add(source_len >> 7)
3278                .wrapping_add(source_len >> 11)
3279                .wrapping_add(7)
3280                .wrapping_add(wrap_len)
3281        } else {
3282            comp_len.wrapping_add(wrap_len)
3283        }
3284    } else {
3285        compress_bound_help(source_len, wrap_len)
3286    }
3287}
3288
3289/// # Safety
3290///
3291/// The `dictionary` must have enough space for the dictionary.
3292pub unsafe fn get_dictionary(stream: &DeflateStream<'_>, dictionary: *mut u8) -> usize {
3293    let s = &stream.state;
3294    let len = Ord::min(s.strstart + s.lookahead, s.w_size);
3295
3296    if !dictionary.is_null() && len > 0 {
3297        unsafe {
3298            core::ptr::copy_nonoverlapping(
3299                s.window.as_ptr().add(s.strstart + s.lookahead - len),
3300                dictionary,
3301                len,
3302            );
3303        }
3304    }
3305
3306    len
3307}
3308
3309struct DeflateAllocOffsets {
3310    total_size: usize,
3311    state_pos: usize,
3312    window_pos: usize,
3313    pending_pos: usize,
3314    sym_buf_pos: usize,
3315    prev_pos: usize,
3316    head_pos: usize,
3317}
3318
3319impl DeflateAllocOffsets {
3320    fn new(window_bits: usize, lit_bufsize: usize) -> Self {
3321        use core::mem::size_of;
3322
3323        // 64B alignment of individual items in the alloc.
3324        // Note that changing this also requires changes in 'init' and 'copy'.
3325        const ALIGN_SIZE: usize = 64;
3326        const LIT_BUFS: usize = 4;
3327
3328        let mut curr_size = 0usize;
3329
3330        /* Define sizes */
3331        let state_size = size_of::<State>();
3332        // Allocate a second window worth of space to avoid the need to shift the data constantly.
3333        let window_size = (1 << window_bits) * 2;
3334        let prev_size = (1 << window_bits) * size_of::<Pos>();
3335        let head_size = HASH_SIZE * size_of::<Pos>();
3336        let pending_size = lit_bufsize * LIT_BUFS;
3337        let sym_buf_size = lit_bufsize * (LIT_BUFS - 1);
3338        // let alloc_size = size_of::<DeflateAlloc>();
3339
3340        /* Calculate relative buffer positions and paddings */
3341        let state_pos = curr_size.next_multiple_of(ALIGN_SIZE);
3342        curr_size = state_pos + state_size;
3343
3344        let window_pos = curr_size.next_multiple_of(ALIGN_SIZE);
3345        curr_size = window_pos + window_size;
3346
3347        let prev_pos = curr_size.next_multiple_of(ALIGN_SIZE);
3348        curr_size = prev_pos + prev_size;
3349
3350        let head_pos = curr_size.next_multiple_of(ALIGN_SIZE);
3351        curr_size = head_pos + head_size;
3352
3353        let pending_pos = curr_size.next_multiple_of(ALIGN_SIZE);
3354        curr_size = pending_pos + pending_size;
3355
3356        let sym_buf_pos = curr_size.next_multiple_of(ALIGN_SIZE);
3357        curr_size = sym_buf_pos + sym_buf_size;
3358
3359        /* Add ALIGN_SIZE-1 to allow alignment (done in the 'init' and 'copy' functions), and round
3360         * size of buffer up to next multiple of ALIGN_SIZE */
3361        let total_size = (curr_size + (ALIGN_SIZE - 1)).next_multiple_of(ALIGN_SIZE);
3362
3363        Self {
3364            total_size,
3365            state_pos,
3366            window_pos,
3367            pending_pos,
3368            sym_buf_pos,
3369            prev_pos,
3370            head_pos,
3371        }
3372    }
3373}
3374
3375#[cfg(test)]
3376mod test {
3377    use crate::{
3378        inflate::{decompress_slice, InflateConfig, InflateStream},
3379        InflateFlush,
3380    };
3381
3382    use super::*;
3383
3384    use core::{ffi::CStr, sync::atomic::AtomicUsize};
3385
3386    #[test]
3387    fn detect_data_type_basic() {
3388        let empty = || [Value::new(0, 0); LITERALS];
3389
3390        assert_eq!(State::detect_data_type(&empty()), DataType::Binary);
3391
3392        let mut binary = empty();
3393        binary[0] = Value::new(1, 0);
3394        assert_eq!(State::detect_data_type(&binary), DataType::Binary);
3395
3396        let mut text = empty();
3397        text[b'\r' as usize] = Value::new(1, 0);
3398        assert_eq!(State::detect_data_type(&text), DataType::Text);
3399
3400        let mut text = empty();
3401        text[b'a' as usize] = Value::new(1, 0);
3402        assert_eq!(State::detect_data_type(&text), DataType::Text);
3403
3404        let mut non_text = empty();
3405        non_text[7] = Value::new(1, 0);
3406        assert_eq!(State::detect_data_type(&non_text), DataType::Binary);
3407    }
3408
3409    #[test]
3410    fn from_stream_mut() {
3411        unsafe {
3412            assert!(DeflateStream::from_stream_mut(core::ptr::null_mut()).is_none());
3413
3414            let mut stream = z_stream::default();
3415            assert!(DeflateStream::from_stream_mut(&mut stream).is_none());
3416
3417            // state is still NULL
3418            assert!(DeflateStream::from_stream_mut(&mut stream).is_none());
3419
3420            init(&mut stream, DeflateConfig::default());
3421            let stream = DeflateStream::from_stream_mut(&mut stream);
3422            assert!(stream.is_some());
3423
3424            assert!(end(stream.unwrap()).is_ok());
3425        }
3426    }
3427
3428    #[cfg(feature = "c-allocator")]
3429    unsafe extern "C" fn fail_nth_allocation<const N: usize>(
3430        opaque: crate::c_api::voidpf,
3431        items: crate::c_api::uInt,
3432        size: crate::c_api::uInt,
3433    ) -> crate::c_api::voidpf {
3434        let count = unsafe { &*(opaque as *const AtomicUsize) };
3435
3436        if count.fetch_add(1, core::sync::atomic::Ordering::Relaxed) != N {
3437            // must use the C allocator internally because (de)allocation is based on function
3438            // pointer values and because we don't use the rust allocator directly, the allocation
3439            // logic will store the pointer to the start at the start of the allocation.
3440            unsafe { (crate::allocate::C.zalloc)(opaque, items, size) }
3441        } else {
3442            core::ptr::null_mut()
3443        }
3444    }
3445
3446    #[test]
3447    #[cfg(feature = "c-allocator")]
3448    fn init_invalid_allocator() {
3449        {
3450            let atomic = AtomicUsize::new(0);
3451            let mut stream = z_stream {
3452                zalloc: Some(fail_nth_allocation::<0>),
3453                zfree: Some(crate::allocate::C.zfree),
3454                opaque: &atomic as *const _ as *const core::ffi::c_void as *mut _,
3455                ..z_stream::default()
3456            };
3457            assert_eq!(
3458                init(&mut stream, DeflateConfig::default()),
3459                ReturnCode::MemError
3460            );
3461        }
3462    }
3463
3464    #[test]
3465    #[cfg(feature = "c-allocator")]
3466    fn copy_invalid_allocator() {
3467        let mut stream = z_stream::default();
3468
3469        let atomic = AtomicUsize::new(0);
3470        stream.opaque = &atomic as *const _ as *const core::ffi::c_void as *mut _;
3471        stream.zalloc = Some(fail_nth_allocation::<1>);
3472        stream.zfree = Some(crate::allocate::C.zfree);
3473
3474        // init performs 6 allocations; we don't want those to fail
3475        assert_eq!(init(&mut stream, DeflateConfig::default()), ReturnCode::Ok);
3476
3477        let Some(stream) = (unsafe { DeflateStream::from_stream_mut(&mut stream) }) else {
3478            unreachable!()
3479        };
3480
3481        let mut stream_copy = MaybeUninit::<DeflateStream>::zeroed();
3482
3483        assert_eq!(copy(&mut stream_copy, stream), ReturnCode::MemError);
3484
3485        assert!(end(stream).is_ok());
3486    }
3487
3488    mod invalid_deflate_config {
3489        use super::*;
3490
3491        #[test]
3492        fn sanity_check() {
3493            let mut stream = z_stream::default();
3494            assert_eq!(init(&mut stream, DeflateConfig::default()), ReturnCode::Ok);
3495
3496            assert!(stream.zalloc.is_some());
3497            assert!(stream.zfree.is_some());
3498
3499            // this should be the default level
3500            let stream = unsafe { DeflateStream::from_stream_mut(&mut stream) }.unwrap();
3501            assert_eq!(stream.state.level, 6);
3502
3503            assert!(end(stream).is_ok());
3504        }
3505
3506        #[test]
3507        fn window_bits_correction() {
3508            // window_bits of 8 gets turned into 9 internally
3509            let mut stream = z_stream::default();
3510            let config = DeflateConfig {
3511                window_bits: 8,
3512                ..Default::default()
3513            };
3514            assert_eq!(init(&mut stream, config), ReturnCode::Ok);
3515            let stream = unsafe { DeflateStream::from_stream_mut(&mut stream) }.unwrap();
3516            assert_eq!(stream.state.w_bits(), 9);
3517
3518            assert!(end(stream).is_ok());
3519        }
3520
3521        #[test]
3522        fn window_bits_too_low() {
3523            let mut stream = z_stream::default();
3524            let config = DeflateConfig {
3525                window_bits: -16,
3526                ..Default::default()
3527            };
3528            assert_eq!(init(&mut stream, config), ReturnCode::StreamError);
3529        }
3530
3531        #[test]
3532        fn window_bits_too_high() {
3533            // window bits too high
3534            let mut stream = z_stream::default();
3535            let config = DeflateConfig {
3536                window_bits: 42,
3537                ..Default::default()
3538            };
3539            assert_eq!(init(&mut stream, config), ReturnCode::StreamError);
3540        }
3541    }
3542
3543    #[test]
3544    fn end_data_error() {
3545        let mut stream = z_stream::default();
3546        assert_eq!(init(&mut stream, DeflateConfig::default()), ReturnCode::Ok);
3547        let stream = unsafe { DeflateStream::from_stream_mut(&mut stream) }.unwrap();
3548
3549        // next deflate into too little space
3550        let input = b"Hello World\n";
3551        stream.next_in = input.as_ptr() as *mut u8;
3552        stream.avail_in = input.len() as _;
3553        let output = &mut [0, 0, 0];
3554        stream.next_out = output.as_mut_ptr();
3555        stream.avail_out = output.len() as _;
3556
3557        // the deflate is fine
3558        assert_eq!(deflate(stream, DeflateFlush::NoFlush), ReturnCode::Ok);
3559
3560        // but end is not
3561        assert!(end(stream).is_err());
3562    }
3563
3564    #[test]
3565    fn test_reset_keep() {
3566        let mut stream = z_stream::default();
3567        assert_eq!(init(&mut stream, DeflateConfig::default()), ReturnCode::Ok);
3568        let stream = unsafe { DeflateStream::from_stream_mut(&mut stream) }.unwrap();
3569
3570        // next deflate into too little space
3571        let input = b"Hello World\n";
3572        stream.next_in = input.as_ptr() as *mut u8;
3573        stream.avail_in = input.len() as _;
3574
3575        let output = &mut [0; 1024];
3576        stream.next_out = output.as_mut_ptr();
3577        stream.avail_out = output.len() as _;
3578        assert_eq!(deflate(stream, DeflateFlush::Finish), ReturnCode::StreamEnd);
3579
3580        assert_eq!(reset_keep(stream), ReturnCode::Ok);
3581
3582        let output = &mut [0; 1024];
3583        stream.next_out = output.as_mut_ptr();
3584        stream.avail_out = output.len() as _;
3585        assert_eq!(deflate(stream, DeflateFlush::Finish), ReturnCode::StreamEnd);
3586
3587        assert!(end(stream).is_ok());
3588    }
3589
3590    #[test]
3591    fn hello_world_huffman_only() {
3592        const EXPECTED: &[u8] = &[
3593            0x78, 0x01, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x08, 0xcf, 0x2f, 0xca, 0x49, 0x51,
3594            0xe4, 0x02, 0x00, 0x20, 0x91, 0x04, 0x48,
3595        ];
3596
3597        let input = "Hello World!\n";
3598
3599        let mut output = vec![0; 128];
3600
3601        let config = DeflateConfig {
3602            level: 6,
3603            method: Method::Deflated,
3604            window_bits: crate::MAX_WBITS,
3605            mem_level: DEF_MEM_LEVEL,
3606            strategy: Strategy::HuffmanOnly,
3607        };
3608
3609        let (output, err) = compress_slice(&mut output, input.as_bytes(), config);
3610
3611        assert_eq!(err, ReturnCode::Ok);
3612
3613        assert_eq!(output.len(), EXPECTED.len());
3614
3615        assert_eq!(EXPECTED, output);
3616    }
3617
3618    #[test]
3619    fn hello_world_quick() {
3620        const EXPECTED: &[u8] = &[
3621            0x78, 0x01, 0xf3, 0x48, 0xcd, 0xc9, 0xc9, 0x57, 0x08, 0xcf, 0x2f, 0xca, 0x49, 0x51,
3622            0xe4, 0x02, 0x00, 0x20, 0x91, 0x04, 0x48,
3623        ];
3624
3625        let input = "Hello World!\n";
3626
3627        let mut output = vec![0; 128];
3628
3629        let config = DeflateConfig {
3630            level: 1,
3631            method: Method::Deflated,
3632            window_bits: crate::MAX_WBITS,
3633            mem_level: DEF_MEM_LEVEL,
3634            strategy: Strategy::Default,
3635        };
3636
3637        let (output, err) = compress_slice(&mut output, input.as_bytes(), config);
3638
3639        assert_eq!(err, ReturnCode::Ok);
3640
3641        assert_eq!(output.len(), EXPECTED.len());
3642
3643        assert_eq!(EXPECTED, output);
3644    }
3645
3646    #[test]
3647    fn hello_world_quick_random() {
3648        const EXPECTED: &[u8] = &[
3649            0x78, 0x01, 0x53, 0xe1, 0x50, 0x51, 0xe1, 0x52, 0x51, 0x51, 0x01, 0x00, 0x03, 0xec,
3650            0x00, 0xeb,
3651        ];
3652
3653        let input = "$\u{8}$$\n$$$";
3654
3655        let mut output = vec![0; 128];
3656
3657        let config = DeflateConfig {
3658            level: 1,
3659            method: Method::Deflated,
3660            window_bits: crate::MAX_WBITS,
3661            mem_level: DEF_MEM_LEVEL,
3662            strategy: Strategy::Default,
3663        };
3664
3665        let (output, err) = compress_slice(&mut output, input.as_bytes(), config);
3666
3667        assert_eq!(err, ReturnCode::Ok);
3668
3669        assert_eq!(output.len(), EXPECTED.len());
3670
3671        assert_eq!(EXPECTED, output);
3672    }
3673
3674    fn fuzz_based_test(input: &[u8], config: DeflateConfig, expected: &[u8]) {
3675        let mut output_rs = [0; 1 << 17];
3676        let (output_rs, err) = compress_slice(&mut output_rs, input, config);
3677        assert_eq!(err, ReturnCode::Ok);
3678
3679        assert_eq!(output_rs, expected);
3680    }
3681
3682    #[test]
3683    fn simple_rle() {
3684        fuzz_based_test(
3685            "\0\0\0\0\u{6}".as_bytes(),
3686            DeflateConfig {
3687                level: -1,
3688                method: Method::Deflated,
3689                window_bits: 11,
3690                mem_level: 4,
3691                strategy: Strategy::Rle,
3692            },
3693            &[56, 17, 99, 0, 2, 54, 0, 0, 11, 0, 7],
3694        )
3695    }
3696
3697    #[test]
3698    fn fill_window_out_of_bounds() {
3699        const INPUT: &[u8] = &[
3700            0x71, 0x71, 0x71, 0x71, 0x71, 0x6a, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3701            0x71, 0x71, 0x71, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x1d, 0x1d, 0x1d, 0x63,
3702            0x63, 0x63, 0x63, 0x63, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
3703            0x1d, 0x27, 0x0, 0x0, 0x0, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71,
3704            0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0,
3705            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3706            0x0, 0x0, 0x0, 0x0, 0x1d, 0x1d, 0x0, 0x0, 0x0, 0x0, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
3707            0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x48, 0x50,
3708            0x50, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x4a,
3709            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3710            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x70, 0x71, 0x71, 0x0, 0x0,
3711            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71, 0x71, 0x6a, 0x0, 0x0, 0x0, 0x0,
3712            0x71, 0x0, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3713            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3714            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3715            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x31, 0x0, 0x0, 0x0, 0x0,
3716            0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3717            0x71, 0x71, 0x0, 0x4a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71,
3718            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3719            0x70, 0x71, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71, 0x71,
3720            0x6a, 0x0, 0x0, 0x0, 0x0, 0x71, 0x0, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3721            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3722            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3723            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3724            0x31, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1d, 0x1d, 0x0, 0x0, 0x0, 0x0,
3725            0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
3726            0x50, 0x50, 0x50, 0x50, 0x48, 0x50, 0x0, 0x0, 0x71, 0x71, 0x71, 0x71, 0x3b, 0x3f, 0x71,
3727            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x50, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3728            0x2c, 0x0, 0x0, 0x0, 0x0, 0x4a, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71,
3729            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3730            0x71, 0x70, 0x71, 0x71, 0x0, 0x0, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71,
3731            0x71, 0x71, 0x71, 0x70, 0x71, 0x71, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3732            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x71, 0x71, 0x71, 0x71, 0x3b, 0x3f, 0x71, 0x71, 0x71,
3733            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3734            0x71, 0x3b, 0x3f, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x20, 0x0, 0x0, 0x0, 0x0,
3735            0x0, 0x0, 0x0, 0x71, 0x75, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3736            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x10, 0x0, 0x71, 0x71,
3737            0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x3b, 0x71, 0x71, 0x71, 0x71, 0x71,
3738            0x71, 0x76, 0x71, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x71, 0x71, 0x71, 0x71, 0x71,
3739            0x71, 0x71, 0x71, 0x10, 0x0, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
3740            0x71, 0x3b, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x76, 0x71, 0x34, 0x34, 0x34, 0x34,
3741            0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
3742            0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x34, 0x34, 0x34, 0x34,
3743            0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
3744            0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
3745            0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
3746            0x34, 0x34, 0x30, 0x34, 0x34, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3747            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3748            0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3749            0x0, 0x0, 0x71, 0x0, 0x0, 0x0, 0x0, 0x6,
3750        ];
3751
3752        fuzz_based_test(
3753            INPUT,
3754            DeflateConfig {
3755                level: -1,
3756                method: Method::Deflated,
3757                window_bits: 9,
3758                mem_level: 1,
3759                strategy: Strategy::HuffmanOnly,
3760            },
3761            &[
3762                0x18, 0x19, 0x4, 0xc1, 0x21, 0x1, 0xc4, 0x0, 0x10, 0x3, 0xb0, 0x18, 0x29, 0x1e,
3763                0x7e, 0x17, 0x83, 0xf5, 0x70, 0x6c, 0xac, 0xfe, 0xc9, 0x27, 0xdb, 0xb6, 0x6f, 0xdb,
3764                0xb6, 0x6d, 0xdb, 0x80, 0x24, 0xb9, 0xbb, 0xbb, 0x24, 0x49, 0x92, 0x24, 0xf, 0x2,
3765                0xd8, 0x36, 0x0, 0xf0, 0x3, 0x0, 0x0, 0x24, 0xd0, 0xb6, 0x6d, 0xdb, 0xb6, 0x6d,
3766                0xdb, 0xbe, 0x6d, 0xf9, 0x13, 0x4, 0xc7, 0x4, 0x0, 0x80, 0x30, 0x0, 0xc3, 0x22,
3767                0x68, 0xf, 0x36, 0x90, 0xc2, 0xb5, 0xfa, 0x7f, 0x48, 0x80, 0x81, 0xb, 0x40, 0x55,
3768                0x55, 0x55, 0xd5, 0x16, 0x80, 0xaa, 0x7, 0x9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
3769                0xe, 0x7c, 0x82, 0xe0, 0x98, 0x0, 0x0, 0x0, 0x4, 0x60, 0x10, 0xf9, 0x8c, 0xe2,
3770                0xe5, 0xfa, 0x3f, 0x2, 0x54, 0x55, 0x55, 0x65, 0x0, 0xa8, 0xaa, 0xaa, 0xaa, 0xba,
3771                0x2, 0x50, 0xb5, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0x82, 0xe0, 0xd0,
3772                0x8a, 0x41, 0x0, 0x0, 0xa2, 0x58, 0x54, 0xb7, 0x60, 0x83, 0x9a, 0x6a, 0x4, 0x96,
3773                0x87, 0xba, 0x51, 0xf8, 0xfb, 0x9b, 0x26, 0xfc, 0x0, 0x1c, 0x7, 0x6c, 0xdb, 0xb6,
3774                0x6d, 0xdb, 0xb6, 0x6d, 0xf7, 0xa8, 0x3a, 0xaf, 0xaa, 0x6a, 0x3, 0xf8, 0xc2, 0x3,
3775                0x40, 0x55, 0x55, 0x55, 0xd5, 0x5b, 0xf8, 0x80, 0xaa, 0x7a, 0xb, 0x0, 0x7f, 0x82,
3776                0xe0, 0x98, 0x0, 0x40, 0x18, 0x0, 0x82, 0xd8, 0x49, 0x40, 0x2, 0x22, 0x7e, 0xeb,
3777                0x80, 0xa6, 0xc, 0xa0, 0x9f, 0xa4, 0x2a, 0x38, 0xf, 0x0, 0x0, 0xe7, 0x1, 0xdc,
3778                0x55, 0x95, 0x17, 0x0, 0x0, 0xae, 0x0, 0x38, 0xc0, 0x67, 0xdb, 0x36, 0x80, 0x2b,
3779                0x0, 0xe, 0xf0, 0xd9, 0xf6, 0x13, 0x4, 0xc7, 0x4, 0x0, 0x0, 0x30, 0xc, 0x83, 0x22,
3780                0x69, 0x7, 0xc6, 0xea, 0xff, 0x19, 0x0, 0x0, 0x80, 0xaa, 0x0, 0x0, 0x0, 0x0, 0x0,
3781                0x0, 0x8e, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x6a,
3782                0xf5, 0x63, 0x60, 0x60, 0x3, 0x0, 0xee, 0x8a, 0x88, 0x67,
3783            ],
3784        )
3785    }
3786
3787    #[test]
3788    fn gzip_no_header() {
3789        let config = DeflateConfig {
3790            level: 9,
3791            method: Method::Deflated,
3792            window_bits: 31, // gzip
3793            ..Default::default()
3794        };
3795
3796        let input = b"Hello World!";
3797        let os = gz_header::OS_CODE;
3798
3799        fuzz_based_test(
3800            input,
3801            config,
3802            &[
3803                31, 139, 8, 0, 0, 0, 0, 0, 2, os, 243, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73,
3804                81, 4, 0, 163, 28, 41, 28, 12, 0, 0, 0,
3805            ],
3806        )
3807    }
3808
3809    #[test]
3810    #[rustfmt::skip]
3811    fn gzip_stored_block_checksum() {
3812        fuzz_based_test(
3813            &[
3814                27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 0,
3815            ],
3816            DeflateConfig {
3817                level: 0,
3818                method: Method::Deflated,
3819                window_bits: 26,
3820                mem_level: 6,
3821                strategy: Strategy::Default,
3822            },
3823            &[
3824                31, 139, 8, 0, 0, 0, 0, 0, 4, gz_header::OS_CODE, 1, 18, 0, 237, 255, 27, 27, 27, 27, 27, 27, 27,
3825                27, 27, 27, 27, 27, 27, 27, 27, 27, 9, 0, 60, 101, 156, 55, 18, 0, 0, 0,
3826            ],
3827        )
3828    }
3829
3830    #[test]
3831    fn gzip_header_pending_flush() {
3832        let extra = "aaaaaaaaaaaaaaaaaaaa\0";
3833        let name = "bbbbbbbbbbbbbbbbbbbb\0";
3834        let comment = "cccccccccccccccccccc\0";
3835
3836        let mut header = gz_header {
3837            text: 0,
3838            time: 0,
3839            xflags: 0,
3840            os: 0,
3841            extra: extra.as_ptr() as *mut _,
3842            extra_len: extra.len() as _,
3843            extra_max: 0,
3844            name: name.as_ptr() as *mut _,
3845            name_max: 0,
3846            comment: comment.as_ptr() as *mut _,
3847            comm_max: 0,
3848            hcrc: 1,
3849            done: 0,
3850        };
3851
3852        let config = DeflateConfig {
3853            window_bits: 31,
3854            mem_level: 1,
3855            ..Default::default()
3856        };
3857
3858        let mut stream = z_stream::default();
3859        assert_eq!(init(&mut stream, config), ReturnCode::Ok);
3860
3861        let Some(stream) = (unsafe { DeflateStream::from_stream_mut(&mut stream) }) else {
3862            unreachable!()
3863        };
3864
3865        unsafe { set_header(stream, Some(&mut header)) };
3866
3867        let input = b"Hello World\n";
3868        stream.next_in = input.as_ptr() as *mut _;
3869        stream.avail_in = input.len() as _;
3870
3871        let mut output = [0u8; 1024];
3872        stream.next_out = output.as_mut_ptr();
3873        stream.avail_out = 100;
3874
3875        assert_eq!(stream.state.bit_writer.pending.capacity(), 512);
3876
3877        // only 12 bytes remain, so to write the name the pending buffer must be flushed.
3878        // but there is insufficient output space to flush (only 100 bytes)
3879        stream.state.bit_writer.pending.extend(&[0; 500]);
3880
3881        assert_eq!(deflate(stream, DeflateFlush::Finish), ReturnCode::Ok);
3882
3883        // now try that again but with sufficient output space
3884        stream.avail_out = output.len() as _;
3885        assert_eq!(deflate(stream, DeflateFlush::Finish), ReturnCode::StreamEnd);
3886
3887        let n = stream.total_out as usize;
3888
3889        assert!(end(stream).is_ok());
3890
3891        let output_rs = &mut output[..n];
3892
3893        assert_eq!(output_rs.len(), 500 + 99);
3894    }
3895
3896    #[test]
3897    fn gzip_with_header() {
3898        // this test is here mostly so we get some MIRI action on the gzip header. A test that
3899        // compares behavior with zlib-ng is in the libz-rs-sys test suite
3900
3901        let extra = "some extra stuff\0";
3902        let name = "nomen est omen\0";
3903        let comment = "such comment\0";
3904
3905        let mut header = gz_header {
3906            text: 0,
3907            time: 0,
3908            xflags: 0,
3909            os: 0,
3910            extra: extra.as_ptr() as *mut _,
3911            extra_len: extra.len() as _,
3912            extra_max: 0,
3913            name: name.as_ptr() as *mut _,
3914            name_max: 0,
3915            comment: comment.as_ptr() as *mut _,
3916            comm_max: 0,
3917            hcrc: 1,
3918            done: 0,
3919        };
3920
3921        let config = DeflateConfig {
3922            window_bits: 31,
3923            ..Default::default()
3924        };
3925
3926        let mut stream = z_stream::default();
3927        assert_eq!(init(&mut stream, config), ReturnCode::Ok);
3928
3929        let Some(stream) = (unsafe { DeflateStream::from_stream_mut(&mut stream) }) else {
3930            unreachable!()
3931        };
3932
3933        unsafe { set_header(stream, Some(&mut header)) };
3934
3935        let input = b"Hello World\n";
3936        stream.next_in = input.as_ptr() as *mut _;
3937        stream.avail_in = input.len() as _;
3938
3939        let mut output = [0u8; 256];
3940        stream.next_out = output.as_mut_ptr();
3941        stream.avail_out = output.len() as _;
3942
3943        assert_eq!(deflate(stream, DeflateFlush::Finish), ReturnCode::StreamEnd);
3944
3945        let n = stream.total_out as usize;
3946
3947        assert!(end(stream).is_ok());
3948
3949        let output_rs = &mut output[..n];
3950
3951        assert_eq!(output_rs.len(), 81);
3952
3953        {
3954            let mut stream = z_stream::default();
3955
3956            let config = InflateConfig {
3957                window_bits: config.window_bits,
3958            };
3959
3960            assert_eq!(crate::inflate::init(&mut stream, config), ReturnCode::Ok);
3961
3962            let Some(stream) = (unsafe { InflateStream::from_stream_mut(&mut stream) }) else {
3963                unreachable!();
3964            };
3965
3966            stream.next_in = output_rs.as_mut_ptr() as _;
3967            stream.avail_in = output_rs.len() as _;
3968
3969            let mut output = [0u8; 12];
3970            stream.next_out = output.as_mut_ptr();
3971            stream.avail_out = output.len() as _;
3972
3973            let mut extra_buf = [0u8; 64];
3974            let mut name_buf = [0u8; 64];
3975            let mut comment_buf = [0u8; 64];
3976
3977            let mut header = gz_header {
3978                text: 0,
3979                time: 0,
3980                xflags: 0,
3981                os: 0,
3982                extra: extra_buf.as_mut_ptr(),
3983                extra_len: 0,
3984                extra_max: extra_buf.len() as _,
3985                name: name_buf.as_mut_ptr(),
3986                name_max: name_buf.len() as _,
3987                comment: comment_buf.as_mut_ptr(),
3988                comm_max: comment_buf.len() as _,
3989                hcrc: 0,
3990                done: 0,
3991            };
3992
3993            assert_eq!(
3994                unsafe { crate::inflate::get_header(stream, Some(&mut header)) },
3995                ReturnCode::Ok
3996            );
3997
3998            assert_eq!(
3999                unsafe { crate::inflate::inflate(stream, InflateFlush::Finish) },
4000                ReturnCode::StreamEnd
4001            );
4002
4003            crate::inflate::end(stream);
4004
4005            assert!(!header.comment.is_null());
4006            assert_eq!(
4007                unsafe { CStr::from_ptr(header.comment.cast()) }
4008                    .to_str()
4009                    .unwrap(),
4010                comment.trim_end_matches('\0')
4011            );
4012
4013            assert!(!header.name.is_null());
4014            assert_eq!(
4015                unsafe { CStr::from_ptr(header.name.cast()) }
4016                    .to_str()
4017                    .unwrap(),
4018                name.trim_end_matches('\0')
4019            );
4020
4021            assert!(!header.extra.is_null());
4022            assert_eq!(
4023                unsafe { CStr::from_ptr(header.extra.cast()) }
4024                    .to_str()
4025                    .unwrap(),
4026                extra.trim_end_matches('\0')
4027            );
4028        }
4029    }
4030
4031    #[test]
4032    fn insufficient_compress_space() {
4033        const DATA: &[u8] = include_bytes!("deflate/test-data/inflate_buf_error.dat");
4034
4035        fn helper(deflate_buf: &mut [u8], deflate_err: ReturnCode) -> ReturnCode {
4036            let config = DeflateConfig {
4037                level: 0,
4038                method: Method::Deflated,
4039                window_bits: 10,
4040                mem_level: 6,
4041                strategy: Strategy::Default,
4042            };
4043
4044            let (output, err) = compress_slice(deflate_buf, DATA, config);
4045            assert_eq!(err, deflate_err);
4046
4047            let config = InflateConfig {
4048                window_bits: config.window_bits,
4049            };
4050
4051            let mut uncompr = [0; 1 << 17];
4052            let (uncompr, err) = decompress_slice(&mut uncompr, output, config);
4053
4054            if err == ReturnCode::Ok {
4055                assert_eq!(DATA, uncompr);
4056            }
4057
4058            err
4059        }
4060
4061        let mut output = [0; 1 << 17];
4062
4063        // this is too little space
4064        assert_eq!(
4065            helper(&mut output[..1 << 16], ReturnCode::BufError),
4066            ReturnCode::DataError
4067        );
4068
4069        // this is sufficient space
4070        assert_eq!(helper(&mut output, ReturnCode::Ok), ReturnCode::Ok);
4071    }
4072
4073    fn test_flush(flush: DeflateFlush, expected: &[u8]) {
4074        let input = b"Hello World!\n";
4075
4076        let config = DeflateConfig {
4077            level: 6, // use gzip
4078            method: Method::Deflated,
4079            window_bits: 16 + crate::MAX_WBITS,
4080            mem_level: DEF_MEM_LEVEL,
4081            strategy: Strategy::Default,
4082        };
4083
4084        let mut output_rs = vec![0; 128];
4085
4086        // with the flush modes that we test here, the deflate process still has `Status::Busy`,
4087        // and the `deflate` function will return `BufError` because more input is needed before
4088        // the flush can occur.
4089        let expected_err = ReturnCode::BufError;
4090
4091        let (rs, err) = compress_slice_with_flush(&mut output_rs, input, config, flush);
4092        assert_eq!(expected_err, err);
4093
4094        assert_eq!(rs, expected);
4095    }
4096
4097    #[test]
4098    #[rustfmt::skip]
4099    fn sync_flush() {
4100        test_flush(
4101            DeflateFlush::SyncFlush,
4102            &[
4103                31, 139, 8, 0, 0, 0, 0, 0, 0, gz_header::OS_CODE, 242, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73,
4104                81, 228, 2, 0, 0, 0, 255, 255,
4105            ],
4106        )
4107    }
4108
4109    #[test]
4110    #[rustfmt::skip]
4111    fn partial_flush() {
4112        test_flush(
4113            DeflateFlush::PartialFlush,
4114            &[
4115                31, 139, 8, 0, 0, 0, 0, 0, 0, gz_header::OS_CODE, 242, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73,
4116                81, 228, 2, 8,
4117            ],
4118        );
4119    }
4120
4121    #[test]
4122    #[rustfmt::skip]
4123    fn full_flush() {
4124        test_flush(
4125            DeflateFlush::FullFlush,
4126            &[
4127                31, 139, 8, 0, 0, 0, 0, 0, 0, gz_header::OS_CODE, 242, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73,
4128                81, 228, 2, 0, 0, 0, 255, 255,
4129            ],
4130        );
4131    }
4132
4133    #[test]
4134    #[rustfmt::skip]
4135    fn block_flush() {
4136        test_flush(
4137            DeflateFlush::Block,
4138            &[
4139                31, 139, 8, 0, 0, 0, 0, 0, 0, gz_header::OS_CODE, 242, 72, 205, 201, 201, 87, 8, 207, 47, 202, 73,
4140                81, 228, 2,
4141            ],
4142        );
4143    }
4144
4145    #[test]
4146    // splits the input into two, deflates them seperately and then joins the deflated byte streams
4147    // into something that can be correctly inflated again. This is the basic idea behind pigz, and
4148    // allows for parallel compression.
4149    fn split_deflate() {
4150        let input = "Hello World!\n";
4151
4152        let (input1, input2) = input.split_at(6);
4153
4154        let mut output1 = vec![0; 128];
4155        let mut output2 = vec![0; 128];
4156
4157        let config = DeflateConfig {
4158            level: 6, // use gzip
4159            method: Method::Deflated,
4160            window_bits: 16 + crate::MAX_WBITS,
4161            mem_level: DEF_MEM_LEVEL,
4162            strategy: Strategy::Default,
4163        };
4164
4165        // see also the docs on `SyncFlush`. it makes sure everything is flushed, ends on a byte
4166        // boundary, and that the final block does not have the "last block" bit set.
4167        let (prefix, err) = compress_slice_with_flush(
4168            &mut output1,
4169            input1.as_bytes(),
4170            config,
4171            DeflateFlush::SyncFlush,
4172        );
4173        assert_eq!(err, ReturnCode::BufError);
4174
4175        let (output2, err) = compress_slice_with_flush(
4176            &mut output2,
4177            input2.as_bytes(),
4178            config,
4179            DeflateFlush::Finish,
4180        );
4181        assert_eq!(err, ReturnCode::Ok);
4182
4183        let inflate_config = crate::inflate::InflateConfig {
4184            window_bits: 16 + 15,
4185        };
4186
4187        // cuts off the length and crc
4188        let (suffix, end) = output2.split_at(output2.len() - 8);
4189        let (crc2, len2) = end.split_at(4);
4190        let crc2 = u32::from_le_bytes(crc2.try_into().unwrap());
4191
4192        // cuts off the gzip header (10 bytes) from the front
4193        let suffix = &suffix[10..];
4194
4195        let mut result: Vec<u8> = Vec::new();
4196        result.extend(prefix.iter());
4197        result.extend(suffix);
4198
4199        // it would be more proper to use `stream.total_in` here, but the slice helpers hide the
4200        // stream so we're cheating a bit here
4201        let len1 = input1.len() as u32;
4202        let len2 = u32::from_le_bytes(len2.try_into().unwrap());
4203        assert_eq!(len2 as usize, input2.len());
4204
4205        let crc1 = crate::crc32::crc32(0, input1.as_bytes());
4206        let crc = crate::crc32::crc32_combine(crc1, crc2, len2 as u64);
4207
4208        // combined crc of the parts should be the crc of the whole
4209        let crc_cheating = crate::crc32::crc32(0, input.as_bytes());
4210        assert_eq!(crc, crc_cheating);
4211
4212        // write the trailer
4213        result.extend(crc.to_le_bytes());
4214        result.extend((len1 + len2).to_le_bytes());
4215
4216        let mut output = vec![0; 128];
4217        let (output, err) = crate::inflate::decompress_slice(&mut output, &result, inflate_config);
4218        assert_eq!(err, ReturnCode::Ok);
4219
4220        assert_eq!(output, input.as_bytes());
4221    }
4222
4223    #[test]
4224    fn inflate_window_copy_slice() {
4225        let uncompressed = [
4226            9, 126, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 76, 33, 8, 2, 0, 0,
4227            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4228            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4229            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4230            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12,
4231            10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 76, 33, 8, 2, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0,
4232            0, 0, 0, 12, 10, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4233            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 14, 0, 0, 0, 0, 0, 69, 69, 69, 69, 69, 69, 69,
4234            69, 69, 69, 69, 69, 69, 69, 69, 9, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4235            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4236            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4237            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 12, 28, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0,
4238            0, 0, 12, 10, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4239            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 14, 0, 0, 0, 0, 0, 69, 69, 69, 69, 69, 69, 69,
4240            69, 69, 69, 69, 69, 69, 69, 69, 9, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4241            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4242            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
4243            69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 12, 28, 0, 2, 0, 0, 0, 63, 1, 0, 12, 2,
4244            36, 0, 28, 0, 0, 0, 1, 0, 0, 63, 63, 13, 0, 0, 0, 0, 0, 0, 0, 63, 63, 63, 63, 0, 0, 0,
4245            0, 0, 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0,
4246            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4247            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4248            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 0, 9, 0, 0, 0, 9, 0, 0, 12, 33, 2, 0, 0, 8,
4249            0, 4, 0, 0, 0, 12, 10, 41, 12, 10, 47,
4250        ];
4251
4252        let compressed = &[
4253            31, 139, 8, 0, 0, 0, 0, 0, 4, 3, 181, 193, 49, 14, 194, 32, 24, 128, 209, 175, 192, 0,
4254            228, 151, 232, 206, 66, 226, 226, 96, 60, 2, 113, 96, 235, 13, 188, 139, 103, 23, 106,
4255            104, 108, 100, 49, 169, 239, 185, 39, 11, 199, 7, 51, 39, 171, 248, 118, 226, 63, 52,
4256            157, 120, 86, 102, 78, 86, 209, 104, 58, 241, 84, 129, 166, 12, 4, 154, 178, 229, 202,
4257            30, 36, 130, 166, 19, 79, 21, 104, 202, 64, 160, 41, 91, 174, 236, 65, 34, 10, 200, 19,
4258            162, 206, 68, 96, 130, 156, 15, 188, 229, 138, 197, 157, 161, 35, 3, 87, 126, 245, 0,
4259            28, 224, 64, 146, 2, 139, 1, 196, 95, 196, 223, 94, 10, 96, 92, 33, 86, 2, 0, 0,
4260        ];
4261
4262        let config = InflateConfig { window_bits: 25 };
4263
4264        let mut dest_vec_rs = vec![0u8; uncompressed.len()];
4265        let (output_rs, error) =
4266            crate::inflate::decompress_slice(&mut dest_vec_rs, compressed, config);
4267
4268        assert_eq!(ReturnCode::Ok, error);
4269        assert_eq!(output_rs, uncompressed);
4270    }
4271
4272    #[test]
4273    fn hash_calc_difference() {
4274        let input = [
4275            0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0,
4276            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4277            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4278            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4279            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0,
4280            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4281            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0,
4282            0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 64, 0, 0,
4283            0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, 102, 102, 102, 102,
4284            102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
4285            102, 102, 102, 102, 102, 102, 102, 102, 112, 102, 102, 102, 102, 102, 102, 102, 102,
4286            102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 0,
4287            0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4288            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4289            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4290            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4291            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
4292            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0,
4293            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 64, 0, 0, 0, 0, 0, 0, 0,
4294            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0,
4295            50, 0,
4296        ];
4297
4298        let config = DeflateConfig {
4299            level: 6,
4300            method: Method::Deflated,
4301            window_bits: 9,
4302            mem_level: 8,
4303            strategy: Strategy::Default,
4304        };
4305
4306        let expected = [
4307            24, 149, 99, 96, 96, 96, 96, 208, 6, 17, 112, 138, 129, 193, 128, 1, 29, 24, 50, 208,
4308            1, 200, 146, 169, 79, 24, 74, 59, 96, 147, 52, 71, 22, 70, 246, 88, 26, 94, 80, 128,
4309            83, 6, 162, 219, 144, 76, 183, 210, 5, 8, 67, 105, 36, 159, 35, 128, 57, 118, 97, 100,
4310            160, 197, 192, 192, 96, 196, 0, 0, 3, 228, 25, 128,
4311        ];
4312
4313        fuzz_based_test(&input, config, &expected);
4314    }
4315
4316    #[cfg(any(target_arch = "x86_64", target_arch = "aarch64"))]
4317    mod _cache_lines {
4318        use super::State;
4319        // FIXME: once zlib-rs Minimum Supported Rust Version >= 1.77, switch to core::mem::offset_of
4320        // and move this _cache_lines module from up a level from tests to super::
4321        use memoffset::offset_of;
4322
4323        const _: () = assert!(offset_of!(State, status) == 0);
4324        const _: () = assert!(offset_of!(State, _cache_line_0) == 64);
4325        const _: () = assert!(offset_of!(State, _cache_line_1) == 128);
4326        #[cfg(not(feature = "ZLIB_DEBUG"))] // ZLIB_DEBUG adds 16 bytes
4327        const _: () = assert!(offset_of!(State, _cache_line_2) == 192);
4328        #[cfg(not(feature = "ZLIB_DEBUG"))] // ZLIB_DEBUG adds 16 bytes
4329        const _: () = assert!(offset_of!(State, _cache_line_3) == 256);
4330    }
4331}