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
mod lzo1x_compress;
mod lzo1x_decompress_safe;
extern crate libc;
use std::mem;
use std::slice;
pub fn worst_compress(size: usize) -> usize {
((size) + ((size) / 16) + 64 + 3)
}
const LZO1X_1_MEM_COMPRESS: usize = (8192 * 16);
const LZO1X_MEM_COMPRESS: usize = LZO1X_1_MEM_COMPRESS;
#[repr(i32)]
#[derive(PartialEq)]
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 fn compress(&mut self, input: &[u8], output: &mut Vec<u8>) -> LZOError {
unsafe {
let mut out_len = output.capacity();
let err = lzo1x_compress::lzo1x_1_compress(input.as_ptr(),
input.len(),
output.as_mut_ptr(),
&mut out_len,
&mut *self.wrkmem as *mut _ as *mut _);
output.set_len(out_len);
mem::transmute::<i32, LZOError>(err)
}
}
pub fn compress_to_slice<'a>(&mut self, in_: &[u8], out: &'a mut [u8]) -> (&'a mut [u8], LZOError) {
unsafe {
let mut out_len = out.len();
let err = lzo1x_compress::lzo1x_1_compress(in_.as_ptr(),
in_.len(),
out.as_mut_ptr(),
&mut out_len,
&mut *self.wrkmem as *mut _ as *mut _);
(slice::from_raw_parts_mut(out.as_mut_ptr(), out_len),
mem::transmute::<i32, LZOError>(err))
}
}
pub fn decompress_to_slice<'a>(in_: &[u8], out: &'a mut [u8]) -> (&'a mut [u8], LZOError) {
unsafe {
let mut out_len = out.len();
let err = lzo1x_decompress_safe::lzo1x_decompress_safe(in_.as_ptr(),
in_.len(),
out.as_mut_ptr(),
&mut out_len);
(slice::from_raw_parts_mut(out.as_mut_ptr(), out_len),
mem::transmute::<i32, LZOError>(err))
}
}
}
#[test]
fn it_works() {
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 = worst_compress(mem::size_of_val(&data));
let mut v = Vec::with_capacity(dst_len);
let dst = libc::malloc(dst_len);
let mut ctx = LZOContext::new();
let mut dst = slice::from_raw_parts_mut(dst as *mut u8, dst_len);
let (dst, err) = ctx.compress_to_slice(&data, &mut dst);
assert!(err == LZOError::OK);
let err = ctx.compress(&data, &mut v);
assert!(err == LZOError::OK);
println!("{}", dst.len());
let dec_dst = libc::malloc(mem::size_of_val(&data));
let result_len = mem::size_of_val(&data);
let mut dec_dst = slice::from_raw_parts_mut(dec_dst as *mut u8, result_len);
let (result, err) = LZOContext::decompress_to_slice(&dst, &mut dec_dst);
assert!(err == LZOError::OK);
println!("{}", result.len());
assert!(result.len() == mem::size_of_val(&data));
assert!(&data[..] == result);
}
}