1 //! Implementation for `miniz_oxide` rust backend.
2 
3 use std::convert::TryInto;
4 use std::fmt;
5 
6 use miniz_oxide::deflate::core::CompressorOxide;
7 use miniz_oxide::inflate::stream::InflateState;
8 pub use miniz_oxide::*;
9 
10 pub const MZ_NO_FLUSH: isize = MZFlush::None as isize;
11 pub const MZ_PARTIAL_FLUSH: isize = MZFlush::Partial as isize;
12 pub const MZ_SYNC_FLUSH: isize = MZFlush::Sync as isize;
13 pub const MZ_FULL_FLUSH: isize = MZFlush::Full as isize;
14 pub const MZ_FINISH: isize = MZFlush::Finish as isize;
15 
16 use super::*;
17 use crate::mem;
18 
19 // miniz_oxide doesn't provide any error messages (yet?)
20 #[derive(Default)]
21 pub struct ErrorMessage;
22 
23 impl ErrorMessage {
get(&self) -> Option<&str>24     pub fn get(&self) -> Option<&str> {
25         None
26     }
27 }
28 
format_from_bool(zlib_header: bool) -> DataFormat29 fn format_from_bool(zlib_header: bool) -> DataFormat {
30     if zlib_header {
31         DataFormat::Zlib
32     } else {
33         DataFormat::Raw
34     }
35 }
36 
37 pub struct Inflate {
38     inner: Box<InflateState>,
39     total_in: u64,
40     total_out: u64,
41 }
42 
43 impl fmt::Debug for Inflate {
fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>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 
53 impl InflateBackend for Inflate {
make(zlib_header: bool, _window_bits: u8) -> Self54     fn make(zlib_header: bool, _window_bits: u8) -> Self {
55         let format = format_from_bool(zlib_header);
56 
57         Inflate {
58             inner: InflateState::new_boxed(format),
59             total_in: 0,
60             total_out: 0,
61         }
62     }
63 
decompress( &mut self, input: &[u8], output: &mut [u8], flush: FlushDecompress, ) -> Result<Status, DecompressError>64     fn decompress(
65         &mut self,
66         input: &[u8],
67         output: &mut [u8],
68         flush: FlushDecompress,
69     ) -> Result<Status, DecompressError> {
70         let flush = MZFlush::new(flush as i32).unwrap();
71 
72         let res = inflate::stream::inflate(&mut self.inner, input, output, flush);
73         self.total_in += res.bytes_consumed as u64;
74         self.total_out += res.bytes_written as u64;
75 
76         match res.status {
77             Ok(status) => match status {
78                 MZStatus::Ok => Ok(Status::Ok),
79                 MZStatus::StreamEnd => Ok(Status::StreamEnd),
80                 MZStatus::NeedDict => {
81                     mem::decompress_need_dict(self.inner.decompressor().adler32().unwrap_or(0))
82                 }
83             },
84             Err(status) => match status {
85                 MZError::Buf => Ok(Status::BufError),
86                 _ => mem::decompress_failed(ErrorMessage),
87             },
88         }
89     }
90 
reset(&mut self, zlib_header: bool)91     fn reset(&mut self, zlib_header: bool) {
92         self.inner.reset(format_from_bool(zlib_header));
93         self.total_in = 0;
94         self.total_out = 0;
95     }
96 }
97 
98 impl Backend for Inflate {
99     #[inline]
total_in(&self) -> u64100     fn total_in(&self) -> u64 {
101         self.total_in
102     }
103 
104     #[inline]
total_out(&self) -> u64105     fn total_out(&self) -> u64 {
106         self.total_out
107     }
108 }
109 
110 pub struct Deflate {
111     inner: Box<CompressorOxide>,
112     total_in: u64,
113     total_out: u64,
114 }
115 
116 impl fmt::Debug for Deflate {
fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>117     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
118         write!(
119             f,
120             "miniz_oxide deflate internal state. total_in: {}, total_out: {}",
121             self.total_in, self.total_out,
122         )
123     }
124 }
125 
126 impl DeflateBackend for Deflate {
make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self127     fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self {
128         // Check in case the integer value changes at some point.
129         debug_assert!(level.level() <= 10);
130 
131         let mut inner: Box<CompressorOxide> = Box::default();
132         let format = format_from_bool(zlib_header);
133         inner.set_format_and_level(format, level.level().try_into().unwrap_or(1));
134 
135         Deflate {
136             inner,
137             total_in: 0,
138             total_out: 0,
139         }
140     }
141 
compress( &mut self, input: &[u8], output: &mut [u8], flush: FlushCompress, ) -> Result<Status, CompressError>142     fn compress(
143         &mut self,
144         input: &[u8],
145         output: &mut [u8],
146         flush: FlushCompress,
147     ) -> Result<Status, CompressError> {
148         let flush = MZFlush::new(flush as i32).unwrap();
149         let res = deflate::stream::deflate(&mut self.inner, input, output, flush);
150         self.total_in += res.bytes_consumed as u64;
151         self.total_out += res.bytes_written as u64;
152 
153         match res.status {
154             Ok(status) => match status {
155                 MZStatus::Ok => Ok(Status::Ok),
156                 MZStatus::StreamEnd => Ok(Status::StreamEnd),
157                 MZStatus::NeedDict => mem::compress_failed(ErrorMessage),
158             },
159             Err(status) => match status {
160                 MZError::Buf => Ok(Status::BufError),
161                 _ => mem::compress_failed(ErrorMessage),
162             },
163         }
164     }
165 
reset(&mut self)166     fn reset(&mut self) {
167         self.total_in = 0;
168         self.total_out = 0;
169         self.inner.reset();
170     }
171 }
172 
173 impl Backend for Deflate {
174     #[inline]
total_in(&self) -> u64175     fn total_in(&self) -> u64 {
176         self.total_in
177     }
178 
179     #[inline]
total_out(&self) -> u64180     fn total_out(&self) -> u64 {
181         self.total_out
182     }
183 }
184