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