clickhouse_driver_lz4/
lib.rs1#![no_std]
2extern crate libc;
3#[cfg(test)]
4#[macro_use]
5extern crate std;
6
7use libc::{c_char, c_int, c_uint, size_t};
8
9pub type LZ4FErrorCode = size_t;
10pub const LZ4F_VERSION: c_uint = 100;
11
12extern "C" {
13 #[allow(non_snake_case)]
15 pub fn LZ4_compress_default(
16 source: *const c_char,
17 dest: *mut c_char,
18 sourceSize: c_int,
19 maxDestSize: c_int,
20 ) -> c_int;
21
22 #[allow(non_snake_case)]
24 pub fn LZ4_compress_fast(
25 source: *const c_char,
26 dest: *mut c_char,
27 sourceSize: c_int,
28 maxDestSize: c_int,
29 acceleration: c_int,
30 ) -> c_int;
31
32 #[allow(non_snake_case)]
34 pub fn LZ4_compress_HC(
35 src: *const c_char,
36 dst: *mut c_char,
37 srcSize: c_int,
38 dstCapacity: c_int,
39 compressionLevel: c_int,
40 ) -> c_int;
41
42 #[allow(non_snake_case)]
44 pub fn LZ4_decompress_safe(
45 source: *const c_char,
46 dest: *mut c_char,
47 compressedSize: c_int,
48 maxDecompressedSize: c_int,
49 ) -> c_int;
50
51 #[allow(non_snake_case)]
52 pub fn LZ4_decompress_fast(
53 source: *const c_char,
54 dest: *mut c_char,
55 originaldSize: c_int,
56 ) -> c_int;
57
58 pub fn LZ4F_getErrorName(code: size_t) -> *const c_char;
60
61 pub fn LZ4_versionNumber() -> c_int;
63
64 fn LZ4_compressBound(size: c_int) -> c_int;
66
67}
68
69const LZ4_DISTANCE_MAX: usize = 65535;
70
71#[allow(non_snake_case)]
72#[inline]
73pub const fn LZ4_CompressInplaceBufferSize(decompressed: usize) -> usize {
74 decompressed + LZ4_DISTANCE_MAX + 32
75}
76
77#[allow(non_snake_case)]
78#[inline]
79pub const fn LZ4_DecompressInplaceBufferSize(compressed: usize) -> usize {
80 compressed + (compressed >> 8) + 32
81}
82
83#[allow(non_snake_case)]
84#[inline]
85pub fn LZ4_Decompress(src: &[u8], dst: &mut [u8]) -> i32 {
86 unsafe {
87 LZ4_decompress_safe(
88 src.as_ptr() as *const c_char,
89 dst.as_mut_ptr() as *mut c_char,
90 src.len() as c_int,
91 dst.len() as c_int,
92 )
93 }
94}
95
96#[allow(non_snake_case)]
97#[inline]
98pub fn LZ4_Compress(src: &[u8], dst: &mut [u8]) -> i32 {
99 unsafe {
100 LZ4_compress_default(
101 src.as_ptr() as *const c_char,
102 dst.as_mut_ptr() as *mut c_char,
103 src.len() as c_int,
104 dst.len() as c_int,
105 )
106 }
107}
108
109#[allow(non_snake_case)]
110#[inline]
111pub fn LZ4_CompressBounds(src: usize) -> usize {
112 unsafe { LZ4_compressBound(src as c_int) as usize }
113}
114
115#[cfg(test)]
116mod test {
117 extern crate rand;
118 use self::rand::RngCore;
119 use crate::*;
120 use libc::c_int;
121
122 #[test]
123 fn test_version_number() {
124 let version = unsafe { LZ4_versionNumber() };
125 assert_eq!(version, 10902 as c_int);
126
127 assert_eq!(unsafe { LZ4_compressBound(640 * 1024) }, 657946);
129
130 assert_eq!(LZ4_CompressInplaceBufferSize(983009), 1024 * 1024);
132 assert_eq!(LZ4_DecompressInplaceBufferSize(1044464), 1024 * 1024 - 1);
133 }
134
135 #[test]
136 fn test_compression() {
137 use std::vec::Vec;
138 let mut rng = rand::thread_rng();
139
140 for sz in [600_usize, 1024, 6000, 65000, 650000].iter() {
141 let cz: usize = LZ4_CompressInplaceBufferSize(*sz);
142
143 let mut orig: Vec<u8> = Vec::with_capacity(cz);
144 unsafe {
145 orig.set_len(cz);
146 rng.fill_bytes(&mut orig[..]);
147
148 let margin = cz - *sz;
149 let bz = LZ4_compressBound(*sz as c_int);
152 let mut comp: Vec<u8> = Vec::with_capacity(bz as usize);
154
155 comp.set_len(bz as usize);
156
157 let code = LZ4_compress_default(
159 orig.as_ptr().add(margin) as *const c_char,
160 comp.as_mut_ptr() as *mut c_char,
161 (orig.len() - margin) as i32,
162 comp.len() as i32,
163 );
164
165 assert!(code >= 0);
166 assert_eq!(orig.len() - margin, *sz);
167 let compressed_sz = code as usize;
168
169 let code = LZ4_compress_default(
171 orig.as_ptr().add(margin) as *const c_char,
172 orig.as_mut_ptr() as *mut c_char,
173 (orig.len() - margin) as i32,
174 orig.len() as i32,
175 );
176
177 assert!(code >= 0);
178
179 assert_eq!(&comp[0..compressed_sz], &orig[0..compressed_sz]);
180 }
181 }
182
183 assert_eq!(1, 1);
184 }
185
186 #[test]
187 fn test_decompression() {
188 use std::vec::Vec;
189 for sz in [600_usize, 1024, 6000, 65000, 650000].iter() {
192 let mut orig: Vec<u8> = Vec::with_capacity(*sz);
193 unsafe {
194 orig.set_len(*sz);
195
196 {
197 orig[0] = 1;
199 orig[*sz / 4] = 4;
200 orig[*sz / 2] = 7;
201 orig[*sz * 2 / 3] = 10;
202 orig[*sz - 1] = 1;
203 }
204
205 let bz = LZ4_compressBound(*sz as c_int) as usize;
206
207 let mut comp: Vec<u8> = Vec::with_capacity(bz);
208 comp.set_len(bz);
209
210 let code = LZ4_compress_default(
211 orig.as_ptr() as *const c_char,
212 comp.as_mut_ptr() as *mut c_char,
213 (orig.len()) as i32,
214 (bz) as i32,
215 );
216
217 assert!(code > 0);
218 println!(
220 "orig {}; compressed {}; in buf len {}",
221 *sz,
222 code as usize,
223 comp.len()
224 );
225 let cz = code as usize;
227
228 let mut buf: Vec<u8> = Vec::with_capacity(*sz);
229 buf.set_len(*sz);
230
231 let code = LZ4_decompress_safe(
232 comp.as_ptr() as *const c_char,
233 buf.as_mut_ptr() as *mut c_char,
234 cz as i32,
235 *sz as i32,
236 );
237
238 assert!(code > 0);
239
240 let cz = code as usize;
241
242 assert_eq!(cz, *sz);
243 assert_eq!(&orig[0..*sz], &buf[0..cz]);
244 }
245 }
246 }
247}