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