libz_rs_sys/
lib.rs

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