#![allow(non_camel_case_types)] #![allow(non_snake_case)] use core::ffi::{c_char, c_int, c_uchar, c_uint, c_ulong, c_void}; use crate::allocate::Allocator; pub type alloc_func = unsafe extern "C" fn(voidpf, uInt, uInt) -> voidpf; pub type free_func = unsafe extern "C" fn(voidpf, voidpf); pub type Bytef = u8; pub type in_func = unsafe extern "C" fn(*mut c_void, *mut *const c_uchar) -> c_uint; pub type out_func = unsafe extern "C" fn(*mut c_void, *mut c_uchar, c_uint) -> c_int; pub type uInt = c_uint; pub type uLong = c_ulong; pub type uLongf = c_ulong; pub type voidp = *mut c_void; pub type voidpc = *const c_void; pub type voidpf = *mut c_void; /// The current stream state /// /// # Custom allocators /// /// The low-level API supports passing in a custom allocator as part of the [`z_stream`]: /// /// ```no_check /// struct z_stream { /// // ... /// zalloc: Option *mut c_void>, /// zfree: Option, /// opaque: *mut c_void, /// } /// ``` /// /// When these fields are `None` (or `NULL` in C), the initialization functions use a default allocator, /// based on feature flags: /// /// - `"rust-allocator"` uses the rust global allocator /// - `"c-allocator"` uses an allocator based on `malloc` and `free` /// /// When both are configured, the `"rust-allocator"` is preferred. When no default allocator is configured, /// and custom `zalloc` and `zfree` are provided, the initialization functions will return a [`Z_STREAM_ERROR`]. /// /// When custom `zalloc` and `zfree` functions are given, they must adhere to the following contract /// to be safe: /// /// - a call `zalloc(opaque, n, m)` must return a pointer `p` to `n * m` bytes of memory, or /// `NULL` if out of memory /// - a call `zfree(opaque, p)` must free that memory /// /// The `strm.opaque` value is passed to as the first argument to all calls to `zalloc` /// and `zfree`, but is otherwise ignored by the library. #[repr(C)] #[derive(Copy, Clone)] pub struct z_stream { pub next_in: *const Bytef, pub avail_in: uInt, pub total_in: z_size, pub next_out: *mut Bytef, pub avail_out: uInt, pub total_out: z_size, pub msg: *mut c_char, pub state: *mut internal_state, pub zalloc: Option, pub zfree: Option, pub opaque: voidpf, pub data_type: c_int, pub adler: z_checksum, pub reserved: uLong, } pub type z_streamp = *mut z_stream; impl Default for z_stream { fn default() -> Self { let mut stream = Self { next_in: core::ptr::null_mut(), avail_in: 0, total_in: 0, next_out: core::ptr::null_mut(), avail_out: 0, total_out: 0, msg: core::ptr::null_mut(), state: core::ptr::null_mut(), zalloc: None, zfree: None, opaque: core::ptr::null_mut(), data_type: 0, adler: 0, reserved: 0, }; #[cfg(feature = "rust-allocator")] if stream.zalloc.is_none() || stream.zfree.is_none() { stream.configure_default_rust_allocator() } #[cfg(feature = "c-allocator")] if stream.zalloc.is_none() || stream.zfree.is_none() { stream.configure_default_c_allocator() } stream } } impl z_stream { fn configure_allocator(&mut self, alloc: Allocator) { self.zalloc = Some(alloc.zalloc); self.zfree = Some(alloc.zfree); self.opaque = alloc.opaque; } #[cfg(feature = "rust-allocator")] pub fn configure_default_rust_allocator(&mut self) { self.configure_allocator(crate::allocate::RUST) } #[cfg(feature = "c-allocator")] pub fn configure_default_c_allocator(&mut self) { self.configure_allocator(crate::allocate::C) } } // // zlib stores Adler-32 and CRC-32 checksums in unsigned long; zlib-ng uses uint32_t. pub(crate) type z_size = c_ulong; pub(crate) type z_checksum = c_ulong; // opaque to the user pub enum internal_state {} pub const Z_NO_FLUSH: c_int = 0; pub const Z_PARTIAL_FLUSH: c_int = 1; pub const Z_SYNC_FLUSH: c_int = 2; pub const Z_FULL_FLUSH: c_int = 3; pub const Z_FINISH: c_int = 4; pub const Z_BLOCK: c_int = 5; pub const Z_TREES: c_int = 6; pub const Z_OK: c_int = 0; pub const Z_STREAM_END: c_int = 1; pub const Z_NEED_DICT: c_int = 2; pub const Z_ERRNO: c_int = -1; pub const Z_STREAM_ERROR: c_int = -2; pub const Z_DATA_ERROR: c_int = -3; pub const Z_MEM_ERROR: c_int = -4; pub const Z_BUF_ERROR: c_int = -5; pub const Z_VERSION_ERROR: c_int = -6; pub const Z_NO_COMPRESSION: c_int = 0; pub const Z_BEST_SPEED: c_int = 1; pub const Z_BEST_COMPRESSION: c_int = 9; pub const Z_DEFAULT_COMPRESSION: c_int = -1; pub const Z_DEFLATED: c_int = 8; pub const Z_BINARY: c_int = 0; pub const Z_TEXT: c_int = 1; pub const Z_ASCII: c_int = Z_TEXT; /* for compatibility with 1.2.2 and earlier */ pub const Z_UNKNOWN: c_int = 2; pub const Z_FILTERED: c_int = 1; pub const Z_HUFFMAN_ONLY: c_int = 2; pub const Z_RLE: c_int = 3; pub const Z_FIXED: c_int = 4; pub const Z_DEFAULT_STRATEGY: c_int = 0; pub type gz_headerp = *mut gz_header; /// gzip header information passed to and from zlib routines. /// See RFC 1952 for more details on the meanings of these fields. #[derive(Debug)] #[repr(C)] pub struct gz_header { /// true if compressed data believed to be text pub text: i32, /// modification time pub time: c_ulong, /// extra flags (not used when writing a gzip file) pub xflags: i32, /// operating system pub os: i32, /// pointer to extra field or NULL if none pub extra: *mut u8, /// extra field length (valid if extra != NULL) pub extra_len: u32, /// space at extra (only when reading header) pub extra_max: u32, /// pointer to zero-terminated file name or NULL pub name: *mut u8, /// space at name (only when reading header) pub name_max: u32, /// pointer to zero-terminated comment or NULL pub comment: *mut u8, /// space at comment (only when reading header) pub comm_max: u32, /// true if there was or will be a header crc pub hcrc: i32, /// true when done reading gzip header (not used when writing a gzip file) pub done: i32, } impl Default for gz_header { fn default() -> Self { Self { text: 0, time: 0, xflags: 0, os: 0, extra: core::ptr::null_mut(), extra_len: 0, extra_max: 0, name: core::ptr::null_mut(), name_max: 0, comment: core::ptr::null_mut(), comm_max: 0, hcrc: 0, done: 0, } } } impl gz_header { // based on the spec https://www.ietf.org/rfc/rfc1952.txt // // 0 - FAT filesystem (MS-DOS, OS/2, NT/Win32) // 1 - Amiga // 2 - VMS (or OpenVMS) // 3 - Unix // 4 - VM/CMS // 5 - Atari TOS // 6 - HPFS filesystem (OS/2, NT) // 7 - Macintosh // 8 - Z-System // 9 - CP/M // 10 - TOPS-20 // 11 - NTFS filesystem (NT) // 12 - QDOS // 13 - Acorn RISCOS // 255 - unknown #[allow(clippy::if_same_then_else)] pub const OS_CODE: u8 = { if cfg!(windows) { 10 } else if cfg!(target_os = "macos") { 19 } else if cfg!(unix) { 3 } else { 3 // assume unix } }; pub(crate) fn flags(&self) -> u8 { (if self.text != 0 { 1 } else { 0 }) + (if self.hcrc != 0 { 2 } else { 0 }) + (if self.extra.is_null() { 0 } else { 4 }) + (if self.name.is_null() { 0 } else { 8 }) + (if self.comment.is_null() { 0 } else { 16 }) } }