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