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
use crate::map_error_code;
use std::io;
use zstd_safe;
/// Allows to compress independently multiple blocks of data.
///
/// This reduces memory usage compared to calling `compress` multiple times.
/// The compressed blocks are still completely independent.
#[derive(Default)]
pub struct Compressor {
context: zstd_safe::CCtx<'static>,
dict: Vec<u8>,
}
impl Compressor {
/// Creates a new zstd compressor
pub fn new() -> Self {
Compressor::with_dict(Vec::new())
}
/// Creates a new zstd compressor, using the given dictionary.
pub fn with_dict(dict: Vec<u8>) -> Self {
Compressor {
context: zstd_safe::create_cctx(),
dict,
}
}
/// Compress a single block of data to the given destination buffer.
///
/// Returns the number of bytes written, or an error if something happened
/// (for instance if the destination buffer was too small).
///
/// A level of `0` uses zstd's default (currently `3`).
pub fn compress_to_buffer(
&mut self,
source: &[u8],
destination: &mut [u8],
level: i32,
) -> io::Result<usize> {
zstd_safe::compress_using_dict(
&mut self.context,
destination,
source,
&self.dict[..],
level,
)
.map_err(map_error_code)
}
/// Compresses a block of data and returns the compressed result.
///
/// A level of `0` uses zstd's default (currently `3`).
pub fn compress(
&mut self,
data: &[u8],
level: i32,
) -> io::Result<Vec<u8>> {
// We allocate a big buffer, slightly larger than the input data.
let buffer_len = zstd_safe::compress_bound(data.len());
let mut buffer = Vec::with_capacity(buffer_len);
unsafe {
// Use all capacity.
// Memory may not be initialized, but we won't read it.
buffer.set_len(buffer_len);
let len = self.compress_to_buffer(data, &mut buffer[..], level)?;
buffer.set_len(len);
}
// Should we shrink the vec? Meh, let the user do it if he wants.
Ok(buffer)
}
}
fn _assert_traits() {
fn _assert_send<T: Send>(_: T) {}
_assert_send(Compressor::new());
}