use zlib_rs::InflateError;
use crate::{Decompress, FlushDecompress, Status};
#[derive(Debug, thiserror::Error)]
#[expect(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 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 error_message(&self) -> Option<&'static str> {
self.0.error_message()
}
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),
}
}
}
impl From<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,
}
}
}