Skip to main content

cloudflare_zlib_sys/
lib.rs

1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3//! It requires x86-64 CPU with SSE 4.2 or ARM64 with NEON & CRC.
4
5use std::os::raw::*;
6
7pub type alloc_func = unsafe extern "C" fn(voidpf, uInt, uInt) -> voidpf;
8pub type Bytef = u8;
9pub type free_func = unsafe extern "C" fn(voidpf, voidpf);
10pub type gzFile = *mut gzFile_s;
11pub type in_func = unsafe extern "C" fn(*mut c_void, *mut *const c_uchar) -> c_uint;
12pub type out_func = unsafe extern "C" fn(*mut c_void, *mut c_uchar, c_uint) -> c_int;
13pub type uInt = u32; // zconf.h says so
14pub type uLong = u64; // zconf.h says so
15pub type uLongf = uLong;
16pub type voidp = *mut c_void;
17pub type voidpc = *const c_void;
18pub type voidpf = *mut c_void;
19
20pub enum gzFile_s {}
21pub enum internal_state {}
22
23pub type z_off_t = isize;
24
25pub const ZLIB_VERSION: &[u8] = b"1.2.8";
26
27pub unsafe fn deflateInit2(strm: z_streamp, level: c_int, method: c_int, window_bits: c_int, mem_level: c_int, strategy: c_int) -> c_int {
28    deflateInit2_(strm, level, method, window_bits, mem_level, strategy, ZLIB_VERSION.as_ptr() as *const _, ::std::mem::size_of::<z_stream>() as c_int)
29}
30
31pub unsafe fn deflateInit(strm: z_streamp, level: c_int) -> c_int {
32    deflateInit_(strm, level, ZLIB_VERSION.as_ptr() as *const _, ::std::mem::size_of::<z_stream>() as c_int)
33}
34
35pub unsafe fn inflateInit(strm: z_streamp) -> c_int {
36    inflateInit_(strm, ZLIB_VERSION.as_ptr() as *const _, ::std::mem::size_of::<z_stream>() as c_int)
37}
38
39pub unsafe fn inflateInit2(strm: z_streamp, window_bits: c_int) -> c_int {
40    inflateInit2_(strm, window_bits, ZLIB_VERSION.as_ptr() as *const _, ::std::mem::size_of::<z_stream>() as c_int)
41}
42
43#[repr(C)]
44#[derive(Copy, Clone)]
45pub struct gz_header {
46    pub text: c_int,
47    pub time: uLong,
48    pub xflags: c_int,
49    pub os: c_int,
50    pub extra: *mut Bytef,
51    pub extra_len: uInt,
52    pub extra_max: uInt,
53    pub name: *mut Bytef,
54    pub name_max: uInt,
55    pub comment: *mut Bytef,
56    pub comm_max: uInt,
57    pub hcrc: c_int,
58    pub done: c_int,
59}
60pub type gz_headerp = *mut gz_header;
61
62#[repr(C)]
63#[derive(Copy, Clone)]
64pub struct z_stream {
65    pub next_in: *mut Bytef,
66    pub avail_in: uInt,
67    pub total_in: uLong,
68    pub next_out: *mut Bytef,
69    pub avail_out: uInt,
70    pub total_out: uLong,
71    pub msg: *mut c_char,
72    pub state: *mut internal_state,
73    pub zalloc: Option<alloc_func>,
74    pub zfree: Option<free_func>,
75    pub opaque: voidpf,
76    pub data_type: c_int,
77    pub adler: uLong,
78    pub reserved: uLong,
79}
80pub type z_streamp = *mut z_stream;
81
82extern "C" {
83    pub fn adler32(adler: uLong, buf: *const Bytef, len: uInt) -> uLong;
84    pub fn adler32_combine(adler1: uLong, adler2: uLong, len2: z_off_t) -> uLong;
85    pub fn compress(dest: *mut Bytef, destLen: *mut uLongf, source: *const Bytef, sourceLen: uLong) -> c_int;
86    pub fn compress2(dest: *mut Bytef, destLen: *mut uLongf, source: *const Bytef, sourceLen: uLong, level: c_int) -> c_int;
87    pub fn compressBound(sourceLen: uLong) -> uLong;
88    pub fn crc32(crc: uLong, buf: *const Bytef, len: uInt) -> uLong;
89    pub fn crc32_combine(crc1: uLong, crc2: uLong, len2: z_off_t) -> uLong;
90    pub fn deflate(strm: z_streamp, flush: c_int) -> c_int;
91    pub fn deflateBound(strm: z_streamp, sourceLen: uLong) -> uLong;
92    pub fn deflateCopy(dest: z_streamp, source: z_streamp) -> c_int;
93    pub fn deflateEnd(strm: z_streamp) -> c_int;
94    pub fn deflateInit2_(strm: z_streamp, level: c_int, method: c_int, windowBits: c_int, memLevel: c_int, strategy: c_int, version: *const c_char, stream_size: c_int) -> c_int;
95    pub fn deflateInit_(strm: z_streamp, level: c_int, version: *const c_char, stream_size: c_int) -> c_int;
96    pub fn deflateParams(strm: z_streamp, level: c_int, strategy: c_int) -> c_int;
97    pub fn deflatePending(strm: z_streamp, pending: *mut c_uint, bits: *mut c_int) -> c_int;
98    pub fn deflatePrime(strm: z_streamp, bits: c_int, value: c_int) -> c_int;
99    pub fn deflateReset(strm: z_streamp) -> c_int;
100    pub fn deflateResetKeep(arg1: z_streamp) -> c_int;
101    pub fn deflateSetDictionary(strm: z_streamp, dictionary: *const Bytef, dictLength: uInt) -> c_int;
102    pub fn deflateSetHeader(strm: z_streamp, head: gz_headerp) -> c_int;
103    pub fn deflateTune(strm: z_streamp, good_length: c_int, max_lazy: c_int, nice_length: c_int, max_chain: c_int) -> c_int;
104    pub fn gzclearerr(file: gzFile);
105    pub fn gzclose(file: gzFile) -> c_int;
106    pub fn gzdirect(file: gzFile) -> c_int;
107    pub fn gzdopen(fd: c_int, mode: *const c_char) -> gzFile;
108    pub fn gzeof(file: gzFile) -> c_int;
109    pub fn gzerror(file: gzFile, errnum: *mut c_int) -> *const c_char;
110    pub fn gzflush(file: gzFile, flush: c_int) -> c_int;
111    pub fn gzgetc(file: gzFile) -> c_int;
112    pub fn gzgets(file: gzFile, buf: *mut c_char, len: c_int) -> *mut c_char;
113    pub fn gzopen(path: *const c_char, mode: *const c_char) -> gzFile;
114    pub fn gzoffset(arg1: gzFile) -> c_long;
115    pub fn gzputc(file: gzFile, c: c_int) -> c_int;
116    pub fn gzputs(file: gzFile, s: *const c_char) -> c_int;
117    pub fn gzread(file: gzFile, buf: voidp, len: c_uint) -> c_int;
118    pub fn gzrewind(file: gzFile) -> c_int;
119    pub fn gzseek(file: gzFile, offset: z_off_t, whence: c_int) -> z_off_t;
120    pub fn gzsetparams(file: gzFile, level: c_int, strategy: c_int) -> c_int;
121    pub fn gztell(file: gzFile) -> z_off_t;
122    pub fn gzungetc(c: c_int, file: gzFile) -> c_int;
123    pub fn gzwrite(file: gzFile, buf: voidpc, len: c_uint) -> c_int;
124    pub fn inflate(strm: z_streamp, flush: c_int) -> c_int;
125    pub fn inflateCopy(dest: z_streamp, source: z_streamp) -> c_int;
126    pub fn inflateEnd(strm: z_streamp) -> c_int;
127    pub fn inflateGetDictionary(strm: z_streamp, dictionary: *mut Bytef, dictLength: *mut uInt) -> c_int;
128    pub fn inflateGetHeader(strm: z_streamp, head: gz_headerp) -> c_int;
129    pub fn inflateInit2_(strm: z_streamp, windowBits: c_int, version: *const c_char, stream_size: c_int) -> c_int;
130    pub fn inflateInit_(strm: z_streamp, version: *const c_char, stream_size: c_int) -> c_int;
131    pub fn inflateMark(strm: z_streamp) -> c_long;
132    pub fn inflatePrime(strm: z_streamp, bits: c_int, value: c_int) -> c_int;
133    pub fn inflateReset(strm: z_streamp) -> c_int;
134    pub fn inflateReset2(strm: z_streamp, windowBits: c_int) -> c_int;
135    pub fn inflateResetKeep(arg1: z_streamp) -> c_int;
136    pub fn inflateSetDictionary(strm: z_streamp, dictionary: *const Bytef, dictLength: uInt) -> c_int;
137    pub fn inflateSync(strm: z_streamp) -> c_int;
138    pub fn inflateSyncPoint(arg1: z_streamp) -> c_int;
139    pub fn inflateUndermine(arg1: z_streamp, arg2: c_int) -> c_int;
140    pub fn inflateValidate(arg1: z_streamp, arg2: c_int) -> c_int;
141    pub fn uncompress(dest: *mut Bytef, destLen: *mut uLongf, source: *const Bytef, sourceLen: uLong) -> c_int;
142    pub fn uncompress2(dest: *mut Bytef, destLen: *mut uLongf, source: *const Bytef, sourceLen: *mut uLong) -> c_int;
143    pub fn zError(arg1: c_int) -> *const c_char;
144    pub fn zlibCompileFlags() -> uLong;
145    pub fn zlibVersion() -> *const c_char;
146}
147
148pub const Z_NO_FLUSH: c_int = 0;
149pub const Z_PARTIAL_FLUSH: c_int = 1;
150pub const Z_SYNC_FLUSH: c_int = 2;
151pub const Z_FULL_FLUSH: c_int = 3;
152pub const Z_FINISH: c_int = 4;
153pub const Z_BLOCK: c_int = 5;
154pub const Z_TREES: c_int = 6;
155
156pub const Z_OK: c_int = 0;
157pub const Z_STREAM_END: c_int = 1;
158pub const Z_NEED_DICT: c_int = 2;
159pub const Z_ERRNO: c_int = -1;
160pub const Z_STREAM_ERROR: c_int = -2;
161pub const Z_DATA_ERROR: c_int = -3;
162pub const Z_MEM_ERROR: c_int = -4;
163pub const Z_BUF_ERROR: c_int = -5;
164pub const Z_VERSION_ERROR: c_int = -6;
165
166pub const Z_NO_COMPRESSION: c_int = 0;
167pub const Z_BEST_SPEED: c_int = 1;
168pub const Z_BEST_COMPRESSION: c_int = 9;
169pub const Z_DEFAULT_COMPRESSION: c_int = -1;
170
171pub const Z_FILTERED: c_int = 1;
172pub const Z_HUFFMAN_ONLY: c_int = 2;
173pub const Z_RLE: c_int = 3;
174pub const Z_FIXED: c_int = 4;
175pub const Z_DEFAULT_STRATEGY: c_int = 0;
176
177pub const Z_BINARY: c_int = 0;
178pub const Z_TEXT: c_int = 1;
179pub const Z_ASCII: c_int = Z_TEXT;
180pub const Z_UNKNOWN: c_int = 2;
181
182pub const Z_DEFLATED: c_int = 8;
183pub const MAX_MEM_LEVEL: c_int = 8;
184pub const DEF_MEM_LEVEL: c_int = 8;
185
186#[cfg(test)]
187mod test {
188    use super::*;
189
190    #[test]
191    fn test_files() {
192        for i in 1..=1 {
193            assert_roundtrips(&std::fs::read(format!("rust/test_files/test{i}")).unwrap());
194        }
195    }
196
197    #[test]
198    fn test_synthetic() {
199        assert_roundtrips(&[0; 0]);
200        assert_roundtrips(&[0; 1]);
201        assert_roundtrips(&[0; 10]);
202        assert_roundtrips(&vec![0; 1000]);
203        assert_roundtrips(&[0xff; 1]);
204        assert_roundtrips(&[0xff; 2]);
205        assert_roundtrips(&[0xff; 3]);
206    }
207
208    #[test]
209    fn test_compress() {
210        let source = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
211tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
212quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
213consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
214cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
215proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
216        assert_eq!(446, source.len());
217        let compressed = assert_roundtrips(source.as_bytes());
218        assert_eq!(271, compressed.len());
219    }
220
221    fn assert_roundtrips(source: &[u8]) -> Vec<u8> {
222        let mut gzbuf = Vec::with_capacity(100 + source.len());
223        let mut gzbuf_len = gzbuf.capacity() as uLong;
224        unsafe {
225            assert_eq!(0, compress2(gzbuf.as_mut_ptr(), &mut gzbuf_len, source.as_ptr(), source.len() as uLong, Z_BEST_COMPRESSION));
226            gzbuf.set_len(gzbuf_len as usize);
227        }
228
229        let mut ungzbuf = vec![0x55; 100 + source.len()];
230        let mut ungzbuf_len = source.len() as uLong;
231        unsafe {
232            assert_eq!(0, uncompress(ungzbuf.as_mut_ptr(), &mut ungzbuf_len, gzbuf.as_ptr(), gzbuf.len() as uLong));
233        }
234        let (ungzipped, rest) = ungzbuf.split_at(source.len());
235        assert_eq!(source, ungzipped);
236        rest.iter().for_each(|&x| assert_eq!(x, 0x55));
237        gzbuf
238    }
239}