rust_lzo/
lib.rs

1mod lzo1x_compress;
2mod lzo1x_decompress_safe;
3extern crate libc;
4use std::mem;
5use std::slice;
6
7/// for a given `size` computes the worst case size that the compresed result can be
8pub fn worst_compress(size: usize) -> usize {
9    ((size) + ((size) / 16) + 64 + 3)
10}
11
12const LZO1X_1_MEM_COMPRESS: usize = (8192 * 16);
13const LZO1X_MEM_COMPRESS: usize = LZO1X_1_MEM_COMPRESS;
14
15#[repr(i32)]
16#[derive(PartialEq)]
17pub enum LZOError {
18    OK = 0,
19    ERROR = -1,
20    OUT_OF_MEMORY = -2,
21    NOT_COMPRESSIBLE = -3,
22    INPUT_OVERRUN = -4,
23    OUTPUT_OVERRUN = -5,
24    LOOKBEHIND_OVERRUN = -6,
25    EOF_NOT_FOUND = -7,
26    INPUT_NOT_CONSUMED = -8,
27    NOT_YET_IMPLEMENTED = -9,
28    INVALID_ARGUMENT = -10,
29}
30
31pub struct LZOContext {
32    wrkmem: *mut libc::c_void,
33}
34
35impl Drop for LZOContext {
36    fn drop(&mut self) {
37        unsafe {
38            libc::free(self.wrkmem);
39        }
40    }
41}
42
43impl LZOContext {
44    pub fn new() -> LZOContext {
45        LZOContext { wrkmem: unsafe { libc::malloc(LZO1X_MEM_COMPRESS) } }
46    }
47
48    /// compress `input` into `output`
49    /// returns an error if the Vec is not large enough
50    pub fn compress(&mut self, input: &[u8], output: &mut Vec<u8>) -> LZOError {
51        unsafe {
52            let mut out_len = output.capacity();
53            let err = lzo1x_compress::lzo1x_1_compress(input.as_ptr(),
54                                                       input.len(),
55                                                       output.as_mut_ptr(),
56                                                       &mut out_len,
57                                                       &mut *self.wrkmem as *mut _ as *mut _);
58
59            output.set_len(out_len);
60            mem::transmute::<i32, LZOError>(err)
61        }
62    }
63
64    /// returns a slice containing the compressed data
65    pub fn compress_to_slice<'a>(&mut self, in_: &[u8], out: &'a mut [u8]) -> (&'a mut [u8], LZOError) {
66        unsafe {
67            let mut out_len = out.len();
68            let err = lzo1x_compress::lzo1x_1_compress(in_.as_ptr(),
69                                                       in_.len(),
70                                                       out.as_mut_ptr(),
71                                                       &mut out_len,
72                                                       &mut *self.wrkmem as *mut _ as *mut _);
73            (slice::from_raw_parts_mut(out.as_mut_ptr(), out_len),
74             mem::transmute::<i32, LZOError>(err))
75        }
76    }
77
78    /// returns a slice containing the decompressed data
79    pub fn decompress_to_slice<'a>(in_: &[u8], out: &'a mut [u8]) -> (&'a mut [u8], LZOError) {
80        unsafe {
81            let mut out_len = out.len();
82            let err = lzo1x_decompress_safe::lzo1x_decompress_safe(in_.as_ptr(),
83                                                                   in_.len(),
84                                                                   out.as_mut_ptr(),
85                                                                   &mut out_len);
86            (slice::from_raw_parts_mut(out.as_mut_ptr(), out_len),
87             mem::transmute::<i32, LZOError>(err))
88        }
89    }
90}
91
92#[test]
93fn it_works() {
94    unsafe {
95        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,
96                    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,
97                    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,
98                    2, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 4];
99        let mut dst_len: usize = worst_compress(mem::size_of_val(&data));
100        let mut v = Vec::with_capacity(dst_len);
101        let dst = libc::malloc(dst_len);
102        let mut ctx = LZOContext::new();
103        let mut dst = slice::from_raw_parts_mut(dst as *mut u8, dst_len);
104        let (dst, err) = ctx.compress_to_slice(&data, &mut dst);
105        assert!(err == LZOError::OK);
106        let err = ctx.compress(&data, &mut v);
107        assert!(err == LZOError::OK);
108        println!("{}", dst.len());
109
110        let dec_dst = libc::malloc(mem::size_of_val(&data));
111        let result_len = mem::size_of_val(&data);
112        let mut dec_dst = slice::from_raw_parts_mut(dec_dst as *mut u8, result_len);
113        let (result, err) = LZOContext::decompress_to_slice(&dst, &mut dec_dst);
114        assert!(err == LZOError::OK);
115        println!("{}", result.len());
116        assert!(result.len() == mem::size_of_val(&data));
117        assert!(&data[..] == result);
118    }
119
120}