use zlib_rs::InflateError;
pub struct Decompress(zlib_rs::Inflate);
impl Default for Decompress {
fn default() -> Self {
Self::new()
}
}
impl Decompress {
pub fn total_in(&self) -> u64 {
self.0.total_in()
}
pub fn total_out(&self) -> u64 {
self.0.total_out()
}
pub fn new() -> Self {
let config = zlib_rs::InflateConfig::default();
let header = true;
let inner = zlib_rs::Inflate::new(header, config.window_bits as u8);
Self(inner)
}
pub fn reset(&mut self) {
self.0.reset(true);
}
pub fn decompress(
&mut self,
input: &[u8],
output: &mut [u8],
flush: FlushDecompress,
) -> Result<Status, DecompressError> {
let inflate_flush = match flush {
FlushDecompress::None => zlib_rs::InflateFlush::NoFlush,
FlushDecompress::Sync => zlib_rs::InflateFlush::SyncFlush,
FlushDecompress::Finish => zlib_rs::InflateFlush::Finish,
};
let status = self.0.decompress(input, output, inflate_flush)?;
match status {
zlib_rs::Status::Ok => Ok(Status::Ok),
zlib_rs::Status::BufError => Ok(Status::BufError),
zlib_rs::Status::StreamEnd => Ok(Status::StreamEnd),
}
}
}
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum DecompressError {
#[error("stream error")]
StreamError,
#[error("Not enough memory")]
InsufficientMemory,
#[error("Invalid input data")]
DataError,
#[error("Decompressing this input requires a dictionary")]
NeedDict,
}
impl From<zlib_rs::InflateError> for DecompressError {
fn from(value: InflateError) -> Self {
match value {
InflateError::NeedDict { .. } => DecompressError::NeedDict,
InflateError::StreamError => DecompressError::StreamError,
InflateError::DataError => DecompressError::DataError,
InflateError::MemError => DecompressError::InsufficientMemory,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Status {
Ok,
BufError,
StreamEnd,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[non_exhaustive]
#[allow(clippy::unnecessary_cast)]
pub enum FlushDecompress {
None = 0,
Sync = 2,
Finish = 4,
}
pub mod inflate {
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("Could not write all bytes when decompressing content")]
WriteInflated(#[from] std::io::Error),
#[error("Could not decode zip stream, status was '{0}'")]
Inflate(#[from] super::DecompressError),
#[error("The zlib status indicated an error, status was '{0:?}'")]
Status(super::Status),
}
}
#[derive(Default)]
pub struct Inflate {
pub state: Decompress,
}
impl Inflate {
pub fn once(&mut self, input: &[u8], out: &mut [u8]) -> Result<(Status, usize, usize), inflate::Error> {
let before_in = self.state.total_in();
let before_out = self.state.total_out();
let status = self.state.decompress(input, out, FlushDecompress::None)?;
Ok((
status,
(self.state.total_in() - before_in) as usize,
(self.state.total_out() - before_out) as usize,
))
}
pub fn reset(&mut self) {
self.state.reset();
}
}
pub mod stream;