1use zlib_rs::InflateError;
2
3pub struct Decompress(zlib_rs::Inflate);
5
6impl Default for Decompress {
7 fn default() -> Self {
8 Self::new()
9 }
10}
11
12impl Decompress {
13 pub fn total_in(&self) -> u64 {
15 self.0.total_in()
16 }
17
18 pub fn total_out(&self) -> u64 {
20 self.0.total_out()
21 }
22
23 pub fn new() -> Self {
25 let config = zlib_rs::InflateConfig::default();
26 let header = true;
27 let inner = zlib_rs::Inflate::new(header, config.window_bits as u8);
28 Self(inner)
29 }
30
31 pub fn reset(&mut self) {
33 self.0.reset(true);
34 }
35
36 pub fn decompress(
38 &mut self,
39 input: &[u8],
40 output: &mut [u8],
41 flush: FlushDecompress,
42 ) -> Result<Status, DecompressError> {
43 let inflate_flush = match flush {
44 FlushDecompress::None => zlib_rs::InflateFlush::NoFlush,
45 FlushDecompress::Sync => zlib_rs::InflateFlush::SyncFlush,
46 FlushDecompress::Finish => zlib_rs::InflateFlush::Finish,
47 };
48
49 let status = self.0.decompress(input, output, inflate_flush)?;
50 match status {
51 zlib_rs::Status::Ok => Ok(Status::Ok),
52 zlib_rs::Status::BufError => Ok(Status::BufError),
53 zlib_rs::Status::StreamEnd => Ok(Status::StreamEnd),
54 }
55 }
56}
57
58#[derive(Debug, thiserror::Error)]
60#[allow(missing_docs)]
61pub enum DecompressError {
62 #[error("stream error")]
63 StreamError,
64 #[error("Not enough memory")]
65 InsufficientMemory,
66 #[error("Invalid input data")]
67 DataError,
68 #[error("Decompressing this input requires a dictionary")]
69 NeedDict,
70}
71
72impl From<zlib_rs::InflateError> for DecompressError {
73 fn from(value: InflateError) -> Self {
74 match value {
75 InflateError::NeedDict { .. } => DecompressError::NeedDict,
76 InflateError::StreamError => DecompressError::StreamError,
77 InflateError::DataError => DecompressError::DataError,
78 InflateError::MemError => DecompressError::InsufficientMemory,
79 }
80 }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85pub enum Status {
86 Ok,
89 BufError,
91 StreamEnd,
93}
94
95#[derive(Copy, Clone, PartialEq, Eq, Debug)]
98#[non_exhaustive]
99#[allow(clippy::unnecessary_cast)]
100pub enum FlushDecompress {
101 None = 0,
105
106 Sync = 2,
114
115 Finish = 4,
120}
121
122pub mod inflate {
124 #[derive(Debug, thiserror::Error)]
126 #[allow(missing_docs)]
127 pub enum Error {
128 #[error("Could not write all bytes when decompressing content")]
129 WriteInflated(#[from] std::io::Error),
130 #[error("Could not decode zip stream, status was '{0}'")]
131 Inflate(#[from] super::DecompressError),
132 #[error("The zlib status indicated an error, status was '{0:?}'")]
133 Status(super::Status),
134 }
135}
136
137#[derive(Default)]
139pub struct Inflate {
140 pub state: Decompress,
142}
143
144impl Inflate {
145 pub fn once(&mut self, input: &[u8], out: &mut [u8]) -> Result<(Status, usize, usize), inflate::Error> {
147 let before_in = self.state.total_in();
148 let before_out = self.state.total_out();
149 let status = self.state.decompress(input, out, FlushDecompress::None)?;
150 Ok((
151 status,
152 (self.state.total_in() - before_in) as usize,
153 (self.state.total_out() - before_out) as usize,
154 ))
155 }
156
157 pub fn reset(&mut self) {
159 self.state.reset();
160 }
161}
162
163pub mod stream;