Skip to main content

flate2/ffi/
miniz_oxide.rs

1//! Implementation for `miniz_oxide` rust backend.
2
3use 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// miniz_oxide doesn't provide any error messages (yet?)
21#[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        // Check in case the integer value changes at some point. Unlike the other zlib
151        // implementations, miniz_oxide actually has a compression level 10.
152        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}