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
mod lzo1x_compress;
mod lzo1x_decompress_safe;
extern crate libc;
use std::mem;

fn lzo1x_worst_compress(x: usize) -> usize {
    ((x) + ((x) / 16) + 64 + 3)
}

const LZO1X_1_MEM_COMPRESS: usize = (8192 * 16);
const LZO1X_MEM_COMPRESS: usize = LZO1X_1_MEM_COMPRESS;

#[repr(i32)]
pub enum LZOError {
    OK = 0,
    ERROR = -1,
    OUT_OF_MEMORY = -2,
    NOT_COMPRESSIBLE = -3,
    INPUT_OVERRUN = -4,
    OUTPUT_OVERRUN = -5,
    LOOKBEHIND_OVERRUN = -6,
    EOF_NOT_FOUND = -7,
    INPUT_NOT_CONSUMED = -8,
    NOT_YET_IMPLEMENTED = -9,
    INVALID_ARGUMENT = -10,
}

pub struct LZOContext {
    wrkmem: *mut libc::c_void,
}

impl Drop for LZOContext {
    fn drop(&mut self) {
        unsafe {
            libc::free(self.wrkmem);
        }
    }
}

impl LZOContext {
    pub fn new() -> LZOContext {
        LZOContext { wrkmem: unsafe { libc::malloc(LZO1X_MEM_COMPRESS) } }
    }

    pub unsafe fn compress(&mut self,
                           in_: &[u8],
                           out: *mut u8,
                           out_len: *mut usize)
                           -> LZOError {
        mem::transmute::<i32, LZOError>(lzo1x_compress::lzo1x_1_compress(in_.as_ptr(),
                                                                         in_.len(),
                                                                         out,
                                                                         out_len,
                                                                         &mut *self.wrkmem as
                                                                         *mut _ as
                                                                         *mut _))
    }
    pub unsafe fn decompress(in_: &[u8],
                             out: *mut u8,
                             out_len: *mut usize)
                             -> LZOError {
        mem::transmute::<i32, LZOError>(lzo1x_decompress_safe::lzo1x_decompress_safe(in_.as_ptr(),
                                                                                     in_.len(),
                                                                                     out,
                                                                                     out_len))
    }
}

#[test]
fn it_works() {
    use std::slice;
    unsafe {
        let data = [0u8, 2, 3, 4, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    2, 3, 4, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3,
                    4, 2, 2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4, 2,
                    2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4];
        let mut dst_len: usize = lzo1x_worst_compress(mem::size_of_val(&data));
        let dst = libc::malloc(dst_len);
        let mut ctx = LZOContext::new();
        let err = ctx.compress(&data,
                               dst as *mut u8,
                               &mut dst_len);
        println!("{}", dst_len);

        let dec_dst = libc::malloc(mem::size_of_val(&data));
        let mut result_len = mem::size_of_val(&data);
        let dst = slice::from_raw_parts(dst as *const u8, dst_len);
        let err = LZOContext::decompress(&dst,
                                         dec_dst as *mut u8,
                                         &mut result_len);
        println!("{}", result_len);
    }

}