use super::CompressionProvider;
use std::io::Read;
fn bounded_read(reader: &mut impl Read, capacity: usize) -> crate::Result<Vec<u8>> {
let mut output = vec![0u8; capacity];
let mut filled = 0;
loop {
let dest = output
.get_mut(filled..)
.ok_or(crate::Error::DecompressedSizeTooLarge {
declared: filled as u64,
limit: capacity as u64,
})?;
match reader.read(dest) {
Ok(0) => break,
Ok(n) => filled += n,
Err(e) => return Err(crate::Error::Io(e)),
}
}
let mut probe = [0u8; 1];
match reader.read(&mut probe) {
Ok(0) => {}
Ok(_) => {
return Err(crate::Error::DecompressedSizeTooLarge {
declared: (filled + 1) as u64,
limit: capacity as u64,
});
}
Err(e) => return Err(crate::Error::Io(e)),
}
output.truncate(filled);
Ok(output)
}
pub struct ZstdPureProvider;
impl CompressionProvider for ZstdPureProvider {
fn compress(data: &[u8], _level: i32) -> crate::Result<Vec<u8>> {
let compressed = structured_zstd::encoding::compress_to_vec(
std::io::Cursor::new(data),
structured_zstd::encoding::CompressionLevel::Fastest,
);
Ok(compressed)
}
fn decompress(data: &[u8], capacity: usize) -> crate::Result<Vec<u8>> {
let mut decoder = structured_zstd::decoding::StreamingDecoder::new(data)
.map_err(|e| crate::Error::Io(std::io::Error::other(e)))?;
bounded_read(&mut decoder, capacity)
}
fn compress_with_dict(_data: &[u8], _level: i32, _dict_raw: &[u8]) -> crate::Result<Vec<u8>> {
Err(crate::Error::Io(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"zstd dictionary compression is not yet supported by the pure Rust backend \
(structured-zstd); use the `zstd` feature for dictionary compression",
)))
}
fn decompress_with_dict(
data: &[u8],
dict_raw: &[u8],
capacity: usize,
) -> crate::Result<Vec<u8>> {
let dict = structured_zstd::decoding::Dictionary::decode_dict(dict_raw)
.map_err(|e| crate::Error::Io(std::io::Error::other(e)))?;
let mut decoder = structured_zstd::decoding::FrameDecoder::new();
decoder
.add_dict(dict)
.map_err(|e| crate::Error::Io(std::io::Error::other(e)))?;
decoder
.init(data)
.map_err(|e| crate::Error::Io(std::io::Error::other(e)))?;
bounded_read(&mut decoder, capacity)
}
}