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(crate::inflate::InflateStream<'static>);
71
72impl Inflate {
73 pub fn total_in(&self) -> u64 {
75 #[allow(clippy::useless_conversion)]
76 u64::from(self.0.total_in)
77 }
78
79 pub fn total_out(&self) -> u64 {
81 #[allow(clippy::useless_conversion)]
82 u64::from(self.0.total_out)
83 }
84
85 pub fn error_message(&self) -> Option<&'static str> {
87 if self.0.msg.is_null() {
88 None
89 } else {
90 unsafe { core::ffi::CStr::from_ptr(self.0.msg).to_str() }.ok()
91 }
92 }
93
94 pub fn new(zlib_header: bool, window_bits: u8) -> Self {
98 let config = InflateConfig {
99 window_bits: if zlib_header {
100 i32::from(window_bits)
101 } else {
102 -i32::from(window_bits)
103 },
104 };
105
106 Self(crate::inflate::InflateStream::new(config))
107 }
108
109 pub fn reset(&mut self, zlib_header: bool) {
111 let mut config = InflateConfig::default();
112
113 if !zlib_header {
114 config.window_bits = -config.window_bits;
115 }
116
117 crate::inflate::reset_with_config(&mut self.0, config);
118 }
119
120 pub fn decompress(
122 &mut self,
123 input: &[u8],
124 output: &mut [u8],
125 flush: InflateFlush,
126 ) -> Result<Status, InflateError> {
127 self.0.avail_in = Ord::min(input.len(), c_uint::MAX as usize) as c_uint;
131 self.0.avail_out = Ord::min(output.len(), c_uint::MAX as usize) as c_uint;
132
133 self.0.next_in = input.as_ptr().cast_mut();
135 self.0.next_out = output.as_mut_ptr();
136
137 match unsafe { crate::inflate::inflate(&mut self.0, flush) } {
139 ReturnCode::Ok => Ok(Status::Ok),
140 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
141 ReturnCode::NeedDict => Err(InflateError::NeedDict {
142 dict_id: self.0.adler as u32,
143 }),
144 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
145 ReturnCode::StreamError => Err(InflateError::StreamError),
146 ReturnCode::DataError => Err(InflateError::DataError),
147 ReturnCode::MemError => Err(InflateError::MemError),
148 ReturnCode::BufError => Ok(Status::BufError),
149 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
150 }
151 }
152
153 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, InflateError> {
154 match crate::inflate::set_dictionary(&mut self.0, dictionary) {
155 ReturnCode::Ok => Ok(self.0.adler as u32),
156 ReturnCode::StreamError => Err(InflateError::StreamError),
157 ReturnCode::DataError => Err(InflateError::DataError),
158 other => unreachable!("set_dictionary does not return {other:?}"),
159 }
160 }
161}
162
163impl Drop for Inflate {
164 fn drop(&mut self) {
165 let _ = crate::inflate::end(&mut self.0);
166 }
167}
168
169#[derive(Copy, Clone, PartialEq, Eq, Debug)]
171pub enum DeflateError {
172 StreamError = -2,
175 DataError = -3,
177 MemError = -4,
179}
180
181impl From<DeflateError> for ReturnCode {
182 fn from(value: DeflateError) -> Self {
183 match value {
184 DeflateError::StreamError => ReturnCode::StreamError,
185 DeflateError::DataError => ReturnCode::DataError,
186 DeflateError::MemError => ReturnCode::MemError,
187 }
188 }
189}
190
191impl DeflateError {
192 pub fn as_str(self) -> &'static str {
193 ReturnCode::from(self).error_message_str()
194 }
195}
196
197impl From<ReturnCode> for Result<Status, DeflateError> {
198 fn from(value: ReturnCode) -> Self {
199 match value {
200 ReturnCode::Ok => Ok(Status::Ok),
201 ReturnCode::StreamEnd => Ok(Status::StreamEnd),
202 ReturnCode::NeedDict => unreachable!("compression does not use dictionary"),
203 ReturnCode::ErrNo => unreachable!("the rust API does not use files"),
204 ReturnCode::StreamError => Err(DeflateError::StreamError),
205 ReturnCode::DataError => Err(DeflateError::DataError),
206 ReturnCode::MemError => Err(DeflateError::MemError),
207 ReturnCode::BufError => Ok(Status::BufError),
208 ReturnCode::VersionError => unreachable!("the rust API does not use the version"),
209 }
210 }
211}
212
213pub struct Deflate(crate::deflate::DeflateStream<'static>);
215
216impl Deflate {
217 pub fn total_in(&self) -> u64 {
219 #[allow(clippy::useless_conversion)]
220 u64::from(self.0.total_in)
221 }
222
223 pub fn total_out(&self) -> u64 {
225 #[allow(clippy::useless_conversion)]
226 u64::from(self.0.total_out)
227 }
228
229 pub fn error_message(&self) -> Option<&'static str> {
231 if self.0.msg.is_null() {
232 None
233 } else {
234 unsafe { core::ffi::CStr::from_ptr(self.0.msg).to_str() }.ok()
235 }
236 }
237
238 pub fn new(level: i32, zlib_header: bool, window_bits: u8) -> Self {
242 let config = DeflateConfig {
243 window_bits: if zlib_header {
244 i32::from(window_bits)
245 } else {
246 -i32::from(window_bits)
247 },
248 level,
249 ..DeflateConfig::default()
250 };
251
252 Self(crate::deflate::DeflateStream::new(config))
253 }
254
255 pub fn reset(&mut self) {
257 crate::deflate::reset(&mut self.0);
258 }
259
260 pub fn compress(
262 &mut self,
263 input: &[u8],
264 output: &mut [u8],
265 flush: DeflateFlush,
266 ) -> Result<Status, DeflateError> {
267 self.0.avail_in = Ord::min(input.len(), c_uint::MAX as usize) as c_uint;
271 self.0.avail_out = Ord::min(output.len(), c_uint::MAX as usize) as c_uint;
272
273 self.0.next_in = input.as_ptr().cast_mut();
275 self.0.next_out = output.as_mut_ptr();
276
277 crate::deflate::deflate(&mut self.0, flush).into()
278 }
279
280 pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, DeflateError> {
284 match crate::deflate::set_dictionary(&mut self.0, dictionary) {
285 ReturnCode::Ok => Ok(self.0.adler as u32),
286 ReturnCode::StreamError => Err(DeflateError::StreamError),
287 other => unreachable!("set_dictionary does not return {other:?}"),
288 }
289 }
290
291 pub fn set_level(&mut self, level: i32) -> Result<Status, DeflateError> {
302 match crate::deflate::params(&mut self.0, level, Default::default()) {
303 ReturnCode::Ok => Ok(Status::Ok),
304 ReturnCode::StreamError => Err(DeflateError::StreamError),
305 ReturnCode::BufError => Ok(Status::BufError),
306 other => unreachable!("set_level does not return {other:?}"),
307 }
308 }
309}
310
311impl Drop for Deflate {
312 fn drop(&mut self) {
313 let _ = crate::deflate::end(&mut self.0);
314 }
315}