zlib_rs/
c_api.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3
4use core::ffi::{c_char, c_int, c_uchar, c_uint, c_ulong, c_void};
5
6use crate::allocate::Allocator;
7
8pub type alloc_func = unsafe extern "C" fn(voidpf, uInt, uInt) -> voidpf;
9pub type free_func = unsafe extern "C" fn(voidpf, voidpf);
10
11pub type Bytef = u8;
12pub type in_func = unsafe extern "C" fn(*mut c_void, *mut *const c_uchar) -> c_uint;
13pub type out_func = unsafe extern "C" fn(*mut c_void, *mut c_uchar, c_uint) -> c_int;
14pub type uInt = c_uint;
15pub type uLong = c_ulong;
16pub type uLongf = c_ulong;
17pub type voidp = *mut c_void;
18pub type voidpc = *const c_void;
19pub type voidpf = *mut c_void;
20
21#[repr(C)]
22#[derive(Copy, Clone)]
23pub struct z_stream {
24    pub next_in: *const Bytef,
25    pub avail_in: uInt,
26    pub total_in: z_size,
27    pub next_out: *mut Bytef,
28    pub avail_out: uInt,
29    pub total_out: z_size,
30    pub msg: *mut c_char,
31    pub state: *mut internal_state,
32    pub zalloc: Option<alloc_func>,
33    pub zfree: Option<free_func>,
34    pub opaque: voidpf,
35    pub data_type: c_int,
36    pub adler: z_checksum,
37    pub reserved: uLong,
38}
39pub type z_streamp = *mut z_stream;
40
41impl Default for z_stream {
42    fn default() -> Self {
43        let mut stream = Self {
44            next_in: core::ptr::null_mut(),
45            avail_in: 0,
46            total_in: 0,
47            next_out: core::ptr::null_mut(),
48            avail_out: 0,
49            total_out: 0,
50            msg: core::ptr::null_mut(),
51            state: core::ptr::null_mut(),
52            zalloc: None,
53            zfree: None,
54            opaque: core::ptr::null_mut(),
55            data_type: 0,
56            adler: 0,
57            reserved: 0,
58        };
59
60        #[cfg(feature = "rust-allocator")]
61        if stream.zalloc.is_none() || stream.zfree.is_none() {
62            stream.configure_default_rust_allocator()
63        }
64
65        #[cfg(feature = "c-allocator")]
66        if stream.zalloc.is_none() || stream.zfree.is_none() {
67            stream.configure_default_c_allocator()
68        }
69
70        stream
71    }
72}
73
74impl z_stream {
75    fn configure_allocator(&mut self, alloc: Allocator) {
76        self.zalloc = Some(alloc.zalloc);
77        self.zfree = Some(alloc.zfree);
78        self.opaque = alloc.opaque;
79    }
80
81    #[cfg(feature = "rust-allocator")]
82    pub fn configure_default_rust_allocator(&mut self) {
83        self.configure_allocator(Allocator::RUST)
84    }
85
86    #[cfg(feature = "c-allocator")]
87    pub fn configure_default_c_allocator(&mut self) {
88        self.configure_allocator(Allocator::C)
89    }
90}
91
92// // zlib stores Adler-32 and CRC-32 checksums in unsigned long; zlib-ng uses uint32_t.
93pub(crate) type z_size = c_ulong;
94pub(crate) type z_checksum = c_ulong;
95
96// opaque to the user
97pub enum internal_state {}
98
99pub const Z_NO_FLUSH: c_int = 0;
100pub const Z_PARTIAL_FLUSH: c_int = 1;
101pub const Z_SYNC_FLUSH: c_int = 2;
102pub const Z_FULL_FLUSH: c_int = 3;
103pub const Z_FINISH: c_int = 4;
104pub const Z_BLOCK: c_int = 5;
105pub const Z_TREES: c_int = 6;
106
107pub const Z_OK: c_int = 0;
108pub const Z_STREAM_END: c_int = 1;
109pub const Z_NEED_DICT: c_int = 2;
110pub const Z_ERRNO: c_int = -1;
111pub const Z_STREAM_ERROR: c_int = -2;
112pub const Z_DATA_ERROR: c_int = -3;
113pub const Z_MEM_ERROR: c_int = -4;
114pub const Z_BUF_ERROR: c_int = -5;
115pub const Z_VERSION_ERROR: c_int = -6;
116
117pub const Z_NO_COMPRESSION: c_int = 0;
118pub const Z_BEST_SPEED: c_int = 1;
119pub const Z_BEST_COMPRESSION: c_int = 9;
120pub const Z_DEFAULT_COMPRESSION: c_int = -1;
121
122pub const Z_DEFLATED: c_int = 8;
123
124pub const Z_BINARY: c_int = 0;
125pub const Z_TEXT: c_int = 1;
126pub const Z_ASCII: c_int = Z_TEXT; /* for compatibility with 1.2.2 and earlier */
127pub const Z_UNKNOWN: c_int = 2;
128
129pub const Z_FILTERED: c_int = 1;
130pub const Z_HUFFMAN_ONLY: c_int = 2;
131pub const Z_RLE: c_int = 3;
132pub const Z_FIXED: c_int = 4;
133pub const Z_DEFAULT_STRATEGY: c_int = 0;
134
135pub type gz_headerp = *mut gz_header;
136
137/// gzip header information passed to and from zlib routines.
138/// See RFC 1952 for more details on the meanings of these fields.
139#[derive(Debug)]
140#[repr(C)]
141pub struct gz_header {
142    /// true if compressed data believed to be text
143    pub text: i32,
144    /// modification time
145    pub time: c_ulong,
146    /// extra flags (not used when writing a gzip file)
147    pub xflags: i32,
148    /// operating system
149    pub os: i32,
150    /// pointer to extra field or NULL if none
151    pub extra: *mut u8,
152    /// extra field length (valid if extra != NULL)
153    pub extra_len: u32,
154    /// space at extra (only when reading header)
155    pub extra_max: u32,
156    /// pointer to zero-terminated file name or NULL
157    pub name: *mut u8,
158    /// space at name (only when reading header)
159    pub name_max: u32,
160    /// pointer to zero-terminated comment or NULL
161    pub comment: *mut u8,
162    /// space at comment (only when reading header)
163    pub comm_max: u32,
164    /// true if there was or will be a header crc
165    pub hcrc: i32,
166    /// true when done reading gzip header (not used when writing a gzip file)
167    pub done: i32,
168}
169
170impl Default for gz_header {
171    fn default() -> Self {
172        Self {
173            text: 0,
174            time: 0,
175            xflags: 0,
176            os: 0,
177            extra: core::ptr::null_mut(),
178            extra_len: 0,
179            extra_max: 0,
180            name: core::ptr::null_mut(),
181            name_max: 0,
182            comment: core::ptr::null_mut(),
183            comm_max: 0,
184            hcrc: 0,
185            done: 0,
186        }
187    }
188}
189
190impl gz_header {
191    // based on the spec https://www.ietf.org/rfc/rfc1952.txt
192    //
193    //   0 - FAT filesystem (MS-DOS, OS/2, NT/Win32)
194    //   1 - Amiga
195    //   2 - VMS (or OpenVMS)
196    //   3 - Unix
197    //   4 - VM/CMS
198    //   5 - Atari TOS
199    //   6 - HPFS filesystem (OS/2, NT)
200    //   7 - Macintosh
201    //   8 - Z-System
202    //   9 - CP/M
203    //  10 - TOPS-20
204    //  11 - NTFS filesystem (NT)
205    //  12 - QDOS
206    //  13 - Acorn RISCOS
207    // 255 - unknown
208    #[allow(clippy::if_same_then_else)]
209    pub const OS_CODE: u8 = {
210        if cfg!(windows) {
211            10
212        } else if cfg!(target_os = "macos") {
213            19
214        } else if cfg!(unix) {
215            3
216        } else {
217            3 // assume unix
218        }
219    };
220
221    pub(crate) fn flags(&self) -> u8 {
222        (if self.text > 0 { 1 } else { 0 })
223            + (if self.hcrc > 0 { 2 } else { 0 })
224            + (if self.extra.is_null() { 0 } else { 4 })
225            + (if self.name.is_null() { 0 } else { 8 })
226            + (if self.comment.is_null() { 0 } else { 16 })
227    }
228}