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
use crate::convert::TryTo;
use libc::c_ulong;
use libz_sys;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum DecompressionError {
#[error("Received invalid data")]
Failed,
#[error("Decompressed data is bigger than expected")]
TooBig,
#[error("Decompressed data is smaller than expected")]
TooSmall,
}
pub fn decompress(data: &[u8], expected_size: usize) -> Result<Vec<u8>, DecompressionError> {
let mut decompressed = Vec::with_capacity(expected_size);
unsafe {
let mut decompressed_len = expected_size.try_to::<c_ulong>();
match libz_sys::uncompress(decompressed.as_mut_ptr(), &mut decompressed_len, data.as_ptr(), data.len().try_to()) {
libz_sys::Z_OK => {},
libz_sys::Z_MEM_ERROR => panic!("Decompression: Out of memory"),
libz_sys::Z_BUF_ERROR => return Err(DecompressionError::TooBig),
libz_sys::Z_DATA_ERROR => return Err(DecompressionError::Failed),
e => panic!("Decompression: unexpected zlib error code {}", e),
}
if decompressed_len.try_to::<usize>() != expected_size {
return Err(DecompressionError::TooSmall);
}
decompressed.set_len(expected_size);
}
Ok(decompressed)
}
pub fn compress(data: &[u8]) -> Vec<u8> {
let mut compressed;
unsafe {
let mut max_size = libz_sys::compressBound(data.len().try_to());
compressed = Vec::with_capacity(max_size.try_to());
match libz_sys::compress(compressed.as_mut_ptr(), &mut max_size, data.as_ptr(), data.len().try_to()) {
libz_sys::Z_OK => {},
libz_sys::Z_MEM_ERROR => panic!("Compression: Out of memory"),
libz_sys::Z_BUF_ERROR => panic!("Compression: Invalid buffer size from compressBound"),
e => panic!("Compression: Unexpected zlib error code {}", e),
}
compressed.set_len(max_size.try_to());
}
compressed
}