aboutsummaryrefslogtreecommitdiff
path: root/vendor/miniz_oxide/src/deflate/stream.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/miniz_oxide/src/deflate/stream.rs')
-rw-r--r--vendor/miniz_oxide/src/deflate/stream.rs121
1 files changed, 121 insertions, 0 deletions
diff --git a/vendor/miniz_oxide/src/deflate/stream.rs b/vendor/miniz_oxide/src/deflate/stream.rs
new file mode 100644
index 0000000..39aa82d
--- /dev/null
+++ b/vendor/miniz_oxide/src/deflate/stream.rs
@@ -0,0 +1,121 @@
+//! Extra streaming compression functionality.
+//!
+//! As of now this is mainly intended for use to build a higher-level wrapper.
+//!
+//! There is no DeflateState as the needed state is contained in the compressor struct itself.
+
+use crate::deflate::core::{compress, CompressorOxide, TDEFLFlush, TDEFLStatus};
+use crate::{MZError, MZFlush, MZStatus, StreamResult};
+
+/// Try to compress from input to output with the given [`CompressorOxide`].
+///
+/// # Errors
+///
+/// Returns [`MZError::Buf`] If the size of the `output` slice is empty or no progress was made due
+/// to lack of expected input data, or if called without [`MZFlush::Finish`] after the compression
+/// was already finished.
+///
+/// Returns [`MZError::Param`] if the compressor parameters are set wrong.
+///
+/// Returns [`MZError::Stream`] when lower-level decompressor returns a
+/// [`TDEFLStatus::PutBufFailed`]; may not actually be possible.
+pub fn deflate(
+ compressor: &mut CompressorOxide,
+ input: &[u8],
+ output: &mut [u8],
+ flush: MZFlush,
+) -> StreamResult {
+ if output.is_empty() {
+ return StreamResult::error(MZError::Buf);
+ }
+
+ if compressor.prev_return_status() == TDEFLStatus::Done {
+ return if flush == MZFlush::Finish {
+ StreamResult {
+ bytes_written: 0,
+ bytes_consumed: 0,
+ status: Ok(MZStatus::StreamEnd),
+ }
+ } else {
+ StreamResult::error(MZError::Buf)
+ };
+ }
+
+ let mut bytes_written = 0;
+ let mut bytes_consumed = 0;
+
+ let mut next_in = input;
+ let mut next_out = output;
+
+ let status = loop {
+ let in_bytes;
+ let out_bytes;
+ let defl_status = {
+ let res = compress(compressor, next_in, next_out, TDEFLFlush::from(flush));
+ in_bytes = res.1;
+ out_bytes = res.2;
+ res.0
+ };
+
+ next_in = &next_in[in_bytes..];
+ next_out = &mut next_out[out_bytes..];
+ bytes_consumed += in_bytes;
+ bytes_written += out_bytes;
+
+ // Check if we are done, or compression failed.
+ match defl_status {
+ TDEFLStatus::BadParam => break Err(MZError::Param),
+ // Don't think this can happen as we're not using a custom callback.
+ TDEFLStatus::PutBufFailed => break Err(MZError::Stream),
+ TDEFLStatus::Done => break Ok(MZStatus::StreamEnd),
+ _ => (),
+ };
+
+ // All the output space was used, so wait for more.
+ if next_out.is_empty() {
+ break Ok(MZStatus::Ok);
+ }
+
+ if next_in.is_empty() && (flush != MZFlush::Finish) {
+ let total_changed = bytes_written > 0 || bytes_consumed > 0;
+
+ break if (flush != MZFlush::None) || total_changed {
+ // We wrote or consumed something, and/or did a flush (sync/partial etc.).
+ Ok(MZStatus::Ok)
+ } else {
+ // No more input data, not flushing, and nothing was consumed or written,
+ // so couldn't make any progress.
+ Err(MZError::Buf)
+ };
+ }
+ };
+ StreamResult {
+ bytes_consumed,
+ bytes_written,
+ status,
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::deflate;
+ use crate::deflate::CompressorOxide;
+ use crate::inflate::decompress_to_vec_zlib;
+ use crate::{MZFlush, MZStatus};
+ use alloc::boxed::Box;
+ use alloc::vec;
+
+ #[test]
+ fn test_state() {
+ let data = b"Hello zlib!";
+ let mut compressed = vec![0; 50];
+ let mut compressor = Box::<CompressorOxide>::default();
+ let res = deflate(&mut compressor, data, &mut compressed, MZFlush::Finish);
+ let status = res.status.expect("Failed to compress!");
+ let decomp =
+ decompress_to_vec_zlib(&compressed).expect("Failed to decompress compressed data");
+ assert_eq!(status, MZStatus::StreamEnd);
+ assert_eq!(decomp[..], data[..]);
+ assert_eq!(res.bytes_consumed, data.len());
+ }
+}