flate2/ffi/
miniz_oxide.rs1use alloc::boxed::Box;
4use core::convert::TryInto;
5use core::fmt;
6
7use ::miniz_oxide::deflate::core::CompressorOxide;
8use ::miniz_oxide::inflate::stream::InflateState;
9pub use ::miniz_oxide::*;
10
11pub const MZ_NO_FLUSH: isize = MZFlush::None as isize;
12pub const MZ_PARTIAL_FLUSH: isize = MZFlush::Partial as isize;
13pub const MZ_SYNC_FLUSH: isize = MZFlush::Sync as isize;
14pub const MZ_FULL_FLUSH: isize = MZFlush::Full as isize;
15pub const MZ_FINISH: isize = MZFlush::Finish as isize;
16
17use super::*;
18use crate::mem;
19
20#[derive(Clone, Default)]
22pub struct ErrorMessage;
23
24impl ErrorMessage {
25 pub fn get(&self) -> Option<&str> {
26 None
27 }
28}
29
30fn format_from_bool(zlib_header: bool) -> DataFormat {
31 if zlib_header {
32 DataFormat::Zlib
33 } else {
34 DataFormat::Raw
35 }
36}
37
38pub struct Inflate {
39 inner: Box<InflateState>,
40 total_in: u64,
41 total_out: u64,
42}
43
44impl fmt::Debug for Inflate {
45 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
46 write!(
47 f,
48 "miniz_oxide inflate internal state. total_in: {}, total_out: {}",
49 self.total_in, self.total_out,
50 )
51 }
52}
53
54impl From<FlushDecompress> for MZFlush {
55 fn from(value: FlushDecompress) -> Self {
56 match value {
57 FlushDecompress::None => Self::None,
58 FlushDecompress::Sync => Self::Sync,
59 FlushDecompress::Finish => Self::Finish,
60 }
61 }
62}
63
64impl InflateBackend for Inflate {
65 fn make(zlib_header: bool, _window_bits: u8) -> Self {
66 let format = format_from_bool(zlib_header);
67
68 Inflate {
69 inner: InflateState::new_boxed(format),
70 total_in: 0,
71 total_out: 0,
72 }
73 }
74
75 fn decompress(
76 &mut self,
77 input: &[u8],
78 output: &mut [u8],
79 flush: FlushDecompress,
80 ) -> Result<Status, DecompressError> {
81 let mz_flush = flush.into();
82 let res = inflate::stream::inflate(&mut self.inner, input, output, mz_flush);
83 self.total_in += res.bytes_consumed as u64;
84 self.total_out += res.bytes_written as u64;
85
86 match res.status {
87 Ok(status) => match status {
88 MZStatus::Ok => Ok(Status::Ok),
89 MZStatus::StreamEnd => Ok(Status::StreamEnd),
90 MZStatus::NeedDict => {
91 mem::decompress_need_dict(self.inner.decompressor().adler32().unwrap_or(0))
92 }
93 },
94 Err(status) => match status {
95 MZError::Buf => Ok(Status::BufError),
96 _ => mem::decompress_failed(ErrorMessage),
97 },
98 }
99 }
100
101 fn reset(&mut self, zlib_header: bool) {
102 self.inner.reset(format_from_bool(zlib_header));
103 self.total_in = 0;
104 self.total_out = 0;
105 }
106}
107
108impl Backend for Inflate {
109 #[inline]
110 fn total_in(&self) -> u64 {
111 self.total_in
112 }
113
114 #[inline]
115 fn total_out(&self) -> u64 {
116 self.total_out
117 }
118}
119
120pub struct Deflate {
121 inner: Box<CompressorOxide>,
122 total_in: u64,
123 total_out: u64,
124}
125
126impl fmt::Debug for Deflate {
127 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
128 write!(
129 f,
130 "miniz_oxide deflate internal state. total_in: {}, total_out: {}",
131 self.total_in, self.total_out,
132 )
133 }
134}
135
136impl From<FlushCompress> for MZFlush {
137 fn from(value: FlushCompress) -> Self {
138 match value {
139 FlushCompress::None => Self::None,
140 FlushCompress::Partial => Self::Partial,
141 FlushCompress::Sync => Self::Sync,
142 FlushCompress::Full => Self::Full,
143 FlushCompress::Finish => Self::Finish,
144 }
145 }
146}
147
148impl DeflateBackend for Deflate {
149 fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self {
150 debug_assert!(level.level() <= 10);
153
154 let mut inner: Box<CompressorOxide> = Box::default();
155 let format = format_from_bool(zlib_header);
156 inner.set_format_and_level(format, level.level().try_into().unwrap_or(1));
157
158 Deflate {
159 inner,
160 total_in: 0,
161 total_out: 0,
162 }
163 }
164
165 fn compress(
166 &mut self,
167 input: &[u8],
168 output: &mut [u8],
169 flush: FlushCompress,
170 ) -> Result<Status, CompressError> {
171 let mz_flush = flush.into();
172 let res = deflate::stream::deflate(&mut self.inner, input, output, mz_flush);
173 self.total_in += res.bytes_consumed as u64;
174 self.total_out += res.bytes_written as u64;
175
176 match res.status {
177 Ok(status) => match status {
178 MZStatus::Ok => Ok(Status::Ok),
179 MZStatus::StreamEnd => Ok(Status::StreamEnd),
180 MZStatus::NeedDict => mem::compress_failed(ErrorMessage),
181 },
182 Err(status) => match status {
183 MZError::Buf => Ok(Status::BufError),
184 _ => mem::compress_failed(ErrorMessage),
185 },
186 }
187 }
188
189 fn reset(&mut self) {
190 self.total_in = 0;
191 self.total_out = 0;
192 self.inner.reset();
193 }
194}
195
196impl Backend for Deflate {
197 #[inline]
198 fn total_in(&self) -> u64 {
199 self.total_in
200 }
201
202 #[inline]
203 fn total_out(&self) -> u64 {
204 self.total_out
205 }
206}