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