diff --git a/Cargo.toml b/Cargo.toml index d41209c5..3daea13e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -112,3 +112,6 @@ any_impl = [] [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] + +[patch.crates-io] +miniz_oxide = { git = "https://github.com/Frommi/miniz_oxide", branch = "master" } diff --git a/src/ffi/miniz_oxide.rs b/src/ffi/miniz_oxide.rs index 4dc7c478..69978ce4 100644 --- a/src/ffi/miniz_oxide.rs +++ b/src/ffi/miniz_oxide.rs @@ -136,7 +136,8 @@ impl From for MZFlush { fn from(value: FlushCompress) -> Self { match value { FlushCompress::None => Self::None, - FlushCompress::Partial | FlushCompress::Sync => Self::Sync, + FlushCompress::Partial => Self::Partial, + FlushCompress::Sync => Self::Sync, FlushCompress::Full => Self::Full, FlushCompress::Finish => Self::Finish, } diff --git a/src/mem.rs b/src/mem.rs index 903e46b5..9021a2e4 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -640,7 +640,6 @@ mod tests { use crate::write; use crate::{Compression, Decompress, FlushDecompress}; - #[cfg(feature = "any_zlib")] use crate::{Compress, FlushCompress}; #[test] @@ -819,4 +818,66 @@ mod tests { assert_eq!(err.message(), Some("invalid stored block lengths")); } + + fn compress_with_flush(flush: FlushCompress) -> Vec { + let incompressible = (0..=255).collect::>(); + let mut output = vec![0; 1024]; + + // Feed in the incompressible data followed by the indicated flush type. + let mut w = Compress::new(Compression::default(), false); + w.compress(&incompressible, &mut output, flush).unwrap(); + + if flush != FlushCompress::None { + // The first instance of incompressible input should have been written uncompressed. + assert!(w.total_out() >= 261); + assert_eq!(&output[0..5], &[0, 0, 1, 0xff, !1]); + assert_eq!(&output[5..261], &incompressible); + } + + // Feed in the same data again. + let len = w.total_out() as usize; + w.compress(&incompressible, &mut output[len..], FlushCompress::Finish) + .unwrap(); + + if flush != FlushCompress::Full { + // This time, the data should have been compressed (because it is an exact duplicate of + // the earlier block). + assert!(w.total_out() < 300); + } + + // Assert that all input has been processed. + assert_eq!(w.total_in(), 256 * 2); + + output.resize(w.total_out() as usize, 0); + output + } + + #[test] + fn test_partial_flush() { + let output = compress_with_flush(FlushCompress::Partial); + + // Check for partial flush marker. + assert_eq!(output[261], 0x2); + assert_eq!(output[262] & 0x7, 0x4); + } + + #[test] + fn test_sync_flush() { + let output = compress_with_flush(FlushCompress::Sync); + + // Check for sync flush marker. + assert_eq!(&output[261..][..5], &[0, 0, 0, 0xff, 0xff]); + } + + #[test] + fn test_full_flush() { + let output = compress_with_flush(FlushCompress::Full); + assert_eq!(output.len(), 527); + + // Check for flush flush marker. + assert_eq!(&output[261..][..5], &[0, 0, 0, 0xff, 0xff]); + + // Check that the second instance of incompressible input was also written uncompressed. + assert_eq!(&output[266..][..5], &[1, 0, 1, 0xff, !1]); + } }