1use crate::deflate::DeflateConfig;
2use crate::inflate::InflateConfig;
3use crate::ReturnCode;
4pub use crate::{DeflateFlush, InflateFlush};
5
6#[derive(Copy, Clone, PartialEq, Eq, Debug)]
9pub enum Status {
10 Ok,
15
16 BufError,
26
27 StreamEnd,
33}
34
35#[derive(Copy, Clone, PartialEq, Eq, Debug)]
37#[repr(i32)]
38pub enum InflateError {
39 NeedDict { dict_id: u32 } = 2,
41 StreamError = -2,
44 DataError = -3,
46 MemError = -4,
48}
49
50impl From<InflateError> for ReturnCode {
51 fn from(value: InflateError) -> Self {
52 match value {
53 InflateError::NeedDict { .. } => ReturnCode::NeedDict,
54 InflateError::StreamError => ReturnCode::StreamError,
55 InflateError::DataError => ReturnCode::DataError,
56 InflateError::MemError => ReturnCode::MemError,
57 }
58 }
59}
60
61impl InflateError {
62 pub fn as_str(self) -> &'static str {
63 ReturnCode::from(self).error_message_str()
64 }
65}
66
67pub struct Inflate(crate::inflate::InflateStream<'static>);
69
70impl Inflate {
71 pub fn total_in(&self) -> u64 {
73 #[allow(clippy::useless_conversion)]
74 u64::from(self.0.total_in)
75 }
76
77 pub fn total_out(&self) -> u64 {
79 #[allow(clippy::useless_conversion)]
80 u64::from(self.0.total_out)
81 }
82
83 pub fn error_message(&self) -> Option<&'static str> {
85 if self.0.msg.is_null() {
86 None
87 } else {
88 unsafe { core::ffi::CStr::from_ptr(self.0.msg).to_str() }.ok()
89 }
90 }
91
92 pub fn new(zlib_header: bool, window_bits: u8) -> Self {
96 let config = InflateConfig {
97 window_bits: if zlib_header {
98 i32::from(window_bits)
99 } else {
100 -i32::from(window_bits)
101 },
102 };
103
104 Self(crate::inflate::InflateStream::new(config))
105 }
106
107 pub fn reset(&mut self, zlib_header: bool) {
109 let mut config = InflateConfig::default();
110
111 if !zlib_header {
112 config.window_bits = -config.window_bits;
113 }
114
115 crate::inflate::reset_with_config(&mut self.0, config);
116 }
117
118 pub fn decompress(
120 &mut self,
121 input: &[u8],
122 output: &mut [u8],
123 flush: InflateFlush,
124 ) -> Result<Status, InflateError> {
125 self.0.avail_in = input.len() as _;
126 self.0.avail_out = output.len() as _;
127
128 self.0.next_in = input.as_ptr().cast_mut();
130 self.0.next_out = output.as_mut_ptr();
131
132 match unsafe { crate::inflate::inflate(&mut self.0, flush) } {
134 ReturnCode::Ok => Ok(Status::Ok),
135 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
136 ReturnCode::NeedDict => Err(InflateError::NeedDict {
137 dict_id: self.0.adler as u32,
138 }),
139 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
140 ReturnCode::StreamError => Err(InflateError::StreamError),
141 ReturnCode::DataError => Err(InflateError::DataError),
142 ReturnCode::MemError => Err(InflateError::MemError),
143 ReturnCode::BufError => Ok(Status::BufError),
144 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
145 }
146 }
147
148 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, InflateError> {
149 match crate::inflate::set_dictionary(&mut self.0, dictionary) {
150 ReturnCode::Ok => Ok(self.0.adler as u32),
151 ReturnCode::StreamError => Err(InflateError::StreamError),
152 ReturnCode::DataError => Err(InflateError::DataError),
153 other => unreachable!("set_dictionary does not return {other:?}"),
154 }
155 }
156}
157
158impl Drop for Inflate {
159 fn drop(&mut self) {
160 let _ = crate::inflate::end(&mut self.0);
161 }
162}
163
164#[derive(Copy, Clone, PartialEq, Eq, Debug)]
166pub enum DeflateError {
167 StreamError = -2,
170 DataError = -3,
172 MemError = -4,
174}
175
176impl From<DeflateError> for ReturnCode {
177 fn from(value: DeflateError) -> Self {
178 match value {
179 DeflateError::StreamError => ReturnCode::StreamError,
180 DeflateError::DataError => ReturnCode::DataError,
181 DeflateError::MemError => ReturnCode::MemError,
182 }
183 }
184}
185
186impl DeflateError {
187 pub fn as_str(self) -> &'static str {
188 ReturnCode::from(self).error_message_str()
189 }
190}
191
192impl From<ReturnCode> for Result<Status, DeflateError> {
193 fn from(value: ReturnCode) -> Self {
194 match value {
195 ReturnCode::Ok => Ok(Status::Ok),
196 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
197 ReturnCode::NeedDict => unreachable!("compression does not use dictionary"),
198 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
199 ReturnCode::StreamError => Err(DeflateError::StreamError),
200 ReturnCode::DataError => Err(DeflateError::DataError),
201 ReturnCode::MemError => Err(DeflateError::MemError),
202 ReturnCode::BufError => Ok(Status::BufError),
203 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
204 }
205 }
206}
207
208pub struct Deflate(crate::deflate::DeflateStream<'static>);
210
211impl Deflate {
212 pub fn total_in(&self) -> u64 {
214 #[allow(clippy::useless_conversion)]
215 u64::from(self.0.total_in)
216 }
217
218 pub fn total_out(&self) -> u64 {
220 #[allow(clippy::useless_conversion)]
221 u64::from(self.0.total_out)
222 }
223
224 pub fn error_message(&self) -> Option<&'static str> {
226 if self.0.msg.is_null() {
227 None
228 } else {
229 unsafe { core::ffi::CStr::from_ptr(self.0.msg).to_str() }.ok()
230 }
231 }
232
233 pub fn new(level: i32, zlib_header: bool, window_bits: u8) -> Self {
237 let config = DeflateConfig {
238 window_bits: if zlib_header {
239 i32::from(window_bits)
240 } else {
241 -i32::from(window_bits)
242 },
243 level,
244 ..DeflateConfig::default()
245 };
246
247 Self(crate::deflate::DeflateStream::new(config))
248 }
249
250 pub fn reset(&mut self) {
252 crate::deflate::reset(&mut self.0);
253 }
254
255 pub fn compress(
257 &mut self,
258 input: &[u8],
259 output: &mut [u8],
260 flush: DeflateFlush,
261 ) -> Result<Status, DeflateError> {
262 self.0.avail_in = input.len() as _;
263 self.0.avail_out = output.len() as _;
264
265 self.0.next_in = input.as_ptr().cast_mut();
267 self.0.next_out = output.as_mut_ptr();
268
269 crate::deflate::deflate(&mut self.0, flush).into()
270 }
271
272 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, DeflateError> {
276 match crate::deflate::set_dictionary(&mut self.0, dictionary) {
277 ReturnCode::Ok => Ok(self.0.adler as u32),
278 ReturnCode::StreamError => Err(DeflateError::StreamError),
279 other => unreachable!("set_dictionary does not return {other:?}"),
280 }
281 }
282
283 pub fn set_level(&mut self, level: i32) -> Result<Status, DeflateError> {
294 match crate::deflate::params(&mut self.0, level, Default::default()) {
295 ReturnCode::Ok => Ok(Status::Ok),
296 ReturnCode::StreamError => Err(DeflateError::StreamError),
297 ReturnCode::BufError => Ok(Status::BufError),
298 other => unreachable!("set_level does not return {other:?}"),
299 }
300 }
301}
302
303impl Drop for Deflate {
304 fn drop(&mut self) {
305 let _ = crate::deflate::end(&mut self.0);
306 }
307}