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
121
122
123
124
125
126
127
128
129
130
131
132
133
#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
extern crate libc;
mod ll;
mod encoder;
mod decoder;
pub mod dict;
pub use encoder::Encoder;
pub use decoder::Decoder;
use std::io;
pub fn compress(destination: &mut [u8], source: &[u8], level: i32) -> io::Result<usize> {
let code = unsafe {
ll::ZSTD_compress(destination.as_mut_ptr(),
destination.len(),
source.as_ptr(),
source.len(),
level)
};
ll::parse_code(code)
}
pub fn compress_to_vec(data: &[u8], level: i32) -> io::Result<Vec<u8>> {
let buffer_len = unsafe { ll::ZSTD_compressBound(data.len()) };
let mut buffer = Vec::with_capacity(buffer_len);
unsafe {
buffer.set_len(buffer_len);
let len = try!(compress(&mut buffer[..], data, level));
buffer.set_len(len);
}
Ok(buffer)
}
pub fn decompress(destination: &mut [u8], source: &[u8]) -> io::Result<usize> {
let code = unsafe {
ll::ZSTD_decompress(destination.as_mut_ptr(),
destination.len(),
source.as_ptr(),
source.len())
};
ll::parse_code(code)
}
pub fn decompress_to_vec(data: &[u8], capacity: usize) -> io::Result<Vec<u8>> {
let mut buffer = Vec::with_capacity(capacity);
unsafe {
buffer.set_len(capacity);
let len = try!(decompress(&mut buffer[..], data));
buffer.set_len(len);
}
Ok(buffer)
}
#[test]
fn test_cycle() {
use std::io::{Read, Write};
let text = "This is a sample text. It is not meant to be interesting or anything. Just text, \
nothing more. Don't expect too much from it.";
let buffer: Vec<u8> = Vec::new();
let mut encoder = Encoder::new(buffer, 1).unwrap();
encoder.write_all(text.as_bytes()).unwrap();
let buffer = encoder.finish().unwrap();
let mut decoder = Decoder::new(&buffer[..]).unwrap();
let mut result = String::new();
decoder.read_to_string(&mut result).unwrap();
assert_eq!(text, &result);
}
#[test]
fn test_direct() {
let text = "Pork belly art party wolf XOXO, neutra scenester ugh thundercats tattooed squid \
skateboard beard readymade kogi. VHS cardigan schlitz, meditation chartreuse kogi \
tilde church-key. Actually direct trade hammock, aesthetic VHS semiotics organic \
narwhal lo-fi heirloom flexitarian master cleanse polaroid man bun. Flannel \
helvetica mustache, bicycle rights small batch slow-carb neutra tilde \
williamsburg meh poutine humblebrag. Four dollar toast butcher actually franzen, \
gastropub mustache tofu cardigan. 90's fingerstache forage brooklyn meditation \
single-origin coffee tofu actually, ramps pabst farm-to-table art party kombucha \
artisan fanny pack. Flannel salvia ennui viral leggings selfies.";
let compressed = compress_to_vec(text.as_bytes(), 1).unwrap();
let uncompressed = decompress_to_vec(&compressed, text.len()).unwrap();
assert_eq!(text.as_bytes(), &uncompressed[..]);
}