1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
#![allow(bad_style)]

#[repr(C)]
pub struct libdeflate_compressor { _unused : [ u8 ; 0 ] , }
#[repr(C)]
pub struct libdeflate_decompressor { _unused : [ u8 ; 0 ] , }
pub const libdeflate_result_LIBDEFLATE_SUCCESS: libdeflate_result = 0;
pub const libdeflate_result_LIBDEFLATE_BAD_DATA: libdeflate_result = 1;
pub const libdeflate_result_LIBDEFLATE_SHORT_OUTPUT: libdeflate_result = 2;
pub const libdeflate_result_LIBDEFLATE_INSUFFICIENT_SPACE: libdeflate_result = 3;
pub type libdeflate_result = u32 ;

extern "C" {
    pub fn libdeflate_alloc_decompressor() -> *mut libdeflate_decompressor;
    pub fn libdeflate_free_decompressor(decompressor: *mut libdeflate_decompressor);

    pub fn libdeflate_gzip_decompress(decompressor: *mut libdeflate_decompressor,
                                      in_: *const ::std::os::raw::c_void,
                                      in_nbytes: usize ,
                                      out: *mut ::std::os::raw::c_void,
                                      out_nbytes_avail: usize,
                                      actual_out_nbytes_ret: *mut usize) -> libdeflate_result;

    pub fn libdeflate_zlib_decompress(decompressor: *mut libdeflate_decompressor,
                                      in_: *const ::std::os::raw::c_void,
                                      in_nbytes: usize,
                                      out: *mut ::std::os::raw::c_void,
                                      out_nbytes_avail: usize,
                                      actual_out_nbytes_ret: *mut usize) -> libdeflate_result;

    pub fn libdeflate_deflate_decompress(decompressor: *mut libdeflate_decompressor,
                                         in_: *const ::std::os::raw::c_void,
                                         in_nbytes: usize,
                                         out: *mut ::std::os::raw::c_void,
                                         out_nbytes_avail: usize,
                                         actual_out_nbytes_ret: *mut usize) -> libdeflate_result;

    pub fn libdeflate_alloc_compressor(compression_level: ::std::os::raw::c_int) -> *mut libdeflate_compressor;

    pub fn libdeflate_deflate_compress_bound(compressor: *mut libdeflate_compressor,
                                             in_nbytes: usize) -> usize;


    pub fn libdeflate_deflate_compress(compressor: *mut libdeflate_compressor,
                                       in_: *const ::std::os::raw::c_void,
                                       in_nbytes: usize,
                                       out: *mut ::std::os::raw::c_void,
                                       out_nbytes_avail: usize) -> usize;

    pub fn libdeflate_zlib_compress_bound(compressor: *mut libdeflate_compressor,
                                          in_nbytes: usize) -> usize;

    pub fn libdeflate_zlib_compress(compressor: *mut libdeflate_compressor,
                                    in_: *const ::std::os::raw::c_void,
                                    in_nbytes: usize,
                                    out: *mut ::std::os::raw::c_void,
                                    out_nbytes_avail: usize) -> usize;

    pub fn libdeflate_gzip_compress_bound(compressor: *mut libdeflate_compressor,
                                          in_nbytes: usize) -> usize;

    pub fn libdeflate_gzip_compress(compressor: *mut libdeflate_compressor,
                                    in_: *const ::std::os::raw::c_void,
                                    in_nbytes: usize,
                                    out: *mut ::std::os::raw::c_void,
                                    out_nbytes_avail: usize ) -> usize;

    pub fn libdeflate_free_compressor (compressor : * mut libdeflate_compressor);

    pub fn libdeflate_crc32(crc32: u32,
                            buffer: *const ::std::os::raw::c_void,
                            len: usize) -> u32;

    pub fn libdeflate_adler32(adler32: u32,
                              buffer: *const ::std::os::raw::c_void,
                              len: usize) -> u32;

    pub fn libdeflate_set_memory_allocator(malloc_func: unsafe extern "C" fn(size: usize) -> *mut ::std::os::raw::c_void,
                                           free_func: unsafe extern "C" fn(ptr: *mut ::std::os::raw::c_void));
}

// Basic tests for Rust-to-C bindings. These tests are just for quick
// internal checks to make sure that the bindgen build script built
// something sane-looking. User-facing tests are in `tests/`
#[cfg(test)]
mod tests {
    use super::*;

    const MIN_COMP_LVL: i32 = 1;
    const MAX_COMP_LVL: i32 = 12;

    #[test]
    fn can_make_decompressor_at_each_compression_lvl() {
        unsafe {
            for lvl in MIN_COMP_LVL..MAX_COMP_LVL+1 {
                let ptr = libdeflate_alloc_compressor(lvl);

                assert!(!ptr.is_null());

                libdeflate_free_compressor(ptr);
            }
        }
    }

    #[test]
    fn making_compressor_with_negative_compression_lvl_fails() {
        unsafe {
            let ptr = libdeflate_alloc_compressor(-1);
            assert!(ptr.is_null());
        }
    }

    #[test]
    fn making_compressor_with_too_large_compression_lvl_fails() {
        unsafe {
            let ptr = libdeflate_alloc_compressor(MAX_COMP_LVL+1);

            assert!(ptr.is_null());
        }
    }

    #[test]
    fn can_use_compressor_to_compress_trivially_compressable_data() {
        unsafe {
            let in_data: [u8; 1<<16] = [0; 1<<16];
            let mut out_data: [u8; 1<<16] = [0; 1<<16];
            let compressor = libdeflate_alloc_compressor(MAX_COMP_LVL);
            let sz = libdeflate_deflate_compress(compressor,
                                                 in_data.as_ptr() as *const core::ffi::c_void,
                                                 in_data.len(),
                                                 out_data.as_mut_ptr() as *mut core::ffi::c_void,
                                                 out_data.len());
            assert_ne!(sz, 0);
            assert!(sz < 100);
        }
    }

    #[test]
    fn can_call_crc32() {
        let init = 0;
        let buf: [u8; 4] = [0x31, 0x33, 0x33, 0x37];

        unsafe {
            let ret = libdeflate_crc32(init,
                                       buf.as_ptr() as *const core::ffi::c_void,
                                       buf.len());

            assert_ne!(ret, init);
        }
    }

    #[test]
    fn can_call_adler32() {
        let init = 0;
        let buf: [u8; 4] = [0x31, 0x33, 0x33, 0x37];

        unsafe {
            let ret = libdeflate_adler32(init,
                                         buf.as_ptr() as *const core::ffi::c_void,
                                         buf.len());

            assert_ne!(ret, init);
        }
    }
}