io_engine/buffer/
lz4.rs

1use std::io::{Error, ErrorKind, Result};
2
3use log::*;
4use lz4_sys::*;
5
6pub const ERR_LZ4_COMPRESS: &'static str = "lz4_compress_failed";
7pub const ERR_LZ4_CDECOMPRESS: &'static str = "lz4_decompress_failed";
8
9#[inline]
10pub fn compress_bound(size: i32) -> i32 {
11    unsafe { LZ4_compressBound(size) }
12}
13
14#[inline]
15pub fn compress(src: &[u8], dest: &mut [u8]) -> Result<i32> {
16    let compressed_len = unsafe {
17        LZ4_compress_default(
18            src.as_ptr() as *const libc::c_char,
19            dest.as_mut_ptr() as *mut libc::c_char,
20            src.len() as i32,
21            dest.len() as i32,
22        )
23    };
24    if compressed_len <= 0 {
25        trace!(
26            "compress fails: src len: {}, dest len : {}, compressed_len: {}",
27            src.len(),
28            dest.len(),
29            compressed_len
30        );
31        Err(Error::new(ErrorKind::Other, ERR_LZ4_COMPRESS))
32    } else {
33        Ok(compressed_len)
34    }
35}
36
37#[inline]
38pub fn decompress(src: &[u8], dest: &mut [u8]) -> Result<i32> {
39    let decompressed_len = unsafe {
40        LZ4_decompress_safe(
41            src.as_ptr() as *const libc::c_char,
42            dest.as_mut_ptr() as *mut libc::c_char,
43            src.len() as i32,
44            dest.len() as i32,
45        )
46    };
47    if decompressed_len <= 0 {
48        trace!(
49            "decompress fails: src len: {}, dest len : {}, decompressed_len: {}",
50            src.len(),
51            dest.len(),
52            decompressed_len
53        );
54        Err(Error::new(ErrorKind::Other, ERR_LZ4_CDECOMPRESS))
55    } else {
56        Ok(decompressed_len)
57    }
58}
59
60#[cfg(test)]
61mod tests {
62
63    use std::time::Instant;
64    //extern crate cpuprofiler;
65    use std::{
66        fs::File,
67        io::{Read, Write},
68    };
69
70    use super::{super::*, *};
71
72    //use self::cpuprofiler::PROFILER;
73
74    #[test]
75    fn test_compress() {
76        let buf_len: usize = 16 * 1024;
77        // prepare
78        let mut buffer = Buffer::alloc(buf_len).unwrap();
79        getrandom::getrandom(&mut buffer).unwrap();
80        let bound = compress_bound(buf_len as i32) as usize;
81        println!("compress_bound={}", bound);
82
83        // compress
84        let mut compressed_buffer = Buffer::alloc(bound).unwrap();
85        let compressed_len = compress(&buffer, &mut compressed_buffer).unwrap();
86        let mut _compressed_buffer = Buffer::alloc(compressed_len as usize).unwrap();
87        _compressed_buffer.copy_from(0, &compressed_buffer);
88        println!("compressed_len={}", _compressed_buffer.len());
89
90        // decompress
91        let mut decompressed_buffer = Buffer::alloc(buf_len).unwrap();
92        decompressed_buffer.set_zero(0, decompressed_buffer.len());
93        let decompressed_len = decompress(&_compressed_buffer, &mut decompressed_buffer).unwrap();
94        println!("decompressed_len={}", decompressed_len);
95        assert_eq!(
96            &decompressed_buffer[0..decompressed_len as usize],
97            &buffer[0..]
98        );
99    }
100
101    #[test]
102    fn test_benchmark_compress() {
103        let loop_cnt: u64 = 1000000;
104        // prepare
105        let mut buffer = Buffer::alloc(16 * 1024).unwrap();
106        getrandom::getrandom(&mut buffer).unwrap();
107        let mut bound = compress_bound(16 * 1024) as usize;
108        bound = (bound + 511) / 512 * 512;
109
110        let mut compressed_len = 0;
111        //PROFILER.lock().unwrap().start("./compress.profile").unwrap();
112        let start_ts = Instant::now();
113        for _i in 0..loop_cnt {
114            let mut compressed_buffer = Buffer::alloc(bound).unwrap();
115
116            let mut _compressed_len = compress(&buffer, &mut compressed_buffer).unwrap();
117            compressed_len = _compressed_len;
118        }
119        let end_ts = Instant::now();
120        //PROFILER.lock().unwrap().stop().unwrap();
121        println!(
122            "compressed_len={}. compress speed {}(byte)/sec",
123            compressed_len,
124            ((loop_cnt * 16 * 1024) as f64) / (end_ts.duration_since(start_ts).as_secs_f64())
125        );
126    }
127
128    #[test]
129    fn test_benchmark_decompress() {
130        let loop_cnt: u64 = 1000000;
131        // prepare
132        let mut buffer = Buffer::alloc(16 * 1024).unwrap();
133        getrandom::getrandom(&mut buffer).unwrap();
134        let mut bound = compress_bound(16 * 1024) as usize;
135        println!("compress_bound={}", bound);
136
137        bound = (bound + 511) / 512 * 512;
138        let mut compressed_buffer = Buffer::alloc(bound).unwrap();
139        let compressed_len = compress(&buffer, &mut compressed_buffer).unwrap();
140
141        let mut decompressed_len = 0;
142        //PROFILER.lock().unwrap().start("./decompress.profile").unwrap();
143        let start_ts = Instant::now();
144        for _i in 0..loop_cnt {
145            let mut decompressed_buffer = Buffer::alloc(16 * 1024).unwrap();
146
147            let _decompressed_len = decompress(
148                &compressed_buffer[0..compressed_len as usize],
149                &mut decompressed_buffer,
150            )
151            .unwrap();
152            decompressed_len = _decompressed_len;
153        }
154        let end_ts = Instant::now();
155        //PROFILER.lock().unwrap().stop().unwrap();
156        println!(
157            "decompressed_len={}. decompress speed {}(byte)/sec",
158            decompressed_len,
159            ((loop_cnt * 16 * 1024) as f64) / (end_ts.duration_since(start_ts).as_secs_f64())
160        );
161    }
162
163    //#[test]
164    #[allow(dead_code)]
165    fn test_compatibility() {
166        let mut src_buffer = Buffer::alloc(40 * 1024).unwrap();
167        let mut dst_buffer = Buffer::alloc(40 * 1024).unwrap();
168        let mut src_len: usize = 0;
169        let mut dst_len: usize = 0;
170        let mut compressed_buffer = Buffer::alloc(40 * 1024).unwrap();
171        let mut decompressed_buffer = Buffer::alloc(40 * 1024).unwrap();
172        {
173            let mut file = File::open("src.lz4").unwrap();
174            loop {
175                let size = file.read(&mut src_buffer[src_len..]).unwrap();
176                if size == 0 {
177                    break;
178                }
179                src_len += size;
180            }
181            println!("src size={}", src_len);
182
183            let compressed_len = compress(&src_buffer, &mut compressed_buffer).unwrap();
184            println!("compressed len={}", compressed_len);
185
186            let mut file_res = File::create("dst.lz4.rust").unwrap();
187            file_res
188                .write_all(&mut compressed_buffer[0..compressed_len as usize])
189                .unwrap();
190        }
191        {
192            let mut file = File::open("dst.lz4").unwrap();
193            loop {
194                let size = file.read(&mut dst_buffer[dst_len..]).unwrap();
195                if size == 0 {
196                    break;
197                }
198                dst_len += size;
199            }
200            println!("dst size={}", dst_len);
201        }
202
203        let decompressed_len =
204            decompress(&dst_buffer[0..dst_len], &mut decompressed_buffer).unwrap();
205        println!("decompressed_buffer size={}", decompressed_len);
206        assert_eq!(
207            &src_buffer[0..src_len],
208            &decompressed_buffer[0..decompressed_len as usize]
209        );
210    }
211}