use crate::map_error_code;
#[cfg(feature = "experimental")]
use std::convert::TryInto;
use std::io;
use zstd_safe;
#[derive(Default)]
pub struct Decompressor<'a> {
context: zstd_safe::DCtx<'a>,
}
impl Decompressor<'static> {
pub fn new() -> io::Result<Self> {
Self::with_dictionary(&[])
}
pub fn with_dictionary(dictionary: &[u8]) -> io::Result<Self> {
let mut decompressor = Self::default();
decompressor.set_dictionary(dictionary)?;
Ok(decompressor)
}
}
impl<'a> Decompressor<'a> {
pub fn with_prepared_dictionary<'b>(
dictionary: &'a crate::dict::DecoderDictionary<'b>,
) -> io::Result<Self>
where
'b: 'a,
{
let mut decompressor = Self::default();
decompressor.set_prepared_dictionary(dictionary)?;
Ok(decompressor)
}
pub fn set_dictionary(&mut self, dictionary: &[u8]) -> io::Result<()> {
self.context
.load_dictionary(dictionary)
.map_err(map_error_code)?;
Ok(())
}
pub fn set_prepared_dictionary<'b>(
&mut self,
dictionary: &'a crate::dict::DecoderDictionary<'b>,
) -> io::Result<()>
where
'b: 'a,
{
self.context
.ref_ddict(dictionary.as_ddict())
.map_err(map_error_code)?;
Ok(())
}
pub fn decompress_to_buffer<C: zstd_safe::WriteBuf + ?Sized>(
&mut self,
source: &[u8],
destination: &mut C,
) -> io::Result<usize> {
self.context
.decompress(destination, source)
.map_err(map_error_code)
}
pub fn decompress(
&mut self,
data: &[u8],
capacity: usize,
) -> io::Result<Vec<u8>> {
let capacity =
Self::upper_bound(data).unwrap_or(capacity).min(capacity);
let mut buffer = Vec::with_capacity(capacity);
self.decompress_to_buffer(data, &mut buffer)?;
Ok(buffer)
}
pub fn set_parameter(
&mut self,
parameter: zstd_safe::DParameter,
) -> io::Result<()> {
self.context
.set_parameter(parameter)
.map_err(map_error_code)?;
Ok(())
}
crate::decoder_parameters!();
pub fn upper_bound(_data: &[u8]) -> Option<usize> {
#[cfg(feature = "experimental")]
{
let bound = zstd_safe::decompress_bound(_data).ok()?;
bound.try_into().ok()
}
#[cfg(not(feature = "experimental"))]
{
None
}
}
}
fn _assert_traits() {
fn _assert_send<T: Send>(_: T) {}
_assert_send(Decompressor::new());
}