1use core::{ffi::c_uint, mem::MaybeUninit};
2
3use crate::deflate::DeflateConfig;
4use crate::inflate::InflateConfig;
5use crate::ReturnCode;
6pub use crate::{DeflateFlush, InflateFlush};
7
8#[derive(Copy, Clone, PartialEq, Eq, Debug)]
11pub enum Status {
12 Ok,
17
18 BufError,
28
29 StreamEnd,
35}
36
37#[derive(Copy, Clone, PartialEq, Eq, Debug)]
39#[repr(i32)]
40pub enum InflateError {
41 NeedDict { dict_id: u32 } = 2,
43 StreamError = -2,
46 DataError = -3,
48 MemError = -4,
50}
51
52impl From<InflateError> for ReturnCode {
53 fn from(value: InflateError) -> Self {
54 match value {
55 InflateError::NeedDict { .. } => ReturnCode::NeedDict,
56 InflateError::StreamError => ReturnCode::StreamError,
57 InflateError::DataError => ReturnCode::DataError,
58 InflateError::MemError => ReturnCode::MemError,
59 }
60 }
61}
62
63impl InflateError {
64 pub fn as_str(self) -> &'static str {
65 ReturnCode::from(self).error_message_str()
66 }
67}
68
69pub struct Inflate {
71 inner: crate::inflate::InflateStream<'static>,
72 total_in: u64,
73 total_out: u64,
74}
75
76impl Inflate {
77 pub fn total_in(&self) -> u64 {
79 self.total_in
80 }
81
82 pub fn total_out(&self) -> u64 {
84 self.total_out
85 }
86
87 pub fn error_message(&self) -> Option<&'static str> {
89 if self.inner.msg.is_null() {
90 None
91 } else {
92 unsafe { core::ffi::CStr::from_ptr(self.inner.msg).to_str() }.ok()
93 }
94 }
95
96 pub fn new(expect_header: bool, window_bits: u8) -> Self {
121 let config = InflateConfig {
122 window_bits: if expect_header {
123 i32::from(window_bits)
124 } else {
125 -i32::from(window_bits)
126 },
127 };
128
129 Self {
130 inner: crate::inflate::InflateStream::new(config),
131 total_in: 0,
132 total_out: 0,
133 }
134 }
135
136 pub fn reset(&mut self, zlib_header: bool) {
138 let mut config = InflateConfig::default();
139
140 if !zlib_header {
141 config.window_bits = -config.window_bits;
142 }
143
144 self.total_in = 0;
145 self.total_out = 0;
146
147 crate::inflate::reset_with_config(&mut self.inner, config);
148 }
149
150 pub fn decompress(
153 &mut self,
154 input: &[u8],
155 output: &mut [u8],
156 flush: InflateFlush,
157 ) -> Result<Status, InflateError> {
158 self.decompress_uninit(
159 input,
160 unsafe { &mut *(output as *mut _ as *mut [MaybeUninit<u8>]) },
161 flush,
162 )
163 }
164
165 pub fn decompress_uninit(
168 &mut self,
169 input: &[u8],
170 output: &mut [MaybeUninit<u8>],
171 flush: InflateFlush,
172 ) -> Result<Status, InflateError> {
173 self.inner.avail_in = Ord::min(input.len(), c_uint::MAX as usize) as c_uint;
177 self.inner.avail_out = Ord::min(output.len(), c_uint::MAX as usize) as c_uint;
178
179 self.inner.next_in = input.as_ptr().cast_mut();
181 self.inner.next_out = output.as_mut_ptr().cast();
182
183 let start_in = self.inner.next_in;
184 let start_out = self.inner.next_out;
185
186 let ret = unsafe { crate::inflate::inflate(&mut self.inner, flush) };
188
189 self.total_in += (self.inner.next_in as usize - start_in as usize) as u64;
190 self.total_out += (self.inner.next_out as usize - start_out as usize) as u64;
191
192 match ret {
193 ReturnCode::Ok => Ok(Status::Ok),
194 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
195 ReturnCode::NeedDict => Err(InflateError::NeedDict {
196 dict_id: self.inner.adler as u32,
197 }),
198 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
199 ReturnCode::StreamError => Err(InflateError::StreamError),
200 ReturnCode::DataError => Err(InflateError::DataError),
201 ReturnCode::MemError => Err(InflateError::MemError),
202 ReturnCode::BufError => Ok(Status::BufError),
203 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
204 }
205 }
206
207 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, InflateError> {
208 match crate::inflate::set_dictionary(&mut self.inner, dictionary) {
209 ReturnCode::Ok => Ok(self.inner.adler as u32),
210 ReturnCode::StreamError => Err(InflateError::StreamError),
211 ReturnCode::DataError => Err(InflateError::DataError),
212 other => unreachable!("set_dictionary does not return {other:?}"),
213 }
214 }
215}
216
217impl Drop for Inflate {
218 fn drop(&mut self) {
219 let _ = crate::inflate::end(&mut self.inner);
220 }
221}
222
223#[derive(Copy, Clone, PartialEq, Eq, Debug)]
225pub enum DeflateError {
226 StreamError = -2,
229 DataError = -3,
231 MemError = -4,
233}
234
235impl From<DeflateError> for ReturnCode {
236 fn from(value: DeflateError) -> Self {
237 match value {
238 DeflateError::StreamError => ReturnCode::StreamError,
239 DeflateError::DataError => ReturnCode::DataError,
240 DeflateError::MemError => ReturnCode::MemError,
241 }
242 }
243}
244
245impl DeflateError {
246 pub fn as_str(self) -> &'static str {
247 ReturnCode::from(self).error_message_str()
248 }
249}
250
251impl From<ReturnCode> for Result<Status, DeflateError> {
252 fn from(value: ReturnCode) -> Self {
253 match value {
254 ReturnCode::Ok => Ok(Status::Ok),
255 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
256 ReturnCode::NeedDict => unreachable!("compression does not use dictionary"),
257 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
258 ReturnCode::StreamError => Err(DeflateError::StreamError),
259 ReturnCode::DataError => Err(DeflateError::DataError),
260 ReturnCode::MemError => Err(DeflateError::MemError),
261 ReturnCode::BufError => Ok(Status::BufError),
262 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
263 }
264 }
265}
266
267pub struct Deflate {
269 inner: crate::deflate::DeflateStream<'static>,
270 total_in: u64,
271 total_out: u64,
272}
273
274impl Deflate {
275 pub fn total_in(&self) -> u64 {
277 self.total_in
278 }
279
280 pub fn total_out(&self) -> u64 {
282 self.total_out
283 }
284
285 pub fn error_message(&self) -> Option<&'static str> {
287 if self.inner.msg.is_null() {
288 None
289 } else {
290 unsafe { core::ffi::CStr::from_ptr(self.inner.msg).to_str() }.ok()
291 }
292 }
293
294 pub fn new(level: i32, zlib_header: bool, window_bits: u8) -> Self {
298 let config = DeflateConfig {
299 window_bits: if zlib_header {
300 i32::from(window_bits)
301 } else {
302 -i32::from(window_bits)
303 },
304 level,
305 ..DeflateConfig::default()
306 };
307
308 Self {
309 inner: crate::deflate::DeflateStream::new(config),
310 total_in: 0,
311 total_out: 0,
312 }
313 }
314
315 pub fn reset(&mut self) {
317 self.total_in = 0;
318 self.total_out = 0;
319
320 crate::deflate::reset(&mut self.inner);
321 }
322
323 pub fn compress(
326 &mut self,
327 input: &[u8],
328 output: &mut [u8],
329 flush: DeflateFlush,
330 ) -> Result<Status, DeflateError> {
331 self.compress_uninit(
332 input,
333 unsafe { &mut *(output as *mut _ as *mut [MaybeUninit<u8>]) },
334 flush,
335 )
336 }
337
338 pub fn compress_uninit(
341 &mut self,
342 input: &[u8],
343 output: &mut [MaybeUninit<u8>],
344 flush: DeflateFlush,
345 ) -> Result<Status, DeflateError> {
346 self.inner.avail_in = Ord::min(input.len(), c_uint::MAX as usize) as c_uint;
350 self.inner.avail_out = Ord::min(output.len(), c_uint::MAX as usize) as c_uint;
351
352 self.inner.next_in = input.as_ptr().cast_mut();
354 self.inner.next_out = output.as_mut_ptr().cast();
355
356 let start_in = self.inner.next_in;
357 let start_out = self.inner.next_out;
358
359 let ret = crate::deflate::deflate(&mut self.inner, flush).into();
360
361 self.total_in += (self.inner.next_in as usize - start_in as usize) as u64;
362 self.total_out += (self.inner.next_out as usize - start_out as usize) as u64;
363
364 ret
365 }
366
367 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, DeflateError> {
371 match crate::deflate::set_dictionary(&mut self.inner, dictionary) {
372 ReturnCode::Ok => Ok(self.inner.adler as u32),
373 ReturnCode::StreamError => Err(DeflateError::StreamError),
374 other => unreachable!("set_dictionary does not return {other:?}"),
375 }
376 }
377
378 pub fn set_level(&mut self, level: i32) -> Result<Status, DeflateError> {
389 match crate::deflate::params(&mut self.inner, level, Default::default()) {
390 ReturnCode::Ok => Ok(Status::Ok),
391 ReturnCode::StreamError => Err(DeflateError::StreamError),
392 ReturnCode::BufError => Ok(Status::BufError),
393 other => unreachable!("set_level does not return {other:?}"),
394 }
395 }
396}
397
398impl Drop for Deflate {
399 fn drop(&mut self) {
400 let _ = crate::deflate::end(&mut self.inner);
401 }
402}