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 inner = zlib_rs::Inflate::new(true, zlib_rs::MAX_WBITS as u8);
26 Self(inner)
27 }
28
29 pub fn reset(&mut self) {
31 self.0.reset(true);
32 }
33
34 pub fn decompress(
36 &mut self,
37 input: &[u8],
38 output: &mut [u8],
39 flush: FlushDecompress,
40 ) -> Result<Status, DecompressError> {
41 let inflate_flush = match flush {
42 FlushDecompress::None => zlib_rs::InflateFlush::NoFlush,
43 FlushDecompress::Sync => zlib_rs::InflateFlush::SyncFlush,
44 FlushDecompress::Finish => zlib_rs::InflateFlush::Finish,
45 };
46
47 let status = self.0.decompress(input, output, inflate_flush)?;
48 match status {
49 zlib_rs::Status::Ok => Ok(Status::Ok),
50 zlib_rs::Status::BufError => Ok(Status::BufError),
51 zlib_rs::Status::StreamEnd => Ok(Status::StreamEnd),
52 }
53 }
54}
55
56#[derive(Debug, thiserror::Error)]
58#[allow(missing_docs)]
59pub enum DecompressError {
60 #[error("stream error")]
61 StreamError,
62 #[error("Not enough memory")]
63 InsufficientMemory,
64 #[error("Invalid input data")]
65 DataError,
66 #[error("Decompressing this input requires a dictionary")]
67 NeedDict,
68}
69
70impl From<zlib_rs::InflateError> for DecompressError {
71 fn from(value: InflateError) -> Self {
72 match value {
73 InflateError::NeedDict { .. } => DecompressError::NeedDict,
74 InflateError::StreamError => DecompressError::StreamError,
75 InflateError::DataError => DecompressError::DataError,
76 InflateError::MemError => DecompressError::InsufficientMemory,
77 }
78 }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq)]
83pub enum Status {
84 Ok,
87 BufError,
89 StreamEnd,
91}
92
93#[derive(Copy, Clone, PartialEq, Eq, Debug)]
96#[non_exhaustive]
97#[allow(clippy::unnecessary_cast)]
98pub enum FlushDecompress {
99 None = 0,
103
104 Sync = 2,
112
113 Finish = 4,
118}
119
120pub mod inflate {
122 #[derive(Debug, thiserror::Error)]
124 #[allow(missing_docs)]
125 pub enum Error {
126 #[error("Could not write all bytes when decompressing content")]
127 WriteInflated(#[from] std::io::Error),
128 #[error("Could not decode zip stream, status was '{0}'")]
129 Inflate(#[from] super::DecompressError),
130 #[error("The zlib status indicated an error, status was '{0:?}'")]
131 Status(super::Status),
132 }
133}
134
135#[derive(Default)]
137pub struct Inflate {
138 pub state: Decompress,
140}
141
142impl Inflate {
143 pub fn once(&mut self, input: &[u8], out: &mut [u8]) -> Result<(Status, usize, usize), inflate::Error> {
145 let before_in = self.state.total_in();
146 let before_out = self.state.total_out();
147 let status = self.state.decompress(input, out, FlushDecompress::None)?;
148 Ok((
149 status,
150 (self.state.total_in() - before_in) as usize,
151 (self.state.total_out() - before_out) as usize,
152 ))
153 }
154
155 pub fn reset(&mut self) {
157 self.state.reset();
158 }
159}
160
161pub mod stream;