Skip to main content

libz_rs_sys/
lib.rs

1#![cfg_attr(feature = "gzprintf", feature(c_variadic))]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![allow(unsafe_op_in_unsafe_fn)] // FIXME
4#![allow(non_camel_case_types)]
5#![allow(non_snake_case)]
6#![cfg_attr(not(feature = "std"), no_std)]
7#![doc = include_str!("../README.md")]
8
9//! # Safety
10//!
11//! Most of the functions in this module are `unsafe fn`s, meaning that their behavior may be
12//! undefined if certain assumptions are broken by the caller. In most cases, documentation
13//! in this module refers to the safety assumptions of standard library functions.
14//!
15//! In most cases, pointers must be either `NULL` or satisfy the requirements of `&*ptr` or `&mut
16//! *ptr`. This requirement maps to the requirements of [`pointer::as_ref`] and [`pointer::as_mut`]
17//! for immutable and mutable pointers respectively.
18//!
19//! For pointer and length pairs, describing some sequence of elements in memory, the requirements
20//! of [`core::slice::from_raw_parts`] or [`core::slice::from_raw_parts_mut`] apply. In some cases,
21//! the element type `T` is converted into `MaybeUninit<T>`, meaning that while the slice must be
22//! valid, the elements in the slice can be uninitialized. Using uninitialized buffers for output
23//! is more performant.
24//!
25//! Finally, some functions accept a string argument, which must either be `NULL` or satisfy the
26//! requirements of [`core::ffi::CStr::from_ptr`].
27//!
28//! [`pointer::as_ref`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_ref
29//! [`pointer::as_mut`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_mut
30
31#[cfg(feature = "gz")]
32mod gz;
33
34#[cfg_attr(docsrs, doc(cfg(feature = "gz")))]
35#[cfg(feature = "gz")]
36pub use gz::*;
37use zlib_rs::{MAX_WBITS, MIN_WBITS};
38
39use core::mem::MaybeUninit;
40
41use core::ffi::{c_char, c_int, c_long, c_uchar, c_uint, c_ulong, c_void};
42
43use zlib_rs::{
44    deflate::{DeflateConfig, DeflateStream, Method, Strategy},
45    inflate::{InflateConfig, InflateStream},
46    DeflateFlush, InflateFlush, ReturnCode,
47};
48
49pub use zlib_rs::c_api::*;
50
51#[allow(non_camel_case_types)]
52pub type size_t = usize;
53
54#[cfg(feature = "custom-prefix")]
55macro_rules! prefix {
56    ($name:expr) => {
57        concat!(env!("LIBZ_RS_SYS_PREFIX"), stringify!($name))
58    };
59}
60
61// NOTE: once we reach 1.0.0, the macro used for the `semver-prefix` feature should no longer include the
62// minor version in the name. The name is meant to be unique between semver-compatible versions!
63const _PRE_ONE_DOT_O: () = assert!(env!("CARGO_PKG_VERSION_MAJOR").as_bytes()[0] == b'0');
64
65#[cfg(feature = "semver-prefix")]
66macro_rules! prefix {
67    ($name:expr) => {
68        concat!(
69            "LIBZ_RS_SYS_v",
70            env!("CARGO_PKG_VERSION_MAJOR"),
71            "_",
72            env!("CARGO_PKG_VERSION_MINOR"),
73            "_x_",
74            stringify!($name)
75        )
76    };
77}
78
79#[cfg(all(
80    not(feature = "custom-prefix"),
81    not(feature = "semver-prefix"),
82    not(any(test, feature = "testing-prefix"))
83))]
84macro_rules! prefix {
85    ($name:expr) => {
86        stringify!($name)
87    };
88}
89
90#[cfg(all(
91    not(feature = "custom-prefix"),
92    not(feature = "semver-prefix"),
93    any(test, feature = "testing-prefix")
94))]
95macro_rules! prefix {
96    ($name:expr) => {
97        concat!("LIBZ_RS_SYS_TEST_", stringify!($name))
98    };
99}
100
101#[cfg(feature = "gz")]
102pub(crate) use prefix;
103
104#[cfg(all(feature = "rust-allocator", feature = "c-allocator"))]
105const _: () =
106    compile_error!("Only one of `rust-allocator` and `c-allocator` can be enabled at a time");
107
108// In spirit this type is `libc::off_t`, but it would be our only libc dependency, and so we
109// hardcode the type here. This should be correct on most operating systems. If we ever run into
110// issues with it, we can either special-case or add a feature flag to force a particular width
111#[cfg(not(target_arch = "wasm32"))]
112pub type z_off_t = c_long;
113
114#[cfg(target_arch = "wasm32")]
115pub type z_off_t = i64;
116
117#[cfg(not(all(windows, target_env = "gnu")))]
118pub type z_off64_t = i64;
119
120// on windows gnu, z_off64_t is actually 32-bit ...
121#[cfg(all(windows, target_env = "gnu"))]
122pub type z_off64_t = z_off_t;
123
124/// Calculates the [crc32](https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks#CRC-32_algorithm) checksum
125/// of a sequence of bytes.
126///
127/// When the pointer argument is `NULL`, the initial checksum value is returned.
128///
129/// # Safety
130///
131/// The caller must guarantee that either:
132///
133/// - `buf` is `NULL`
134/// - `buf` and `len` satisfy the requirements of [`core::slice::from_raw_parts`]
135///
136/// # Example
137///
138/// ```
139/// use libz_rs_sys::crc32_z;
140///
141/// unsafe {
142///     assert_eq!(crc32_z(0, core::ptr::null(), 0), 0);
143///     assert_eq!(crc32_z(1, core::ptr::null(), 32), 0);
144///
145///     let input = [1,2,3];
146///     assert_eq!(crc32_z(0, input.as_ptr(), input.len() as _), 1438416925);
147/// }
148/// ```
149#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_z))]
150pub unsafe extern "C" fn crc32_z(crc: c_ulong, buf: *const Bytef, len: size_t) -> c_ulong {
151    match unsafe { slice_from_raw_parts(buf, len) } {
152        Some(buf) => zlib_rs::crc32::crc32(crc as u32, buf) as c_ulong,
153        None => 0,
154    }
155}
156
157/// Calculates the [crc32](https://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks#CRC-32_algorithm) checksum
158/// of a sequence of bytes.
159///
160/// When the pointer argument is `NULL`, the initial checksum value is returned.
161///
162/// # Safety
163///
164/// The caller must guarantee that either:
165///
166/// - `buf` is `NULL`
167/// - `buf` and `len` satisfy the requirements of [`core::slice::from_raw_parts`]
168///
169/// # Example
170///
171/// ```
172/// use libz_rs_sys::crc32;
173///
174/// unsafe {
175///     assert_eq!(crc32(0, core::ptr::null(), 0), 0);
176///     assert_eq!(crc32(1, core::ptr::null(), 32), 0);
177///
178///     let input = [1,2,3];
179///     assert_eq!(crc32(0, input.as_ptr(), input.len() as _), 1438416925);
180/// }
181/// ```
182#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32))]
183pub unsafe extern "C" fn crc32(crc: c_ulong, buf: *const Bytef, len: uInt) -> c_ulong {
184    crc32_z(crc, buf, len as size_t)
185}
186
187/// Combines the checksum of two slices into one.
188///
189/// The combined value is equivalent to calculating the checksum of the whole input.
190///
191/// This function can be used when input arrives in chunks, or when different threads
192/// calculate the checksum of different sections of the input.
193///
194/// # Example
195///
196/// ```
197/// use libz_rs_sys::{crc32, crc32_combine};
198///
199/// let input = [1, 2, 3, 4, 5, 6, 7, 8];
200/// let lo = &input[..4];
201/// let hi = &input[4..];
202///
203/// unsafe {
204///     let full = crc32(0, input.as_ptr(), input.len() as _);
205///
206///     let crc1 = crc32(0, lo.as_ptr(), lo.len() as _);
207///     let crc2 = crc32(0, hi.as_ptr(), hi.len() as _);
208///
209///     let combined = crc32_combine(crc1, crc2, hi.len() as _);
210///
211///     assert_eq!(full, combined);
212/// }
213/// ```
214#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine))]
215pub extern "C" fn crc32_combine(crc1: c_ulong, crc2: c_ulong, len2: z_off_t) -> c_ulong {
216    zlib_rs::crc32::crc32_combine(crc1 as u32, crc2 as u32, len2 as u64) as c_ulong
217}
218
219/// Combines the checksum of two slices into one.
220///
221/// The combined value is equivalent to calculating the checksum of the whole input.
222///
223/// This function can be used when input arrives in chunks, or when different threads
224/// calculate the checksum of different sections of the input.
225///
226/// # Example
227///
228/// ```
229/// use libz_rs_sys::{crc32, crc32_combine64};
230///
231/// let input = [1, 2, 3, 4, 5, 6, 7, 8];
232/// let lo = &input[..4];
233/// let hi = &input[4..];
234///
235/// unsafe {
236///     let full = crc32(0, input.as_ptr(), input.len() as _);
237///
238///     let crc1 = crc32(0, lo.as_ptr(), lo.len() as _);
239///     let crc2 = crc32(0, hi.as_ptr(), hi.len() as _);
240///
241///     let combined = crc32_combine64(crc1, crc2, hi.len() as _);
242///
243///     assert_eq!(full, combined);
244/// }
245/// ```
246#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine64))]
247pub extern "C" fn crc32_combine64(crc1: c_ulong, crc2: c_ulong, len2: z_off64_t) -> c_ulong {
248    zlib_rs::crc32::crc32_combine(crc1 as u32, crc2 as u32, len2 as u64) as c_ulong
249}
250
251/// The CRC table used by the crc32 checksum algorithm.
252#[cfg_attr(feature = "export-symbols", export_name = prefix!(get_crc_table))]
253pub extern "C" fn get_crc_table() -> *const [u32; 256] {
254    zlib_rs::crc32::get_crc_table()
255}
256
257/// Return the operator corresponding to length `len2`, to be used with
258/// [`crc32_combine_op`]. `len2` must be non-negative.
259#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine_gen64))]
260pub const extern "C" fn crc32_combine_gen64(len2: z_off64_t) -> c_ulong {
261    debug_assert!(len2 >= 0, "`len2` must be non-negative");
262    zlib_rs::crc32::crc32_combine_gen(len2 as u64) as c_ulong
263}
264
265/// Return the operator corresponding to length `len2`, to be used with
266/// [`crc32_combine_op`]. `len2` must be non-negative.
267#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine_gen))]
268pub const extern "C" fn crc32_combine_gen(len2: z_off_t) -> c_ulong {
269    debug_assert!(len2 >= 0, "`len2` must be non-negative");
270    zlib_rs::crc32::crc32_combine_gen(len2 as u64) as c_ulong
271}
272
273/// Give the same result as [`crc32_combine`], using `op` in place of `len2`.
274/// `op` is is generated from `len2` by [`crc32_combine_gen`].
275/// This will be faster than [`crc32_combine`] if the generated `op` is used more than once.
276#[cfg_attr(feature = "export-symbols", export_name = prefix!(crc32_combine_op))]
277pub const extern "C" fn crc32_combine_op(crc1: c_ulong, crc2: c_ulong, op: c_ulong) -> c_ulong {
278    zlib_rs::crc32::crc32_combine_op(crc1 as u32, crc2 as u32, op as u32) as c_ulong
279}
280
281/// Calculates the [adler32](https://en.wikipedia.org/wiki/Adler-32) checksum
282/// of a sequence of bytes.
283///
284/// When the pointer argument is `NULL`, the initial checksum value is returned.
285///
286/// # Safety
287///
288/// The caller must guarantee that either:
289///
290/// - `buf` is `NULL`
291/// - `buf` and `len` satisfy the requirements of [`core::slice::from_raw_parts`]
292///
293/// # Example
294///
295/// ```
296/// use libz_rs_sys::adler32_z;
297///
298/// unsafe {
299///     assert_eq!(adler32_z(0, core::ptr::null(), 0), 1);
300///     assert_eq!(adler32_z(1, core::ptr::null(), 32), 1);
301///
302///     let input = [1,2,3];
303///     assert_eq!(adler32_z(0, input.as_ptr(), input.len() as _), 655366);
304/// }
305/// ```
306#[cfg_attr(feature = "export-symbols", export_name = prefix!(adler32_z))]
307pub unsafe extern "C" fn adler32_z(adler: c_ulong, buf: *const Bytef, len: size_t) -> c_ulong {
308    match unsafe { slice_from_raw_parts(buf, len) } {
309        Some(buf) => zlib_rs::adler32::adler32(adler as u32, buf) as c_ulong,
310        None => 1,
311    }
312}
313
314/// Calculates the [adler32](https://en.wikipedia.org/wiki/Adler-32) checksum
315/// of a sequence of bytes.
316///
317/// When the pointer argument is `NULL`, the initial checksum value is returned.
318///
319/// # Safety
320///
321/// The caller must guarantee that either:
322///
323/// - `buf` is `NULL`
324/// - `buf` and `len` satisfy the requirements of [`core::slice::from_raw_parts`]
325///
326/// # Example
327///
328/// ```
329/// use libz_rs_sys::adler32;
330///
331/// unsafe {
332///     assert_eq!(adler32(0, core::ptr::null(), 0), 1);
333///     assert_eq!(adler32(1, core::ptr::null(), 32), 1);
334///
335///     let input = [1,2,3];
336///     assert_eq!(adler32(0, input.as_ptr(), input.len() as _), 655366);
337/// }
338/// ```
339#[cfg_attr(feature = "export-symbols", export_name = prefix!(adler32))]
340pub unsafe extern "C" fn adler32(adler: c_ulong, buf: *const Bytef, len: uInt) -> c_ulong {
341    adler32_z(adler, buf, len as size_t)
342}
343
344/// Combines the checksum of two slices into one.
345///
346/// The combined value is equivalent to calculating the checksum of the whole input.
347///
348/// This function can be used when input arrives in chunks, or when different threads
349/// calculate the checksum of different sections of the input.
350///
351/// # Example
352///
353/// ```
354/// use libz_rs_sys::{adler32, adler32_combine};
355///
356/// let input = [1, 2, 3, 4, 5, 6, 7, 8];
357/// let lo = &input[..4];
358/// let hi = &input[4..];
359///
360/// unsafe {
361///     let full = adler32(1, input.as_ptr(), input.len() as _);
362///
363///     let adler1 = adler32(1, lo.as_ptr(), lo.len() as _);
364///     let adler2 = adler32(1, hi.as_ptr(), hi.len() as _);
365///
366///     let combined = adler32_combine(adler1, adler2, hi.len() as _);
367///
368///     assert_eq!(full, combined);
369/// }
370/// ```
371#[cfg_attr(feature = "export-symbols", export_name = prefix!(adler32_combine))]
372pub extern "C" fn adler32_combine(adler1: c_ulong, adler2: c_ulong, len2: z_off_t) -> c_ulong {
373    match u64::try_from(len2) {
374        Ok(len2) => {
375            zlib_rs::adler32::adler32_combine(adler1 as u32, adler2 as u32, len2) as c_ulong
376        }
377        Err(_) => {
378            // for negative len, return invalid adler32 as a clue for debugging
379            0xFFFF_FFFF
380        }
381    }
382}
383
384/// Combines the checksum of two slices into one.
385///
386/// The combined value is equivalent to calculating the checksum of the whole input.
387///
388/// This function can be used when input arrives in chunks, or when different threads
389/// calculate the checksum of different sections of the input.
390///
391/// # Example
392///
393/// ```
394/// use libz_rs_sys::{adler32, adler32_combine64};
395///
396/// let input = [1, 2, 3, 4, 5, 6, 7, 8];
397/// let lo = &input[..4];
398/// let hi = &input[4..];
399///
400/// unsafe {
401///     let full = adler32(1, input.as_ptr(), input.len() as _);
402///
403///     let adler1 = adler32(1, lo.as_ptr(), lo.len() as _);
404///     let adler2 = adler32(1, hi.as_ptr(), hi.len() as _);
405///
406///     let combined = adler32_combine64(adler1, adler2, hi.len() as _);
407///
408///     assert_eq!(full, combined);
409/// }
410/// ```
411#[cfg_attr(feature = "export-symbols", export_name = prefix!(adler32_combine64))]
412pub extern "C" fn adler32_combine64(adler1: c_ulong, adler2: c_ulong, len2: z_off64_t) -> c_ulong {
413    match u64::try_from(len2) {
414        Ok(len2) => {
415            zlib_rs::adler32::adler32_combine(adler1 as u32, adler2 as u32, len2) as c_ulong
416        }
417        Err(_) => {
418            // for negative len, return invalid adler32 as a clue for debugging
419            0xFFFF_FFFF
420        }
421    }
422}
423
424/// Like [`uncompress`] but takes a `usize` instead.
425///
426/// # Returns
427///
428/// Same as [`uncompress`].
429///
430/// # Safety
431///
432/// Same as [`uncompress`].
433#[cfg_attr(feature = "export-symbols", export_name = prefix!(uncompress_z))]
434pub unsafe extern "C" fn uncompress_z(
435    dest: *mut u8,
436    destLen: *mut usize,
437    source: *const u8,
438    mut sourceLen: usize,
439) -> c_int {
440    uncompress2_z(dest, destLen, source, &mut sourceLen)
441}
442
443/// Inflates `source` into `dest`, and writes the final inflated size into `destLen`.
444///
445/// Upon entry, `destLen` is the total size of the destination buffer, which must be large enough to hold the entire
446/// uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and
447/// transmitted to the decompressor by some mechanism outside the scope of this compression library.)
448/// Upon exit, `destLen` is the actual size of the uncompressed data.
449///
450/// # Returns
451///
452/// * [`Z_OK`] if success
453/// * [`Z_MEM_ERROR`] if there was not enough memory
454/// * [`Z_BUF_ERROR`] if there was not enough room in the output buffer
455/// * [`Z_DATA_ERROR`] if the input data was corrupted or incomplete
456///
457/// In the case where there is not enough room, [`uncompress`] will fill the output buffer with the uncompressed data up to that point.
458///
459/// # Safety
460///
461/// The caller must guarantee that
462///
463/// * Either
464///     - `destLen` is `NULL`
465///     - `destLen` satisfies the requirements of `&mut *destLen`
466/// * Either
467///     - `dest` is `NULL`
468///     - `dest` and `*destLen` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
469/// * Either
470///     - `source` is `NULL`
471///     - `source` and `sourceLen` satisfy the requirements of [`core::slice::from_raw_parts::<u8>`]
472///
473/// # Example
474///
475/// ```
476/// use libz_rs_sys::{Z_OK, uncompress};
477///
478/// let source = [120, 156, 115, 75, 45, 42, 202, 44, 6, 0, 8, 6, 2, 108];
479///
480/// let mut dest = vec![0u8; 100];
481/// let mut dest_len = dest.len() as _;
482///
483/// let err = unsafe {
484///     uncompress(
485///         dest.as_mut_ptr(),
486///         &mut dest_len,
487///         source.as_ptr(),
488///         source.len() as _,
489///     )
490/// };
491///
492/// assert_eq!(err, Z_OK);
493/// assert_eq!(dest_len, 6);
494///
495/// dest.truncate(dest_len as usize);
496/// assert_eq!(dest, b"Ferris");
497/// ```
498#[cfg_attr(feature = "export-symbols", export_name = prefix!(uncompress))]
499pub unsafe extern "C" fn uncompress(
500    dest: *mut u8,
501    destLen: *mut c_ulong,
502    source: *const u8,
503    mut sourceLen: c_ulong,
504) -> c_int {
505    uncompress2(dest, destLen, source, &mut sourceLen)
506}
507
508/// Like [`uncompress2`] but takes a `usize` instead.
509///
510/// # Returns
511///
512/// Same as [`uncompress2`].
513///
514/// # Safety
515///
516/// Same as [`uncompress2`].
517#[cfg_attr(feature = "export-symbols", export_name = prefix!(uncompress2_z))]
518pub unsafe extern "C" fn uncompress2_z(
519    dest: *mut u8,
520    destLen: *mut usize,
521    source: *const u8,
522    sourceLen: *mut usize,
523) -> c_int {
524    // stock zlib will just dereference a NULL pointer: that's UB.
525    // Hence us returning an error value is compatible
526    let Some(destLen) = (unsafe { destLen.as_mut() }) else {
527        return ReturnCode::StreamError as _;
528    };
529
530    let Some(sourceLen) = (unsafe { sourceLen.as_mut() }) else {
531        return ReturnCode::StreamError as _;
532    };
533
534    let Some(output) = (unsafe { slice_from_raw_parts_uninit_mut(dest, *destLen) }) else {
535        return ReturnCode::StreamError as _;
536    };
537
538    let Some(input) = (unsafe { slice_from_raw_parts(source, *sourceLen) }) else {
539        return ReturnCode::StreamError as _;
540    };
541
542    let config = InflateConfig::default();
543    let (consumed, output, err) = zlib_rs::inflate::uncompress2(output, input, config);
544
545    *sourceLen -= consumed as usize;
546    *destLen = output.len();
547
548    err as c_int
549}
550
551/// Inflates `source` into `dest` like [`uncompress`], and writes the final inflated size into `destLen` and the number
552/// of source bytes consumed into `sourceLen`.
553///
554/// Upon entry, `destLen` is the total size of the destination buffer, which must be large enough to hold the entire
555/// uncompressed data. (The size of the uncompressed data must have been saved previously by the compressor and
556/// transmitted to the decompressor by some mechanism outside the scope of this compression library.)
557/// Upon exit, `destLen` is the actual size of the uncompressed data.
558///
559/// # Returns
560///
561/// * [`Z_OK`] if success
562/// * [`Z_MEM_ERROR`] if there was not enough memory
563/// * [`Z_BUF_ERROR`] if there was not enough room in the output buffer
564/// * [`Z_DATA_ERROR`] if the input data was corrupted or incomplete
565///
566/// In the case where there is not enough room, [`uncompress2`] will fill the output buffer with the uncompressed data up to that point.
567///
568/// # Safety
569///
570/// The caller must guarantee that
571///
572/// * Either
573///     - `destLen` is `NULL`
574///     - `destLen` satisfies the requirements of `&mut *destLen`
575/// * Either
576///     - `dest` is `NULL`
577///     - `dest` and `*destLen` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
578/// * Either
579///     - `source` is `NULL`
580///     - `source` and `sourceLen` satisfy the requirements of [`core::slice::from_raw_parts::<u8>`]
581/// * `sourceLen` satisfies the requirements of `&mut *sourceLen`
582#[cfg_attr(feature = "export-symbols", export_name = prefix!(uncompress2))]
583pub unsafe extern "C" fn uncompress2(
584    dest: *mut u8,
585    destLen: *mut c_ulong,
586    source: *const u8,
587    sourceLen: *mut c_ulong,
588) -> c_int {
589    // stock zlib will just dereference a NULL pointer: that's UB.
590    // Hence us returning an error value is compatible
591    let Some(destLen) = (unsafe { destLen.as_mut() }) else {
592        return ReturnCode::StreamError as _;
593    };
594
595    let Some(sourceLen) = (unsafe { sourceLen.as_mut() }) else {
596        return ReturnCode::StreamError as _;
597    };
598
599    let mut got = *destLen as usize;
600    let mut used = *sourceLen as usize;
601
602    let err = uncompress2_z(dest, &mut got, source, &mut used);
603
604    *sourceLen = used as c_ulong;
605    *destLen = got as c_ulong;
606
607    err as c_int
608}
609
610/// Decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full.
611///
612/// # Returns
613///
614/// - [`Z_OK`] if success
615/// - [`Z_STREAM_END`] if the end of the compressed data has been reached and all uncompressed output has been produced
616/// - [`Z_NEED_DICT`] if a preset dictionary is needed at this point
617/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
618/// - [`Z_DATA_ERROR`] if the input data was corrupted
619/// - [`Z_MEM_ERROR`] if there was not enough memory
620/// - [`Z_BUF_ERROR`] if no progress was possible or if there was not enough room in the output buffer when [`Z_FINISH`] is used
621///
622/// Note that [`Z_BUF_ERROR`] is not fatal, and [`inflate`] can be called again with more input and more output space to continue decompressing.
623/// If [`Z_DATA_ERROR`] is returned, the application may then call [`inflateSync`] to look for a good compression block if a partial recovery of the data is to be attempted.
624///
625/// # Safety
626///
627/// * Either
628///     - `strm` is `NULL`
629///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
630/// * Either
631///     - `strm.next_out` is `NULL`
632///     - `strm.next_out` and `strm.avail_out` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
633/// * Either
634///     - `strm.next_in` is `NULL`
635///     - `strm.next_in` and `strm.avail_in` satisfy the requirements of [`core::slice::from_raw_parts::<u8>`]
636#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflate))]
637pub unsafe extern "C" fn inflate(strm: *mut z_stream, flush: i32) -> i32 {
638    if let Some(stream) = InflateStream::from_stream_mut(strm) {
639        let flush = InflateFlush::try_from(flush).unwrap_or_default();
640        zlib_rs::inflate::inflate(stream, flush) as _
641    } else {
642        ReturnCode::StreamError as _
643    }
644}
645
646/// Deallocates all dynamically allocated data structures for this stream.
647///
648/// This function discards any unprocessed input and does not flush any pending output.
649///
650/// # Returns
651///
652/// - [`Z_OK`] if success
653/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
654///
655/// # Safety
656///
657/// * Either
658///     - `strm` is `NULL`
659///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
660#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateEnd))]
661pub unsafe extern "C" fn inflateEnd(strm: *mut z_stream) -> i32 {
662    match InflateStream::from_stream_mut(strm) {
663        Some(stream) => {
664            zlib_rs::inflate::end(stream);
665            ReturnCode::Ok as _
666        }
667        None => ReturnCode::StreamError as _,
668    }
669}
670
671/// Initializes the state for decompression
672///
673/// # Returns
674///
675/// - [`Z_OK`] if success
676/// - [`Z_MEM_ERROR`] if there was not enough memory
677/// - [`Z_VERSION_ERROR`] if the zlib library version is incompatible with the version assumed by the caller
678/// - [`Z_STREAM_ERROR`] if a parameter is invalid, such as a null pointer to the `window` or an
679///   invalid `windowBits`.
680///
681/// # Safety
682///
683/// The caller must guarantee that
684///
685/// * Either
686///     - `strm` is `NULL`
687///     - `strm` satisfies the requirements of `&mut *strm`
688/// * Either
689///     - `version` is NULL
690///     - `version` satisfies the requirements of [`core::ffi::CStr::from_ptr`]
691/// * If `strm` is not `NULL`, the following fields contain valid values
692///     - `zalloc`
693///     - `zfree`
694///     - `opaque`
695/// * The `window` pointer points to an allocation of `1 << windowBits` bytes
696#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateBackInit_))]
697pub unsafe extern "C" fn inflateBackInit_(
698    strm: z_streamp,
699    windowBits: c_int,
700    window: *mut c_uchar,
701    version: *const c_char,
702    stream_size: c_int,
703) -> c_int {
704    if !is_version_compatible(version, stream_size) {
705        return ReturnCode::VersionError as _;
706    }
707
708    let Some(strm) = (unsafe { strm.as_mut() }) else {
709        return ReturnCode::StreamError as _;
710    };
711
712    if window.is_null() {
713        return ReturnCode::StreamError as _;
714    }
715
716    if !(MIN_WBITS..=MAX_WBITS).contains(&windowBits) {
717        return ReturnCode::StreamError as _;
718    }
719
720    let config = InflateConfig {
721        window_bits: windowBits,
722    };
723
724    // NOTE: normally we allocate a window with some additional padding. That doesn't happen here,
725    // so the `infback` function uses `Window::buffer_size` instead of `Window::size`.
726    let window = unsafe { zlib_rs::inflate::Window::from_raw_parts(window, 1usize << windowBits) };
727
728    zlib_rs::inflate::back_init(strm, config, window) as _
729}
730
731/// Decompresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full.
732///
733/// ## Safety
734///
735/// The caller must guarantee that
736///
737/// * Either
738///     - `strm` is `NULL`
739///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateBackInit_`]
740#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateBack))]
741pub unsafe extern "C" fn inflateBack(
742    strm: z_streamp,
743    in_: Option<in_func>,
744    in_desc: *mut c_void,
745    out: Option<out_func>,
746    out_desc: *mut c_void,
747) -> c_int {
748    let Some(strm) = (unsafe { InflateStream::from_stream_mut(strm) }) else {
749        return ReturnCode::StreamError as _;
750    };
751
752    let Some(in_) = in_ else {
753        return ReturnCode::StreamError as _;
754    };
755
756    let Some(out) = out else {
757        return ReturnCode::StreamError as _;
758    };
759
760    zlib_rs::inflate::back(strm, in_, in_desc, out, out_desc) as _
761}
762
763/// Deallocates all dynamically allocated data structures for this stream.
764///
765/// This function discards any unprocessed input and does not flush any pending output.
766///
767/// ## Returns
768///
769/// - [`Z_OK`] if success
770/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
771///
772/// ## Safety
773///
774/// The caller must guarantee that
775///
776/// * Either
777///     - `strm` is `NULL`
778///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateBackInit_`]
779#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateBackEnd))]
780pub unsafe extern "C" fn inflateBackEnd(strm: z_streamp) -> c_int {
781    let Some(stream) = (unsafe { InflateStream::from_stream_mut(strm) }) else {
782        return ReturnCode::StreamError as _;
783    };
784
785    zlib_rs::inflate::back_end(stream);
786
787    ReturnCode::Ok as _
788}
789
790/// Sets the destination stream as a complete copy of the source stream.
791///
792/// This function can be useful when randomly accessing a large stream.
793/// The first pass through the stream can periodically record the inflate state,
794/// allowing restarting inflate at those points when randomly accessing the stream.
795///
796/// # Returns
797///
798/// - [`Z_OK`] if success
799/// - [`Z_MEM_ERROR`] if there was not enough memory
800/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent (such as zalloc being NULL)
801///
802/// The `msg` field is left unchanged in both source and destination.
803///
804/// # Safety
805///
806/// The caller must guarantee that
807///
808/// * Either
809///     - `dest` is `NULL`
810///     - `dest` satisfies the requirements of `&mut *(dest as *mut MaybeUninit<z_stream>)`
811/// * Either
812///     - `source` is `NULL`
813///     - `source` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
814#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateCopy))]
815pub unsafe extern "C" fn inflateCopy(dest: *mut z_stream, source: *const z_stream) -> i32 {
816    let Some(dest) = (unsafe { dest.cast::<MaybeUninit<InflateStream>>().as_mut() }) else {
817        return ReturnCode::StreamError as _;
818    };
819
820    let Some(source) = (unsafe { InflateStream::from_stream_ref(source) }) else {
821        return ReturnCode::StreamError as _;
822    };
823
824    zlib_rs::inflate::copy(dest, source) as _
825}
826
827/// Gives information about the current location of the input stream.
828///
829/// This function marks locations in the input data for random access, which may be at bit positions, and notes those cases where the output of a code may span boundaries of random access blocks. The current location in the input stream can be determined from `avail_in` and `data_type` as noted in the description for the [`Z_BLOCK`] flush parameter for [`inflate`].
830///
831/// A code is being processed if [`inflate`] is waiting for more input to complete decoding of the code, or if it has completed decoding but is waiting for more output space to write the literal or match data.
832///
833/// # Returns
834///
835/// This function returns two values, one in the lower 16 bits of the return value, and the other in the remaining upper bits, obtained by shifting the return value down 16 bits.
836///
837/// - If the upper value is `-1` and the lower value is zero, then [`inflate`] is currently decoding information outside of a block.
838/// - If the upper value is `-1` and the lower value is non-zero, then [`inflate`] is in the middle of a stored block, with the lower value equaling the number of bytes from the input remaining to copy.
839/// - If the upper value is not `-1`, then it is the number of bits back from the current bit position in the input of the code (literal or length/distance pair) currently being processed. In that case the lower value is the number of bytes already emitted for that code.
840/// - `-65536` if the provided source stream state was inconsistent.
841///
842/// # Safety
843///
844/// The caller must guarantee that
845///
846/// * Either
847///     - `strm` is `NULL`
848///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
849#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateMark))]
850pub unsafe extern "C" fn inflateMark(strm: *const z_stream) -> c_long {
851    if let Some(stream) = InflateStream::from_stream_ref(strm) {
852        zlib_rs::inflate::mark(stream)
853    } else {
854        -65536
855    }
856}
857
858/// Skips invalid compressed data until
859///
860/// Skip invalid compressed data until a possible full flush point (see the description of deflate with [`Z_FULL_FLUSH`]) can be found,
861/// or until all available input is skipped. No output is provided.
862///
863/// [`inflateSync`] searches for a `00 00 FF FF` pattern in the compressed data.
864/// All full flush points have this pattern, but not all occurrences of this pattern are full flush points.
865///
866/// # Returns
867///
868/// - [`Z_OK`] if a possible full flush point has been found
869/// - [`Z_BUF_ERROR`] if no more input was provided
870/// - [`Z_DATA_ERROR`] if no flush point has been found
871/// - [`Z_STREAM_ERROR`] if the stream structure was inconsistent
872///
873/// In the success case, the application may save the current value of `total_in` which indicates where valid compressed data was found.
874/// In the error case, the application may repeatedly call [`inflateSync`], providing more input each time, until success or end of the input data.
875///
876/// # Safety
877///
878/// The caller must guarantee that
879///
880/// * Either
881///     - `strm` is `NULL`
882///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
883#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateSync))]
884pub unsafe extern "C" fn inflateSync(strm: *mut z_stream) -> i32 {
885    if let Some(stream) = InflateStream::from_stream_mut(strm) {
886        zlib_rs::inflate::sync(stream) as _
887    } else {
888        ReturnCode::StreamError as _
889    }
890}
891
892#[doc(hidden)]
893/// # Safety
894///
895/// The caller must guarantee that
896///
897/// * Either
898///     - `strm` is `NULL`
899///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
900#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateSyncPoint))]
901pub unsafe extern "C" fn inflateSyncPoint(strm: *mut z_stream) -> i32 {
902    if let Some(stream) = InflateStream::from_stream_mut(strm) {
903        zlib_rs::inflate::sync_point(stream) as i32
904    } else {
905        ReturnCode::StreamError as _
906    }
907}
908
909/// Initializes the state for decompression
910///
911/// A call to [`inflateInit_`] is equivalent to [`inflateInit2_`] where `windowBits` is 15.
912///
913/// # Returns
914///
915/// - [`Z_OK`] if success
916/// - [`Z_MEM_ERROR`] if there was not enough memory
917/// - [`Z_VERSION_ERROR`] if the zlib library version is incompatible with the version assumed by the caller
918/// - [`Z_STREAM_ERROR`] if a parameter is invalid, such as a null pointer to the structure
919///
920/// # Safety
921///
922/// The caller must guarantee that
923///
924/// * Either
925///     - `strm` is `NULL`
926///     - `strm` satisfies the requirements of `&mut *strm`
927/// * Either
928///     - `version` is NULL
929///     - `version` satisfies the requirements of [`core::ffi::CStr::from_ptr`]
930/// * If `strm` is not `NULL`, the following fields contain valid values
931///     - `zalloc`
932///     - `zfree`
933///     - `opaque`
934#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateInit_))]
935pub unsafe extern "C" fn inflateInit_(
936    strm: z_streamp,
937    version: *const c_char,
938    stream_size: c_int,
939) -> c_int {
940    let config = InflateConfig::default();
941    unsafe { inflateInit2_(strm, config.window_bits, version, stream_size) }
942}
943
944/// Initializes the state for decompression
945///
946/// # Returns
947///
948/// - [`Z_OK`] if success
949/// - [`Z_MEM_ERROR`] if there was not enough memory
950/// - [`Z_VERSION_ERROR`] if the zlib library version is incompatible with the version assumed by the caller
951/// - [`Z_STREAM_ERROR`] if a parameter is invalid, such as a null pointer to the structure
952///
953/// # Safety
954///
955/// The caller must guarantee that
956///
957/// * Either
958///     - `strm` is `NULL`
959///     - `strm` satisfies the requirements of `&mut *strm`
960/// * Either
961///     - `version` is NULL
962///     - `version` satisfies the requirements of [`core::ffi::CStr::from_ptr`]
963/// * If `strm` is not `NULL`, the following fields contain valid values
964///     - `zalloc`
965///     - `zfree`
966///     - `opaque`
967#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateInit2_))]
968pub unsafe extern "C" fn inflateInit2_(
969    strm: z_streamp,
970    windowBits: c_int,
971    version: *const c_char,
972    stream_size: c_int,
973) -> c_int {
974    if !is_version_compatible(version, stream_size) {
975        ReturnCode::VersionError as _
976    } else {
977        inflateInit2(strm, windowBits)
978    }
979}
980
981/// Helper that implements the actual initialization logic
982///
983/// # Safety
984///
985/// The caller must guarantee that
986///
987/// * Either
988///     - `strm` is `NULL`
989///     - `strm` satisfies the requirements of `&mut *strm`
990/// * If `strm` is not `NULL`, the following fields contain valid values
991///     - `zalloc`
992///     - `zfree`
993///     - `opaque`
994unsafe extern "C" fn inflateInit2(strm: z_streamp, windowBits: c_int) -> c_int {
995    let Some(strm) = (unsafe { strm.as_mut() }) else {
996        return ReturnCode::StreamError as _;
997    };
998
999    let config = InflateConfig {
1000        window_bits: windowBits,
1001    };
1002
1003    zlib_rs::inflate::init(strm, config) as _
1004}
1005
1006/// Inserts bits in the inflate input stream.
1007///
1008/// The intent is that this function is used to start inflating at a bit position in the middle of a byte.
1009/// The provided bits will be used before any bytes are used from next_in.
1010/// This function should only be used with raw inflate, and should be used before the first [`inflate`] call after [`inflateInit2_`] or [`inflateReset`].
1011/// bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the input.
1012///
1013/// If bits is negative, then the input stream bit buffer is emptied. Then [`inflatePrime`] can be called again to put bits in the buffer.
1014/// This is used to clear out bits leftover after feeding inflate a block description prior to feeding inflate codes.
1015///
1016/// # Returns
1017///
1018/// - [`Z_OK`] if success
1019/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent
1020///
1021/// # Safety
1022///
1023/// The caller must guarantee that
1024///
1025/// * Either
1026///     - `strm` is `NULL`
1027///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1028#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflatePrime))]
1029pub unsafe extern "C" fn inflatePrime(strm: *mut z_stream, bits: i32, value: i32) -> i32 {
1030    if let Some(stream) = InflateStream::from_stream_mut(strm) {
1031        zlib_rs::inflate::prime(stream, bits, value) as _
1032    } else {
1033        ReturnCode::StreamError as _
1034    }
1035}
1036
1037/// Equivalent to [`inflateEnd`] followed by [`inflateInit_`], but does not free and reallocate the internal decompression state.
1038///
1039/// The stream will keep attributes that may have been set by [`inflateInit2_`].
1040/// The stream's `total_in`, `total_out`, `adler`, and `msg` fields are initialized.
1041///
1042/// # Returns
1043///
1044/// - [`Z_OK`] if success
1045/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent
1046///
1047/// # Safety
1048///
1049/// The caller must guarantee that
1050///
1051/// * Either
1052///     - `strm` is `NULL`
1053///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1054#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateReset))]
1055pub unsafe extern "C" fn inflateReset(strm: *mut z_stream) -> i32 {
1056    if let Some(stream) = InflateStream::from_stream_mut(strm) {
1057        zlib_rs::inflate::reset(stream) as _
1058    } else {
1059        ReturnCode::StreamError as _
1060    }
1061}
1062
1063/// This function is the same as [`inflateReset`], but it also permits changing the wrap and window size requests.
1064///
1065/// The `windowBits` parameter is interpreted the same as it is for [`inflateInit2_`].
1066/// If the window size is changed, then the memory allocated for the window is freed, and the window will be reallocated by [`inflate`] if needed.
1067///
1068/// # Returns
1069///
1070/// - [`Z_OK`] if success
1071/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent, or if the `windowBits`
1072///   parameter is invalid
1073///
1074/// # Safety
1075///
1076/// The caller must guarantee that
1077///
1078/// * Either
1079///     - `strm` is `NULL`
1080///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1081#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateReset2))]
1082pub unsafe extern "C" fn inflateReset2(strm: *mut z_stream, windowBits: c_int) -> i32 {
1083    if let Some(stream) = InflateStream::from_stream_mut(strm) {
1084        let config = InflateConfig {
1085            window_bits: windowBits,
1086        };
1087        zlib_rs::inflate::reset_with_config(stream, config) as _
1088    } else {
1089        ReturnCode::StreamError as _
1090    }
1091}
1092
1093/// Initializes the decompression dictionary from the given uncompressed byte sequence.
1094///
1095/// This function must be called immediately after a call of [`inflate`], if that call returned [`Z_NEED_DICT`].
1096/// The dictionary chosen by the compressor can be determined from the Adler-32 value returned by that call of inflate.
1097/// The compressor and decompressor must use exactly the same dictionary (see [`deflateSetDictionary`]).
1098/// For raw inflate, this function can be called at any time to set the dictionary.
1099/// If the provided dictionary is smaller than the window and there is already data in the window, then the provided dictionary will amend what's there.
1100/// The application must insure that the same dictionary that was used for compression is provided.
1101///
1102/// [`inflateSetDictionary`] does not perform any decompression: this will be done by subsequent calls of [`inflate`].
1103///
1104/// # Returns
1105///
1106/// - [`Z_OK`] if success
1107/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent or `dictionary` is `NULL`
1108/// - [`Z_DATA_ERROR`] if the given dictionary doesn't match the expected one (i.e. it has an incorrect Adler-32 value).
1109///
1110/// # Safety
1111///
1112/// The caller must guarantee that
1113///
1114/// * Either
1115///     - `strm` is `NULL`
1116///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1117/// * Either
1118///     - `dictionary` is `NULL`
1119///     - `dictionary` and `dictLength` satisfy the requirements of [`core::slice::from_raw_parts_mut::<u8>`]
1120#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateSetDictionary))]
1121pub unsafe extern "C" fn inflateSetDictionary(
1122    strm: *mut z_stream,
1123    dictionary: *const u8,
1124    dictLength: c_uint,
1125) -> c_int {
1126    let Some(stream) = InflateStream::from_stream_mut(strm) else {
1127        return ReturnCode::StreamError as _;
1128    };
1129
1130    let dict = match dictLength {
1131        0 => &[],
1132        _ => unsafe { slice_from_raw_parts(dictionary, dictLength as usize) }.unwrap_or(&[]),
1133    };
1134
1135    zlib_rs::inflate::set_dictionary(stream, dict) as _
1136}
1137
1138/// Requests that gzip header information be stored in the provided [`gz_header`] structure.
1139///
1140/// The [`inflateGetHeader`] function may be called after [`inflateInit2_`] or [`inflateReset`], and before the first call of [`inflate`].
1141/// As [`inflate`] processes the gzip stream, `head.done` is zero until the header is completed, at which time `head.done` is set to one.
1142/// If a zlib stream is being decoded, then `head.done` is set to `-1` to indicate that there will be no gzip header information forthcoming.
1143/// Note that [`Z_BLOCK`] can be used to force [`inflate`] to return immediately after header processing is complete and before any actual data is decompressed.
1144///
1145/// - The `text`, `time`, `xflags`, and `os` fields are filled in with the gzip header contents.
1146/// - `hcrc` is set to true if there is a header CRC. (The header CRC was valid if done is set to one.)
1147/// - If `extra` is not `NULL`, then `extra_max` contains the maximum number of bytes to write to extra.
1148///   Once `done` is `true`, `extra_len` contains the actual extra field length,
1149///   and `extra` contains the extra field, or that field truncated if `extra_max` is less than `extra_len`.
1150/// - If `name` is not `NULL`, then up to `name_max` characters are written there, terminated with a zero unless the length is greater than `name_max`.
1151/// - If `comment` is not `NULL`, then up to `comm_max` characters are written there, terminated with a zero unless the length is greater than `comm_max`.
1152///
1153/// When any of `extra`, `name`, or `comment` are not `NULL` and the respective field is not present in the header, then that field is set to `NULL` to signal its absence.
1154/// This allows the use of [`deflateSetHeader`] with the returned structure to duplicate the header. However if those fields are set to allocated memory,
1155/// then the application will need to save those pointers elsewhere so that they can be eventually freed.
1156///
1157/// If [`inflateGetHeader`] is not used, then the header information is simply discarded. The header is always checked for validity, including the header CRC if present.
1158/// [`inflateReset`] will reset the process to discard the header information.
1159/// The application would need to call [`inflateGetHeader`] again to retrieve the header from the next gzip stream.
1160///
1161/// # Returns
1162///
1163/// - [`Z_OK`] if success
1164/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent (such as zalloc being NULL)
1165///
1166/// # Safety
1167///
1168/// * Either
1169///     - `strm` is `NULL`
1170///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1171/// * Either
1172///     - `head` is `NULL`
1173///     - `head` satisfies the requirements of `&mut *head`
1174/// * If `head` is not `NULL`:
1175///     - if `head.extra` is not NULL, it must be writable for at least `head.extra_max` bytes
1176///     - if `head.name` is not NULL, it must be writable for at least `head.name_max` bytes
1177///     - if `head.comment` is not NULL, it must be writable for at least `head.comm_max` bytes
1178#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateGetHeader))]
1179pub unsafe extern "C" fn inflateGetHeader(strm: z_streamp, head: gz_headerp) -> c_int {
1180    let Some(stream) = (unsafe { InflateStream::from_stream_mut(strm) }) else {
1181        return ReturnCode::StreamError as _;
1182    };
1183
1184    // SAFETY: the caller guarantees the safety of `&mut *`
1185    let header = unsafe { head.as_mut() };
1186
1187    zlib_rs::inflate::get_header(stream, header) as i32
1188}
1189
1190#[doc(hidden)]
1191/// # Safety
1192///
1193/// The caller must guarantee that
1194///
1195/// * Either
1196///     - `strm` is `NULL`
1197///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1198#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateUndermine))]
1199pub unsafe extern "C" fn inflateUndermine(strm: *mut z_stream, subvert: i32) -> c_int {
1200    if let Some(stream) = InflateStream::from_stream_mut(strm) {
1201        zlib_rs::inflate::undermine(stream, subvert) as i32
1202    } else {
1203        ReturnCode::StreamError as _
1204    }
1205}
1206
1207#[doc(hidden)]
1208/// # Safety
1209///
1210/// The caller must guarantee that
1211///
1212/// * Either
1213///     - `strm` is `NULL`
1214///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1215#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateValidate))]
1216pub unsafe extern "C" fn inflateValidate(strm: *mut z_stream, check: i32) -> c_int {
1217    let Some(stream) = InflateStream::from_stream_mut(strm) else {
1218        return ReturnCode::StreamError as _;
1219    };
1220
1221    zlib_rs::inflate::validate(stream, check != 0);
1222
1223    ReturnCode::Ok as _
1224}
1225
1226#[doc(hidden)]
1227/// ## Safety
1228///
1229/// * Either
1230///     - `strm` is `NULL`
1231///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`inflateInit_`] or similar
1232#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateResetKeep))]
1233pub unsafe extern "C" fn inflateResetKeep(strm: *mut z_stream) -> c_int {
1234    if let Some(stream) = InflateStream::from_stream_mut(strm) {
1235        zlib_rs::inflate::reset_keep(stream) as _
1236    } else {
1237        ReturnCode::StreamError as _
1238    }
1239}
1240
1241// undocumented but exposed function
1242#[doc(hidden)]
1243/// Returns the number of codes used
1244///
1245/// # Safety
1246///
1247/// The caller must guarantee that either:
1248///
1249/// - `buf` is `NULL`
1250/// - `buf` and `len` satisfy the requirements of [`core::slice::from_raw_parts`]
1251#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateCodesUsed))]
1252pub unsafe extern "C" fn inflateCodesUsed(strm: *mut z_stream) -> c_ulong {
1253    match InflateStream::from_stream_mut(strm) {
1254        Some(stream) => zlib_rs::inflate::codes_used(stream) as c_ulong,
1255        None => c_ulong::MAX,
1256    }
1257}
1258
1259/// Compresses as much data as possible, and stops when the input buffer becomes empty or the output buffer becomes full.
1260///
1261/// # Returns
1262///
1263/// - [`Z_OK`] if success
1264/// - [`Z_STREAM_END`] if the end of the compressed data has been reached and all uncompressed output has been produced
1265/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
1266/// - [`Z_BUF_ERROR`] if no progress was possible or if there was not enough room in the output buffer when [`Z_FINISH`] is used
1267///
1268/// Note that [`Z_BUF_ERROR`] is not fatal, and [`deflate`] can be called again with more input and more output space to continue decompressing.
1269///
1270/// # Safety
1271///
1272/// * Either
1273///     - `strm` is `NULL`
1274///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1275/// * Either
1276///     - `strm.next_out` is `NULL`
1277///     - `strm.next_out` and `strm.avail_out` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
1278/// * Either
1279///     - `strm.next_in` is `NULL`
1280///     - `strm.next_in` and `strm.avail_in` satisfy the requirements of [`core::slice::from_raw_parts::<u8>`]
1281#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflate))]
1282pub unsafe extern "C" fn deflate(strm: *mut z_stream, flush: i32) -> c_int {
1283    if let Some(stream) = DeflateStream::from_stream_mut(strm) {
1284        match DeflateFlush::try_from(flush) {
1285            Ok(flush) => zlib_rs::deflate::deflate(stream, flush) as _,
1286            Err(()) => ReturnCode::StreamError as _,
1287        }
1288    } else {
1289        ReturnCode::StreamError as _
1290    }
1291}
1292
1293/// Provides gzip header information for when a gzip stream is requested by [`deflateInit2_`].
1294///
1295/// [`deflateSetHeader`] may be called after [`deflateInit2_`] or [`deflateReset`]) and before the first call of [`deflate`]. The header's `text`, `time`, `os`, `extra`, `name`, and `comment` fields in the provided [`gz_header`] structure are written to the gzip header (xflag is ignored — the extra flags are set according to the compression level).
1296///
1297/// The caller must assure that, if not `NULL`, `name` and `comment` are terminated with a zero byte, and that if `extra` is not NULL, that `extra_len` bytes are available there.
1298/// If `hcrc` is true, a gzip header crc is included.
1299///
1300/// If [`deflateSetHeader`] is not used, the default gzip header has text false, the time set to zero, and os set to the current operating system, with no extra, name, or comment fields. The gzip header is returned to the default state by [`deflateReset`].
1301///
1302/// # Returns
1303///
1304/// - [`Z_OK`] if success
1305/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
1306///
1307/// # Safety
1308///
1309/// * Either
1310///     - `strm` is `NULL`
1311///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1312/// * Either
1313///     - `head` is `NULL`
1314///     - `head` satisfies the requirements of `&mut *head` and satisfies the following:
1315///         - `head.extra` is `NULL` or is readable for at least `head.extra_len` bytes
1316///         - `head.name` is `NULL` or satisfies the requirements of [`core::ffi::CStr::from_ptr`]
1317///         - `head.comment` is `NULL` or satisfies the requirements of [`core::ffi::CStr::from_ptr`]
1318#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateSetHeader))]
1319pub unsafe extern "C" fn deflateSetHeader(strm: *mut z_stream, head: gz_headerp) -> c_int {
1320    let Some(stream) = (unsafe { DeflateStream::from_stream_mut(strm) }) else {
1321        return ReturnCode::StreamError as _;
1322    };
1323
1324    let header = unsafe { head.as_mut() };
1325
1326    zlib_rs::deflate::set_header(stream, header) as _
1327}
1328
1329/// Returns an upper bound on the compressed size after deflation of `sourceLen` bytes.
1330///
1331/// This function must be called after [`deflateInit_`] or [`deflateInit2_`].
1332/// This would be used to allocate an output buffer for deflation in a single pass, and so would be called before [`deflate`].
1333/// If that first [`deflate`] call is provided the `sourceLen` input bytes, an output buffer allocated to the size returned by [`deflateBound`],
1334/// and the flush value [`Z_FINISH`], then [`deflate`] is guaranteed to return [`Z_STREAM_END`].
1335///
1336/// Note that it is possible for the compressed size to be larger than the value returned by [`deflateBound`]
1337/// if flush options other than [`Z_FINISH`] or [`Z_NO_FLUSH`] are used.
1338///
1339/// ## Safety
1340///
1341/// * Either
1342///     - `strm` is `NULL`
1343///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1344#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateBound_z))]
1345pub unsafe extern "C" fn deflateBound_z(strm: *mut z_stream, sourceLen: usize) -> usize {
1346    zlib_rs::deflate::bound(DeflateStream::from_stream_mut(strm), sourceLen)
1347}
1348
1349/// Returns an upper bound on the compressed size after deflation of `sourceLen` bytes.
1350///
1351/// This function must be called after [`deflateInit_`] or [`deflateInit2_`].
1352/// This would be used to allocate an output buffer for deflation in a single pass, and so would be called before [`deflate`].
1353/// If that first [`deflate`] call is provided the `sourceLen` input bytes, an output buffer allocated to the size returned by [`deflateBound`],
1354/// and the flush value [`Z_FINISH`], then [`deflate`] is guaranteed to return [`Z_STREAM_END`].
1355///
1356/// Note that it is possible for the compressed size to be larger than the value returned by [`deflateBound`]
1357/// if flush options other than [`Z_FINISH`] or [`Z_NO_FLUSH`] are used.
1358///
1359/// ## Safety
1360///
1361/// * Either
1362///     - `strm` is `NULL`
1363///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1364#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateBound))]
1365pub unsafe extern "C" fn deflateBound(strm: *mut z_stream, sourceLen: c_ulong) -> c_ulong {
1366    zlib_rs::deflate::bound(DeflateStream::from_stream_mut(strm), sourceLen as usize) as c_ulong
1367}
1368
1369/// Like [`compress`] but takes a `usize` instead.
1370///
1371/// # Returns
1372///
1373/// Same as [`compress`].
1374///
1375/// # Safety
1376///
1377/// Same as [`compress`].
1378#[cfg_attr(feature = "export-symbols", export_name = prefix!(compress_z))]
1379pub unsafe extern "C" fn compress_z(
1380    dest: *mut Bytef,
1381    destLen: *mut usize,
1382    source: *const Bytef,
1383    sourceLen: usize,
1384) -> c_int {
1385    compress2_z(
1386        dest,
1387        destLen,
1388        source,
1389        sourceLen,
1390        DeflateConfig::default().level,
1391    )
1392}
1393
1394/// Compresses `source` into `dest`, and writes the final deflated size into `destLen`.
1395///
1396///`sourceLen` is the byte length of the source buffer.
1397/// Upon entry, `destLen` is the total size of the destination buffer,
1398/// which must be at least the value returned by [`compressBound`]`(sourceLen)`.
1399/// Upon exit, `destLen` is the actual size of the compressed data.
1400///
1401/// A call to [`compress`] is equivalent to [`compress2`] with a level parameter of [`Z_DEFAULT_COMPRESSION`].
1402///
1403/// # Returns
1404///
1405/// * [`Z_OK`] if success
1406/// * [`Z_MEM_ERROR`] if there was not enough memory
1407/// * [`Z_BUF_ERROR`] if there was not enough room in the output buffer
1408///
1409/// # Safety
1410///
1411/// The caller must guarantee that
1412///
1413/// * The `destLen` pointer satisfies the requirements of [`core::ptr::read`]
1414/// * Either
1415///     - `dest` is `NULL`
1416///     - `dest` and `*destLen` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
1417/// * Either
1418///     - `source` is `NULL`
1419///     - `source` and `sourceLen` satisfy the requirements of [`core::slice::from_raw_parts`]
1420///
1421/// # Example
1422///
1423/// ```
1424/// use libz_rs_sys::{Z_OK, compress};
1425///
1426/// let source = b"Ferris";
1427///
1428/// let mut dest = vec![0u8; 100];
1429/// let mut dest_len = dest.len() as _;
1430///
1431/// let err = unsafe {
1432///     compress(
1433///         dest.as_mut_ptr(),
1434///         &mut dest_len,
1435///         source.as_ptr(),
1436///         source.len() as _,
1437///     )
1438/// };
1439///
1440/// assert_eq!(err, Z_OK);
1441/// assert_eq!(dest_len, 14);
1442///
1443/// dest.truncate(dest_len as usize);
1444/// assert_eq!(dest, [120, 156, 115, 75, 45, 42, 202, 44, 6, 0, 8, 6, 2, 108]);
1445/// ```
1446#[cfg_attr(feature = "export-symbols", export_name = prefix!(compress))]
1447pub unsafe extern "C" fn compress(
1448    dest: *mut Bytef,
1449    destLen: *mut c_ulong,
1450    source: *const Bytef,
1451    sourceLen: c_ulong,
1452) -> c_int {
1453    compress2(
1454        dest,
1455        destLen,
1456        source,
1457        sourceLen,
1458        DeflateConfig::default().level,
1459    )
1460}
1461
1462/// Like [`compress2`] but takes a `usize` instead.
1463///
1464/// # Returns
1465///
1466/// Same as [`compress2`].
1467///
1468/// # Safety
1469///
1470/// Same as [`compress2`].
1471#[cfg_attr(feature = "export-symbols", export_name = prefix!(compress2_z))]
1472pub unsafe extern "C" fn compress2_z(
1473    dest: *mut Bytef,
1474    destLen: *mut usize,
1475    source: *const Bytef,
1476    sourceLen: usize,
1477    level: c_int,
1478) -> c_int {
1479    // stock zlib will just dereference a NULL pointer: that's UB.
1480    // Hence us returning an error value is compatible
1481    let Some(destLen) = (unsafe { destLen.as_mut() }) else {
1482        return ReturnCode::StreamError as _;
1483    };
1484
1485    let Some(output) = (unsafe { slice_from_raw_parts_uninit_mut(dest, *destLen) }) else {
1486        return ReturnCode::StreamError as _;
1487    };
1488
1489    let Some(input) = (unsafe { slice_from_raw_parts(source, sourceLen) }) else {
1490        return ReturnCode::StreamError as _;
1491    };
1492
1493    let config = DeflateConfig::new(level);
1494    let (output, err) = zlib_rs::deflate::compress(output, input, config);
1495
1496    *destLen = output.len();
1497
1498    err as c_int
1499}
1500
1501/// Compresses `source` into `dest`, and writes the final deflated size into `destLen`.
1502///
1503/// The level parameter has the same meaning as in [`deflateInit_`].
1504/// `sourceLen` is the byte length of the source buffer.
1505/// Upon entry, `destLen` is the total size of the destination buffer,
1506/// which must be at least the value returned by [`compressBound`]`(sourceLen)`.
1507/// Upon exit, `destLen` is the actual size of the compressed data.
1508///
1509/// # Returns
1510///
1511/// * [`Z_OK`] if success
1512/// * [`Z_MEM_ERROR`] if there was not enough memory
1513/// * [`Z_BUF_ERROR`] if there was not enough room in the output buffer
1514///
1515/// # Safety
1516///
1517/// The caller must guarantee that
1518///
1519/// * Either
1520///     - `destLen` is `NULL`
1521///     - `destLen` satisfies the requirements of `&mut *destLen`
1522/// * Either
1523///     - `dest` is `NULL`
1524///     - `dest` and `*destLen` satisfy the requirements of [`core::slice::from_raw_parts_mut::<MaybeUninit<u8>>`]
1525/// * Either
1526///     - `source` is `NULL`
1527///     - `source` and `sourceLen` satisfy the requirements of [`core::slice::from_raw_parts`]
1528#[cfg_attr(feature = "export-symbols", export_name = prefix!(compress2))]
1529pub unsafe extern "C" fn compress2(
1530    dest: *mut Bytef,
1531    destLen: *mut c_ulong,
1532    source: *const Bytef,
1533    sourceLen: c_ulong,
1534    level: c_int,
1535) -> c_int {
1536    // stock zlib will just dereference a NULL pointer: that's UB.
1537    // Hence us returning an error value is compatible
1538    let Some(destLen) = (unsafe { destLen.as_mut() }) else {
1539        return ReturnCode::StreamError as _;
1540    };
1541
1542    let mut got = *destLen as usize;
1543    let ret = compress2_z(dest, &mut got, source, sourceLen as usize, level);
1544    *destLen = got as c_ulong;
1545
1546    ret
1547}
1548
1549/// Returns an upper bound on the compressed size after [`compress`] or [`compress2`] on `sourceLen` bytes.
1550///
1551/// Can be used before a [`compress`] or [`compress2`] call to allocate the destination buffer.
1552#[cfg_attr(feature = "export-symbols", export_name = prefix!(compressBound_z))]
1553pub extern "C" fn compressBound_z(sourceLen: usize) -> usize {
1554    zlib_rs::deflate::compress_bound(sourceLen)
1555}
1556
1557/// Returns an upper bound on the compressed size after [`compress`] or [`compress2`] on `sourceLen` bytes.
1558///
1559/// Can be used before a [`compress`] or [`compress2`] call to allocate the destination buffer.
1560#[cfg_attr(feature = "export-symbols", export_name = prefix!(compressBound))]
1561pub extern "C" fn compressBound(sourceLen: c_ulong) -> c_ulong {
1562    zlib_rs::deflate::compress_bound(sourceLen as usize) as c_ulong
1563}
1564
1565/// Deallocates all dynamically allocated data structures for this stream.
1566///
1567/// This function discards any unprocessed input and does not flush any pending output.
1568///
1569/// # Returns
1570///
1571/// - [`Z_OK`] if success
1572/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
1573/// - [`Z_DATA_ERROR`] if the stream was freed prematurely (some input or output was discarded)
1574///
1575/// In the error case, `strm.msg` may be set but then points to a static string (which must not be deallocated).
1576///
1577/// # Safety
1578///
1579/// * Either
1580///     - `strm` is `NULL`
1581///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1582#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateEnd))]
1583pub unsafe extern "C" fn deflateEnd(strm: *mut z_stream) -> i32 {
1584    match DeflateStream::from_stream_mut(strm) {
1585        Some(stream) => match zlib_rs::deflate::end(stream) {
1586            Ok(_) => ReturnCode::Ok as _,
1587            Err(_) => ReturnCode::DataError as _,
1588        },
1589        None => ReturnCode::StreamError as _,
1590    }
1591}
1592
1593/// This function is equivalent to [`deflateEnd`] followed by [`deflateInit_`], but does not free and reallocate the internal compression state.
1594///
1595/// This function will leave the compression level and any other attributes that may have been set unchanged.
1596/// The stream's `total_in`, `total_out`, `adler`, and `msg` fields are initialized.
1597///
1598/// ## Returns
1599///
1600/// - [`Z_OK`] if success
1601/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
1602///
1603/// ## Safety
1604///
1605/// The caller must guarantee that
1606///
1607/// * Either
1608///     - `strm` is `NULL`
1609///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1610#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateReset))]
1611pub unsafe extern "C" fn deflateReset(strm: *mut z_stream) -> i32 {
1612    match DeflateStream::from_stream_mut(strm) {
1613        Some(stream) => zlib_rs::deflate::reset(stream) as _,
1614        None => ReturnCode::StreamError as _,
1615    }
1616}
1617
1618#[doc(hidden)]
1619/// # Safety
1620///
1621/// The caller must guarantee that
1622///
1623/// * Either
1624///     - `strm` is `NULL`
1625///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1626#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateResetKeep))]
1627pub unsafe extern "C" fn deflateResetKeep(strm: *mut z_stream) -> c_int {
1628    match DeflateStream::from_stream_mut(strm) {
1629        Some(stream) => zlib_rs::deflate::reset_keep(stream) as _,
1630        None => ReturnCode::StreamError as _,
1631    }
1632}
1633
1634/// Dynamically update the compression level and compression strategy.
1635///
1636/// This can be used to switch between compression and straight copy of the input data,
1637/// or to switch to a different kind of input data requiring a different strategy.
1638///
1639/// The interpretation of level and strategy is as in [`deflateInit2_`].
1640///
1641/// # Returns
1642///
1643/// - [`Z_OK`] if success
1644/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent or if a parameter was invalid
1645/// - [`Z_BUF_ERROR`] if there was not enough output space to complete the compression of the available input data before a change in the strategy or approach.
1646///
1647/// Note that in the case of a [`Z_BUF_ERROR`], the parameters are not changed.
1648/// A return value of [`Z_BUF_ERROR`] is not fatal, in which case [`deflateParams`] can be retried with more output space.
1649///
1650/// # Safety
1651///
1652/// The caller must guarantee that
1653///
1654/// * Either
1655///     - `strm` is `NULL`
1656///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1657#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateParams))]
1658pub unsafe extern "C" fn deflateParams(strm: z_streamp, level: c_int, strategy: c_int) -> c_int {
1659    let Ok(strategy) = Strategy::try_from(strategy) else {
1660        return ReturnCode::StreamError as _;
1661    };
1662
1663    match DeflateStream::from_stream_mut(strm) {
1664        Some(stream) => zlib_rs::deflate::params(stream, level, strategy) as _,
1665        None => ReturnCode::StreamError as _,
1666    }
1667}
1668
1669/// Initializes the compression dictionary from the given byte sequence without producing any compressed output.
1670///
1671/// This function may be called after [`deflateInit_`], [`deflateInit2_`] or [`deflateReset`]) and before the first call of [`deflate`].
1672///
1673/// # Returns
1674///
1675/// - [`Z_OK`] if success
1676/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
1677///
1678/// # Safety
1679///
1680/// The caller must guarantee that
1681///
1682/// * Either
1683///     - `strm` is `NULL`
1684///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1685/// * Either
1686///     - `dictionary` is `NULL`
1687///     - `dictionary` and `dictLength` satisfy the requirements of [`core::slice::from_raw_parts_mut::<u8>`]
1688#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateSetDictionary))]
1689pub unsafe extern "C" fn deflateSetDictionary(
1690    strm: z_streamp,
1691    dictionary: *const Bytef,
1692    dictLength: uInt,
1693) -> c_int {
1694    let Some(dictionary) = (unsafe { slice_from_raw_parts(dictionary, dictLength as usize) })
1695    else {
1696        return ReturnCode::StreamError as _;
1697    };
1698
1699    match DeflateStream::from_stream_mut(strm) {
1700        Some(stream) => zlib_rs::deflate::set_dictionary(stream, dictionary) as _,
1701        None => ReturnCode::StreamError as _,
1702    }
1703}
1704
1705/// Inserts bits in the deflate output stream.
1706///
1707/// The intent is that this function is used to start off the deflate output with the bits leftover from a previous deflate stream when appending to it.
1708/// As such, this function can only be used for raw deflate, and must be used before the first [`deflate`] call after a [`deflateInit2_`] or [`deflateReset`].
1709/// bits must be less than or equal to 16, and that many of the least significant bits of value will be inserted in the output.
1710///
1711/// # Returns
1712///
1713/// - [`Z_OK`] if success
1714/// - [`Z_BUF_ERROR`] if there was not enough room in the internal buffer to insert the bits
1715/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent
1716///
1717/// # Safety
1718///
1719/// The caller must guarantee that
1720///
1721/// * Either
1722///     - `strm` is `NULL`
1723///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1724#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflatePrime))]
1725pub unsafe extern "C" fn deflatePrime(strm: z_streamp, bits: c_int, value: c_int) -> c_int {
1726    match DeflateStream::from_stream_mut(strm) {
1727        Some(stream) => zlib_rs::deflate::prime(stream, bits, value) as _,
1728        None => ReturnCode::StreamError as _,
1729    }
1730}
1731
1732/// Returns the number of bytes and bits of output that have been generated, but not yet provided in the available output.
1733///
1734/// The bytes not provided would be due to the available output space having being consumed.
1735/// The number of bits of output not provided are between `0` and `7`, where they await more bits to join them in order to fill out a full byte.
1736/// If pending or bits are `NULL`, then those values are not set.
1737///
1738/// # Returns
1739///
1740/// - [`Z_OK`] if success
1741/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent
1742///
1743/// # Safety
1744///
1745/// The caller must guarantee that
1746///
1747/// * Either
1748///     - `strm` is `NULL`
1749///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1750/// * Either
1751///     - `pending` is `NULL`
1752///     - `pending` satisfies the requirements of [`core::ptr::write::<c_int>`]
1753/// * Either
1754///     - `bits` is `NULL`
1755///     - `bits` satisfies the requirements of [`core::ptr::write::<c_int>`]
1756#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflatePending))]
1757pub unsafe extern "C" fn deflatePending(
1758    strm: z_streamp,
1759    pending: *mut c_uint,
1760    bits: *mut c_int,
1761) -> c_int {
1762    let Some(stream) = (unsafe { DeflateStream::from_stream_mut(strm) }) else {
1763        return ReturnCode::StreamError as _;
1764    };
1765
1766    let (current_pending, current_bits) = stream.pending();
1767
1768    if let Some(pending) = unsafe { pending.as_mut() } {
1769        *pending = current_pending as c_uint;
1770    }
1771
1772    if let Some(bits) = unsafe { bits.as_mut() } {
1773        *bits = current_bits as c_int;
1774    }
1775
1776    ReturnCode::Ok as _
1777}
1778
1779/// Writes into `bits` the most recent number of deflate bits used in the last
1780/// byte when flushing to a byte boundary. The result is in `1..=8`, or 0 if
1781/// there has not yet been a flush. This helps determine the location of the
1782/// last bit of a deflate stream.
1783///
1784/// # Returns
1785///
1786/// - [`Z_OK`] if success
1787/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent
1788///
1789/// # Safety
1790///
1791/// The caller must guarantee that
1792///
1793/// * Either
1794///     - `strm` is `NULL`
1795///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1796/// * Either
1797///     - `bits` is `NULL`
1798///     - `bits` satisfies the requirements of [`core::ptr::write::<c_int>`]
1799#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateUsed))]
1800pub unsafe extern "C" fn deflateUsed(strm: z_streamp, bits: *mut c_int) -> c_int {
1801    let Some(stream) = (unsafe { DeflateStream::from_stream_mut(strm) }) else {
1802        return ReturnCode::StreamError as _;
1803    };
1804
1805    if let Some(bits) = unsafe { bits.as_mut() } {
1806        *bits = c_int::from(stream.bits_used());
1807    }
1808
1809    ReturnCode::Ok as _
1810}
1811
1812/// Sets the destination stream as a complete copy of the source stream.
1813///
1814/// This function can be useful when several compression strategies will be tried, for example when there are several ways of pre-processing the input data with a filter.
1815/// The streams that will be discarded should then be freed by calling [`deflateEnd`].
1816/// Note that [`deflateCopy`] duplicates the internal compression state which can be quite large, so this strategy is slow and can consume lots of memory.
1817///
1818/// # Returns
1819///
1820/// - [`Z_OK`] if success
1821/// - [`Z_MEM_ERROR`] if there was not enough memory
1822/// - [`Z_STREAM_ERROR`] if the source stream state was inconsistent (such as zalloc being NULL)
1823///
1824/// The `msg` field is left unchanged in both source and destination.
1825///
1826/// # Safety
1827///
1828/// The caller must guarantee that
1829///
1830/// * Either
1831///     - `dest` is `NULL`
1832///     - `dest` satisfies the requirements of `&mut *(dest as *mut MaybeUninit<z_stream>)`
1833/// * Either
1834///     - `source` is `NULL`
1835///     - `source` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
1836#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateCopy))]
1837pub unsafe extern "C" fn deflateCopy(dest: z_streamp, source: z_streamp) -> c_int {
1838    let Some(dest) = (unsafe { dest.cast::<MaybeUninit<DeflateStream>>().as_mut() }) else {
1839        return ReturnCode::StreamError as _;
1840    };
1841
1842    let Some(source) = (unsafe { DeflateStream::from_stream_mut(source) }) else {
1843        return ReturnCode::StreamError as _;
1844    };
1845
1846    zlib_rs::deflate::copy(dest, source) as _
1847}
1848
1849/// Initializes the state for compression
1850///
1851///  The stream's `zalloc`, `zfree` and `opaque` fields must be initialized before by the caller.
1852///  If `zalloc` and `zfree` are set to `NULL`, [`deflateInit_`] updates them to use default allocation functions.
1853///  The `total_in`, `total_out`, `adler`, and `msg` fields are initialized.
1854///
1855/// The compression level must be [`Z_DEFAULT_COMPRESSION`], or between `0` and `9`:
1856///
1857/// - level `0` gives no compression at all (the input data is simply copied a block at a time)
1858/// - level `1` gives best speed
1859/// - level `9` gives best compression
1860/// - [`Z_DEFAULT_COMPRESSION`] requests a default compromise between speed and compression (currently equivalent to level `6`).
1861///
1862/// A call to [`deflateInit_`] is equivalent to [`deflateInit2_`] where:
1863///
1864/// - `method` is `8` (deflate)
1865/// - `windowBits` is `15`
1866/// - `memLevel` is `8`
1867/// - `strategy` is `0` (default)
1868///
1869/// # Returns
1870///
1871/// - [`Z_OK`] if success
1872/// - [`Z_MEM_ERROR`] if there was not enough memory
1873/// - [`Z_VERSION_ERROR`] if the zlib library version is incompatible with the version assumed by the caller
1874/// - [`Z_STREAM_ERROR`] if a parameter is invalid, such as a null pointer to the structure
1875///
1876/// # Safety
1877///
1878/// The caller must guarantee that
1879///
1880/// * Either
1881///     - `strm` is `NULL`
1882///     - `strm` satisfies the requirements of `&mut *strm`
1883/// * Either
1884///     - `version` is NULL
1885///     - `version` satisfies the requirements of [`core::ffi::CStr::from_ptr`]
1886/// * If `strm` is not `NULL`, the following fields contain valid values
1887///     - `zalloc`
1888///     - `zfree`
1889///     - `opaque`
1890///
1891/// # Example
1892///
1893/// ```
1894/// use core::mem::MaybeUninit;
1895/// use libz_rs_sys::{z_stream, deflateInit_, zlibVersion, Z_OK};
1896///
1897/// // the zalloc and zfree fields are initialized as zero/NULL.
1898/// // `deflateInit_` will set a default allocation  and deallocation function.
1899/// let mut strm = MaybeUninit::zeroed();
1900///
1901/// let err = unsafe {
1902///     deflateInit_(
1903///         strm.as_mut_ptr(),
1904///         6,
1905///         zlibVersion(),
1906///         core::mem::size_of::<z_stream>() as _,
1907///     )
1908/// };
1909/// assert_eq!(err, Z_OK);
1910///
1911/// // the stream is now fully initialized. Prefer `assume_init_mut` over
1912/// // `assume_init` so the stream does not get moved.
1913/// let strm = unsafe { strm.assume_init_mut() };
1914/// ```
1915#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateInit_))]
1916pub unsafe extern "C" fn deflateInit_(
1917    strm: z_streamp,
1918    level: c_int,
1919    version: *const c_char,
1920    stream_size: c_int,
1921) -> c_int {
1922    let config = DeflateConfig::new(level);
1923
1924    unsafe {
1925        deflateInit2_(
1926            strm,
1927            level,
1928            config.method as c_int,
1929            config.window_bits,
1930            config.mem_level,
1931            config.strategy as c_int,
1932            version,
1933            stream_size,
1934        )
1935    }
1936}
1937
1938/// Initializes the state for compression
1939///
1940///  The stream's `zalloc`, `zfree` and `opaque` fields must be initialized before by the caller.
1941///  If `zalloc` and `zfree` are set to `NULL`, [`deflateInit_`] updates them to use default allocation functions.
1942///  The `total_in`, `total_out`, `adler`, and `msg` fields are initialized.
1943///
1944/// The compression level must be [`Z_DEFAULT_COMPRESSION`], or between `0` and `9`:
1945///
1946/// - level `0` gives no compression at all (the input data is simply copied a block at a time)
1947/// - level `1` gives best speed
1948/// - level `9` gives best compression
1949/// - [`Z_DEFAULT_COMPRESSION`] requests a default compromise between speed and compression (currently equivalent to level `6`).
1950///
1951/// # Returns
1952///
1953/// - [`Z_OK`] if success
1954/// - [`Z_MEM_ERROR`] if there was not enough memory
1955/// - [`Z_VERSION_ERROR`] if the zlib library version is incompatible with the version assumed by the caller
1956/// - [`Z_STREAM_ERROR`] if a parameter is invalid, such as a null pointer to the structure
1957///
1958/// # Safety
1959///
1960/// The caller must guarantee that
1961///
1962/// * Either
1963///     - `strm` is `NULL`
1964///     - `strm` satisfies the requirements of `&mut *strm`
1965/// * Either
1966///     - `version` is NULL
1967///     - `version` satisfies the requirements of [`core::ffi::CStr::from_ptr`]
1968/// * If `strm` is not `NULL`, the following fields contain valid values
1969///     - `zalloc`
1970///     - `zfree`
1971///     - `opaque`
1972///
1973/// # Example
1974///
1975/// ```
1976/// use core::mem::MaybeUninit;
1977/// use libz_rs_sys::{z_stream, deflateInit2_, zlibVersion, Z_OK};
1978///
1979/// // the zalloc and zfree fields are initialized as zero/NULL.
1980/// // `deflateInit_` will set a default allocation  and deallocation function.
1981/// let mut strm = MaybeUninit::zeroed();
1982///
1983/// let err = unsafe {
1984///     deflateInit2_(
1985///         strm.as_mut_ptr(),
1986///         6,
1987///         8,
1988///         15,
1989///         8,
1990///         0,
1991///         zlibVersion(),
1992///         core::mem::size_of::<z_stream>() as _,
1993///     )
1994/// };
1995/// assert_eq!(err, Z_OK);
1996///
1997/// // the stream is now fully initialized. Prefer `assume_init_mut` over
1998/// // `assume_init` so the stream does not get moved.
1999/// let strm = unsafe { strm.assume_init_mut() };
2000/// ```
2001#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateInit2_))]
2002pub unsafe extern "C" fn deflateInit2_(
2003    strm: z_streamp,
2004    level: c_int,
2005    method: c_int,
2006    windowBits: c_int,
2007    memLevel: c_int,
2008    strategy: c_int,
2009    version: *const c_char,
2010    stream_size: c_int,
2011) -> c_int {
2012    if !is_version_compatible(version, stream_size) {
2013        return ReturnCode::VersionError as _;
2014    }
2015
2016    let Some(strm) = (unsafe { strm.as_mut() }) else {
2017        return ReturnCode::StreamError as _;
2018    };
2019
2020    let Ok(method) = Method::try_from(method) else {
2021        return ReturnCode::StreamError as _;
2022    };
2023
2024    let Ok(strategy) = Strategy::try_from(strategy) else {
2025        return ReturnCode::StreamError as _;
2026    };
2027
2028    let config = DeflateConfig {
2029        level,
2030        method,
2031        window_bits: windowBits,
2032        mem_level: memLevel,
2033        strategy,
2034    };
2035
2036    zlib_rs::deflate::init(strm, config) as _
2037}
2038
2039/// Fine tune deflate's internal compression parameters.
2040///
2041/// This should only be used by someone who understands the algorithm used by zlib's deflate for searching
2042/// for the best matching string, and even then only by the most fanatic optimizer trying to squeeze out
2043/// the last compressed bit for their specific input data. Read the `deflate.rs` source code for the meaning
2044/// of the `max_lazy`, `good_length`, `nice_length`, and `max_chain` parameters.
2045///
2046/// ## Returns
2047///
2048/// - [`Z_OK`] if success
2049/// - [`Z_STREAM_ERROR`] if the stream state was inconsistent
2050///
2051/// # Safety
2052///
2053/// The caller must guarantee that
2054///
2055/// * Either
2056///     - `strm` is `NULL`
2057///     - `strm` satisfies the requirements of `&mut *strm` and was initialized with [`deflateInit_`] or similar
2058#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateTune))]
2059pub unsafe extern "C" fn deflateTune(
2060    strm: z_streamp,
2061    good_length: c_int,
2062    max_lazy: c_int,
2063    nice_length: c_int,
2064    max_chain: c_int,
2065) -> c_int {
2066    let Some(stream) = (unsafe { DeflateStream::from_stream_mut(strm) }) else {
2067        return ReturnCode::StreamError as _;
2068    };
2069
2070    zlib_rs::deflate::tune(
2071        stream,
2072        good_length as usize,
2073        max_lazy as usize,
2074        nice_length as usize,
2075        max_chain as usize,
2076    ) as _
2077}
2078
2079/// Get the error message for an error. This could be the value returned by e.g. [`compress`] or
2080/// [`inflate`].
2081///
2082/// The return value is a pointer to a NULL-terminated sequence of bytes
2083///
2084/// ## Example
2085///
2086/// ```
2087/// use libz_rs_sys::*;
2088/// use core::ffi::{c_char, CStr};
2089///
2090/// fn cstr<'a>(ptr: *const c_char) -> &'a [u8] {
2091///     // SAFETY: we trust the input
2092///     unsafe { CStr::from_ptr(ptr) }.to_bytes()
2093/// }
2094///
2095/// // defined error values give a short message
2096/// assert_eq!(cstr(zError(Z_NEED_DICT)), b"need dictionary");
2097/// assert_eq!(cstr(zError(Z_NEED_DICT)), b"need dictionary");
2098/// assert_eq!(cstr(zError(Z_STREAM_END)), b"stream end");
2099/// assert_eq!(cstr(zError(Z_OK)), b"");
2100/// assert_eq!(cstr(zError(Z_ERRNO)), b"file error");
2101/// assert_eq!(cstr(zError(Z_STREAM_ERROR)), b"stream error");
2102/// assert_eq!(cstr(zError(Z_DATA_ERROR)), b"data error");
2103/// assert_eq!(cstr(zError(Z_MEM_ERROR)), b"insufficient memory");
2104/// assert_eq!(cstr(zError(Z_BUF_ERROR)), b"buffer error");
2105/// assert_eq!(cstr(zError(Z_VERSION_ERROR)), b"incompatible version");
2106///
2107/// // other inputs return an empty string
2108/// assert_eq!(cstr(zError(1234)), b"");
2109/// ```
2110#[cfg_attr(feature = "export-symbols", export_name = prefix!(zError))]
2111pub const extern "C" fn zError(err: c_int) -> *const c_char {
2112    match ReturnCode::try_from_c_int(err) {
2113        Some(return_code) => return_code.error_message(),
2114        None => [0 as c_char].as_ptr(),
2115    }
2116}
2117
2118macro_rules! libz_rs_sys_version {
2119    () => {
2120        concat!("1.3.0-zlib-rs-", env!("CARGO_PKG_VERSION"), "\0")
2121    };
2122}
2123
2124// the first part of this version specifies the zlib that we're compatible with (in terms of
2125// supported functions). In practice in most cases only the major version is checked, unless
2126// specific functions that were added later are used.
2127const LIBZ_RS_SYS_VERSION: &str = concat!(libz_rs_sys_version!(), "\0");
2128
2129unsafe fn is_version_compatible(version: *const c_char, stream_size: i32) -> bool {
2130    let Some(expected_major_version) = (unsafe { version.as_ref() }) else {
2131        return false;
2132    };
2133
2134    if *expected_major_version as u8 != LIBZ_RS_SYS_VERSION.as_bytes()[0] {
2135        return false;
2136    }
2137
2138    core::mem::size_of::<z_stream>() as i32 == stream_size
2139}
2140
2141/// The version of the zlib library.
2142///
2143/// Its value is a pointer to a NULL-terminated sequence of bytes.
2144///
2145/// The version string for this release is `
2146#[doc = libz_rs_sys_version!()]
2147/// `:
2148///
2149/// - The first component is the version of stock zlib that this release is compatible with
2150/// - The final component is the zlib-rs version used to build this release.
2151#[cfg_attr(feature = "export-symbols", export_name = prefix!(zlibVersion))]
2152pub const extern "C" fn zlibVersion() -> *const c_char {
2153    LIBZ_RS_SYS_VERSION.as_ptr().cast::<c_char>()
2154}
2155
2156/// Return flags indicating compile-time options.
2157///
2158/// Type sizes, two bits each, `0b00` = 16 bits, `0b01` = 32, `0b10` = 64, `0b11` = other:
2159///
2160/// | bits | description |
2161/// | -- | -- |
2162/// | `0..=1` | size of [`uInt`] |
2163/// | `2..=3` | size of [`uLong`] |
2164/// | `4..=5` | size of [`voidpf`] (pointer) |
2165/// | `6..=7` | size of [`z_off_t`] |
2166///
2167/// Compiler, assembler, and debug options:
2168///
2169/// | bits | flag | description |
2170/// | -- | -- | -- |
2171/// | `8`     | `ZLIB_DEBUG` | debug prints are enabled |
2172/// | `9`     | `ASMV` or `ASMINF` | use ASM code |
2173/// | `10`    | `ZLIB_WINAPI` | exported functions use the WINAPI calling convention |
2174/// | `11`    | | reserved |
2175///
2176/// One-time table building (smaller code, but not thread-safe if true):
2177///
2178/// | bits | flag | description |
2179/// | -- | -- | -- |
2180/// | `12` | `BUILDFIXED` | build static block decoding tables when needed |
2181/// | `13` | `DYNAMIC_CRC_TABLE` | build CRC calculation tables when needed |
2182/// | `14`    | | reserved |
2183/// | `15`    | | reserved |
2184///
2185/// Library content (indicates missing functionality):
2186///
2187/// | bits | flag | description |
2188/// | -- | -- | -- |
2189/// | `16` | `NO_GZCOMPRESS` | `gz*` functions cannot compress (to avoid linking deflate code when not needed) |
2190/// | `17` | `NO_GZIP` | deflate can't write gzip streams, and inflate can't detect and decode gzip streams (to avoid linking crc code) |
2191/// | `18`    | | reserved |
2192/// | `19`    | | reserved |
2193///
2194/// Operation variations (changes in library functionality):
2195///
2196/// | bits | flag | description |
2197/// | -- | -- | -- |
2198/// | `20` | `PKZIP_BUG_WORKAROUND` | slightly more permissive inflate |
2199/// | `21` | `FASTEST` | deflate algorithm with only one, lowest compression level |
2200/// | `22`    | | reserved |
2201/// | `23`    | | reserved |
2202///
2203/// The sprintf variant used by `gzprintf` (zero is best):
2204///
2205/// | bits | value | description |
2206/// | -- | -- | -- |
2207/// | `24` | 0 = vs*, 1 = s* | 1 means limited to 20 arguments after the format |
2208/// | `25` | 0 = *nprintf, 1 = *printf | 1 means `gzprintf` not secure! |
2209/// | `26` | 0 = returns value, 1 = void | 1 means inferred string length returned |
2210///
2211/// Remainder:
2212///
2213/// The remaining bits `27..=31` are 0 (reserved).
2214#[cfg_attr(feature = "export-symbols", export_name = prefix!(zlibCompileFlags))]
2215pub const extern "C" fn zlibCompileFlags() -> c_ulong {
2216    let mut flags = 0;
2217
2218    const fn encode_size<T>() -> c_ulong {
2219        match core::mem::size_of::<T>() {
2220            2 => 0b00,
2221            4 => 0b01,
2222            8 => 0b10,
2223            _ => 0b11,
2224        }
2225    }
2226
2227    flags |= encode_size::<uInt>();
2228    flags |= encode_size::<uLong>() << 2;
2229    flags |= encode_size::<voidpf>() << 4;
2230    flags |= encode_size::<z_off_t>() << 6;
2231
2232    macro_rules! set_bit {
2233        ($i:expr, $v:expr) => {
2234            flags |= (($v as uLong) << $i);
2235        };
2236    }
2237
2238    // Compiler, assembler, debug:
2239    set_bit!(8, false); // ZLIB_DEBUG
2240    set_bit!(9, false); // ASMV || ASMINF
2241    set_bit!(10, false); // ZLIB_WINAPI
2242
2243    // One-time table building:
2244    set_bit!(12, false); // BUILDFIXED
2245    set_bit!(13, false); // DYNAMIC_CRC_TABLE
2246
2247    // Library content (indicates missing functionality):
2248    set_bit!(16, false); // NO_GZCOMPRESS
2249    set_bit!(17, false); // NO_GZIP
2250
2251    // Operation variations (changes in library functionality):
2252    set_bit!(20, false); // PKZIP_BUG_WORKAROUND
2253    set_bit!(21, false); // FASTEST
2254
2255    // The sprintf variant used by gzprintf (we assume a modern libc):
2256    set_bit!(24, false);
2257    set_bit!(25, false);
2258    set_bit!(26, false);
2259
2260    flags
2261}
2262
2263/// Returns the sliding dictionary being maintained by inflate.  
2264///
2265/// `dictLength` is set to the number of bytes in the dictionary, and that many bytes are copied
2266/// to `dictionary`. `dictionary` must have enough space, where `32768` bytes is
2267/// always enough.  If [`inflateGetDictionary`] is called with `dictionary` equal to
2268/// `NULL`, then only the dictionary length is returned, and nothing is copied.
2269/// Similarly, if `dictLength` is `NULL`, then it is not set.
2270///
2271/// # Returns
2272///
2273/// * [`Z_OK`] if success
2274/// * [`Z_STREAM_ERROR`] if the stream state is inconsistent
2275///
2276/// # Safety
2277///
2278/// - `dictionary` must `NULL` or writable for the dictionary length (`32768` is always enough)
2279/// - `dictLength` must `NULL` or satisfy the requirements of [`pointer::as_mut`]
2280///
2281/// [`pointer::as_mut`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_mut
2282#[cfg_attr(feature = "export-symbols", export_name = prefix!(inflateGetDictionary))]
2283pub unsafe extern "C" fn inflateGetDictionary(
2284    strm: *const z_stream,
2285    dictionary: *mut c_uchar,
2286    dictLength: *mut c_uint,
2287) -> c_int {
2288    let Some(stream) = InflateStream::from_stream_ref(strm) else {
2289        return ReturnCode::StreamError as c_int;
2290    };
2291
2292    let whave = zlib_rs::inflate::get_dictionary(stream, dictionary);
2293
2294    if let Some(dictLength) = unsafe { dictLength.as_mut() } {
2295        *dictLength = whave as c_uint;
2296    }
2297
2298    ReturnCode::Ok as _
2299}
2300
2301/// Returns the sliding dictionary being maintained by deflate.  
2302///
2303/// `dictLength` is set to the number of bytes in the dictionary, and that many bytes are copied
2304/// to `dictionary`. `dictionary` must have enough space, where `32768` bytes is
2305/// always enough.  If [`deflateGetDictionary`] is called with `dictionary` equal to
2306/// `NULL`, then only the dictionary length is returned, and nothing is copied.
2307/// Similarly, if `dictLength` is `NULL`, then it is not set.
2308///
2309/// [`deflateGetDictionary`] may return a length less than the window size, even
2310/// when more than the window size in input has been provided. It may return up
2311/// to 258 bytes less in that case, due to how zlib's implementation of deflate
2312/// manages the sliding window and lookahead for matches, where matches can be
2313/// up to 258 bytes long. If the application needs the last window-size bytes of
2314/// input, then that would need to be saved by the application outside of zlib.
2315///
2316/// # Returns
2317///
2318/// * [`Z_OK`] if success
2319/// * [`Z_STREAM_ERROR`] if the stream state is inconsistent
2320///
2321/// # Safety
2322///
2323/// - `dictionary` must `NULL` or writable for the dictionary length (`32768` is always enough)
2324/// - `dictLength` must `NULL` or satisfy the requirements of [`pointer::as_mut`]
2325///
2326/// [`pointer::as_mut`]: https://doc.rust-lang.org/core/primitive.pointer.html#method.as_mut
2327#[cfg_attr(feature = "export-symbols", export_name = prefix!(deflateGetDictionary))]
2328pub unsafe extern "C" fn deflateGetDictionary(
2329    strm: *const z_stream,
2330    dictionary: *mut c_uchar,
2331    dictLength: *mut c_uint,
2332) -> c_int {
2333    let Some(stream) = DeflateStream::from_stream_ref(strm) else {
2334        return ReturnCode::StreamError as c_int;
2335    };
2336
2337    let len = zlib_rs::deflate::get_dictionary(stream, dictionary);
2338
2339    if let Some(dictLength) = unsafe { dictLength.as_mut() } {
2340        *dictLength = len as c_uint;
2341    }
2342
2343    ReturnCode::Ok as _
2344}
2345
2346/// # Safety
2347///
2348/// Either
2349///
2350/// - `ptr` is `NULL`
2351/// - `ptr` and `len` satisfy the requirements of [`core::slice::from_raw_parts`]
2352unsafe fn slice_from_raw_parts<'a, T>(ptr: *const T, len: usize) -> Option<&'a [T]> {
2353    if ptr.is_null() {
2354        None
2355    } else {
2356        Some(unsafe { core::slice::from_raw_parts(ptr, len) })
2357    }
2358}
2359
2360/// # Safety
2361///
2362/// Either
2363///
2364/// - `ptr` is `NULL`
2365/// - `ptr` and `len` satisfy the requirements of [`core::slice::from_raw_parts_mut`]
2366unsafe fn slice_from_raw_parts_uninit_mut<'a, T>(
2367    ptr: *mut T,
2368    len: usize,
2369) -> Option<&'a mut [MaybeUninit<T>]> {
2370    if ptr.is_null() {
2371        None
2372    } else {
2373        Some(unsafe { core::slice::from_raw_parts_mut(ptr.cast::<MaybeUninit<T>>(), len) })
2374    }
2375}