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