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