1use core::ffi::c_uint;
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(zlib_header: bool, window_bits: u8) -> Self {
100 let config = InflateConfig {
101 window_bits: if zlib_header {
102 i32::from(window_bits)
103 } else {
104 -i32::from(window_bits)
105 },
106 };
107
108 Self {
109 inner: crate::inflate::InflateStream::new(config),
110 total_in: 0,
111 total_out: 0,
112 }
113 }
114
115 pub fn reset(&mut self, zlib_header: bool) {
117 let mut config = InflateConfig::default();
118
119 if !zlib_header {
120 config.window_bits = -config.window_bits;
121 }
122
123 self.total_in = 0;
124 self.total_out = 0;
125
126 crate::inflate::reset_with_config(&mut self.inner, config);
127 }
128
129 pub fn decompress(
131 &mut self,
132 input: &[u8],
133 output: &mut [u8],
134 flush: InflateFlush,
135 ) -> Result<Status, InflateError> {
136 self.inner.avail_in = Ord::min(input.len(), c_uint::MAX as usize) as c_uint;
140 self.inner.avail_out = Ord::min(output.len(), c_uint::MAX as usize) as c_uint;
141
142 self.inner.next_in = input.as_ptr().cast_mut();
144 self.inner.next_out = output.as_mut_ptr();
145
146 let start_in = self.inner.next_in;
147 let start_out = self.inner.next_out;
148
149 let ret = unsafe { crate::inflate::inflate(&mut self.inner, flush) };
151
152 self.total_in += (self.inner.next_in as usize - start_in as usize) as u64;
153 self.total_out += (self.inner.next_out as usize - start_out as usize) as u64;
154
155 match ret {
156 ReturnCode::Ok => Ok(Status::Ok),
157 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
158 ReturnCode::NeedDict => Err(InflateError::NeedDict {
159 dict_id: self.inner.adler as u32,
160 }),
161 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
162 ReturnCode::StreamError => Err(InflateError::StreamError),
163 ReturnCode::DataError => Err(InflateError::DataError),
164 ReturnCode::MemError => Err(InflateError::MemError),
165 ReturnCode::BufError => Ok(Status::BufError),
166 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
167 }
168 }
169
170 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, InflateError> {
171 match crate::inflate::set_dictionary(&mut self.inner, dictionary) {
172 ReturnCode::Ok => Ok(self.inner.adler as u32),
173 ReturnCode::StreamError => Err(InflateError::StreamError),
174 ReturnCode::DataError => Err(InflateError::DataError),
175 other => unreachable!("set_dictionary does not return {other:?}"),
176 }
177 }
178}
179
180impl Drop for Inflate {
181 fn drop(&mut self) {
182 let _ = crate::inflate::end(&mut self.inner);
183 }
184}
185
186#[derive(Copy, Clone, PartialEq, Eq, Debug)]
188pub enum DeflateError {
189 StreamError = -2,
192 DataError = -3,
194 MemError = -4,
196}
197
198impl From<DeflateError> for ReturnCode {
199 fn from(value: DeflateError) -> Self {
200 match value {
201 DeflateError::StreamError => ReturnCode::StreamError,
202 DeflateError::DataError => ReturnCode::DataError,
203 DeflateError::MemError => ReturnCode::MemError,
204 }
205 }
206}
207
208impl DeflateError {
209 pub fn as_str(self) -> &'static str {
210 ReturnCode::from(self).error_message_str()
211 }
212}
213
214impl From<ReturnCode> for Result<Status, DeflateError> {
215 fn from(value: ReturnCode) -> Self {
216 match value {
217 ReturnCode::Ok => Ok(Status::Ok),
218 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
219 ReturnCode::NeedDict => unreachable!("compression does not use dictionary"),
220 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
221 ReturnCode::StreamError => Err(DeflateError::StreamError),
222 ReturnCode::DataError => Err(DeflateError::DataError),
223 ReturnCode::MemError => Err(DeflateError::MemError),
224 ReturnCode::BufError => Ok(Status::BufError),
225 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
226 }
227 }
228}
229
230pub struct Deflate {
232 inner: crate::deflate::DeflateStream<'static>,
233 total_in: u64,
234 total_out: u64,
235}
236
237impl Deflate {
238 pub fn total_in(&self) -> u64 {
240 self.total_in
241 }
242
243 pub fn total_out(&self) -> u64 {
245 self.total_out
246 }
247
248 pub fn error_message(&self) -> Option<&'static str> {
250 if self.inner.msg.is_null() {
251 None
252 } else {
253 unsafe { core::ffi::CStr::from_ptr(self.inner.msg).to_str() }.ok()
254 }
255 }
256
257 pub fn new(level: i32, zlib_header: bool, window_bits: u8) -> Self {
261 let config = DeflateConfig {
262 window_bits: if zlib_header {
263 i32::from(window_bits)
264 } else {
265 -i32::from(window_bits)
266 },
267 level,
268 ..DeflateConfig::default()
269 };
270
271 Self {
272 inner: crate::deflate::DeflateStream::new(config),
273 total_in: 0,
274 total_out: 0,
275 }
276 }
277
278 pub fn reset(&mut self) {
280 self.total_in = 0;
281 self.total_out = 0;
282
283 crate::deflate::reset(&mut self.inner);
284 }
285
286 pub fn compress(
288 &mut self,
289 input: &[u8],
290 output: &mut [u8],
291 flush: DeflateFlush,
292 ) -> Result<Status, DeflateError> {
293 self.inner.avail_in = Ord::min(input.len(), c_uint::MAX as usize) as c_uint;
297 self.inner.avail_out = Ord::min(output.len(), c_uint::MAX as usize) as c_uint;
298
299 self.inner.next_in = input.as_ptr().cast_mut();
301 self.inner.next_out = output.as_mut_ptr();
302
303 let start_in = self.inner.next_in;
304 let start_out = self.inner.next_out;
305
306 let ret = crate::deflate::deflate(&mut self.inner, flush).into();
307
308 self.total_in += (self.inner.next_in as usize - start_in as usize) as u64;
309 self.total_out += (self.inner.next_out as usize - start_out as usize) as u64;
310
311 ret
312 }
313
314 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, DeflateError> {
318 match crate::deflate::set_dictionary(&mut self.inner, dictionary) {
319 ReturnCode::Ok => Ok(self.inner.adler as u32),
320 ReturnCode::StreamError => Err(DeflateError::StreamError),
321 other => unreachable!("set_dictionary does not return {other:?}"),
322 }
323 }
324
325 pub fn set_level(&mut self, level: i32) -> Result<Status, DeflateError> {
336 match crate::deflate::params(&mut self.inner, level, Default::default()) {
337 ReturnCode::Ok => Ok(Status::Ok),
338 ReturnCode::StreamError => Err(DeflateError::StreamError),
339 ReturnCode::BufError => Ok(Status::BufError),
340 other => unreachable!("set_level does not return {other:?}"),
341 }
342 }
343}
344
345impl Drop for Deflate {
346 fn drop(&mut self) {
347 let _ = crate::deflate::end(&mut self.inner);
348 }
349}