use ps_buffer::Buffer;
use crate::error::DecompressionError;
use crate::zstd;
fn required_out_size(data: &[u8]) -> Result<usize, DecompressionError> {
zstd::frame_content_size(data).ok_or(DecompressionError::BadData)
}
fn required_out_size_bounded(
data: &[u8],
max_output_bytes: usize,
) -> Result<usize, DecompressionError> {
let out_size = required_out_size(data)?;
if out_size > max_output_bytes {
return Err(DecompressionError::TooLarge {
size: out_size,
max: max_output_bytes,
});
}
Ok(out_size)
}
pub fn decompress_into(data: &[u8], out_data: &mut [u8]) -> Result<usize, DecompressionError> {
let expected_size = required_out_size(data)?;
if expected_size > out_data.len() {
return Err(DecompressionError::InsufficientSpace);
}
let size = match zstd::decompress(data, out_data) {
Ok(size) => size,
Err(code) => {
return if zstd::is_dst_too_small(code) {
Err(DecompressionError::InsufficientSpace)
} else {
Err(DecompressionError::BadData)
};
}
};
Ok(size)
}
pub fn decompress(data: &[u8]) -> Result<Buffer, DecompressionError> {
let out_size = required_out_size(data)?;
let mut out_data = Buffer::alloc_uninit(out_size)?;
let size = decompress_into(data, &mut out_data)?;
if size < out_size {
out_data.truncate(size);
}
Ok(out_data)
}
pub fn decompress_bounded(
data: &[u8],
max_output_bytes: usize,
) -> Result<Buffer, DecompressionError> {
let out_size = required_out_size_bounded(data, max_output_bytes)?;
let mut out_data = Buffer::alloc_uninit(out_size)?;
let size = decompress_into(data, &mut out_data)?;
if size < out_size {
out_data.truncate(size);
}
Ok(out_data)
}