diff --git a/src/ffi/c.rs b/src/ffi/c.rs index 8eae160bd..9763eece3 100644 --- a/src/ffi/c.rs +++ b/src/ffi/c.rs @@ -164,10 +164,6 @@ pub struct Inflate { impl InflateBackend for Inflate { fn make(zlib_header: bool, window_bits: u8) -> Self { - assert!( - window_bits > 8 && window_bits < 16, - "window_bits must be within 9 ..= 15" - ); unsafe { let mut state = StreamWrapper::default(); let ret = mz_inflateInit2( @@ -258,10 +254,6 @@ pub struct Deflate { impl DeflateBackend for Deflate { fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { - assert!( - window_bits > 8 && window_bits < 16, - "window_bits must be within 9 ..= 15" - ); unsafe { let mut state = StreamWrapper::default(); let ret = mz_deflateInit2( diff --git a/src/ffi/rust.rs b/src/ffi/rust.rs index 2e62cef09..ea95a29c4 100644 --- a/src/ffi/rust.rs +++ b/src/ffi/rust.rs @@ -41,12 +41,7 @@ impl fmt::Debug for Inflate { } impl InflateBackend for Inflate { - fn make(zlib_header: bool, window_bits: u8) -> Self { - assert!( - window_bits > 8 && window_bits < 16, - "window_bits must be within 9 ..= 15" - ); - + fn make(zlib_header: bool, _window_bits: u8) -> Self { let format = format_from_bool(zlib_header); Inflate { @@ -119,12 +114,7 @@ impl fmt::Debug for Deflate { } impl DeflateBackend for Deflate { - fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { - assert!( - window_bits > 8 && window_bits < 16, - "window_bits must be within 9 ..= 15" - ); - + fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self { // Check in case the integer value changes at some point. debug_assert!(level.level() <= 10); diff --git a/src/mem.rs b/src/mem.rs index e293b4ba8..ae159bdb8 100644 --- a/src/mem.rs +++ b/src/mem.rs @@ -215,11 +215,43 @@ impl Compress { zlib_header: bool, window_bits: u8, ) -> Compress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); Compress { inner: Deflate::make(level, zlib_header, window_bits), } } + /// Creates a new object ready for compressing data that it's given. + /// + /// The `level` argument here indicates what level of compression is going + /// to be performed. + /// + /// The Compress object produced by this constructor outputs gzip headers + /// for the compressed data. + /// + /// # Panics + /// + /// If `window_bits` does not fall into the range 9 ..= 15, + /// `new_with_window_bits` will panic. + /// + /// # Note + /// + /// This constructor is only available when the `zlib` feature is used. + /// Other backends currently do not support gzip headers for Compress. + #[cfg(feature = "zlib")] + pub fn new_gzip(level: Compression, window_bits: u8) -> Compress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); + Compress { + inner: Deflate::make(level, true, window_bits + 16), + } + } + /// Returns the total number of input bytes which have been processed by /// this compression object. pub fn total_in(&self) -> u64 { @@ -355,11 +387,40 @@ impl Decompress { /// Other backends currently do not support custom window bits. #[cfg(feature = "any_zlib")] pub fn new_with_window_bits(zlib_header: bool, window_bits: u8) -> Decompress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); Decompress { inner: Inflate::make(zlib_header, window_bits), } } + /// Creates a new object ready for decompressing data that it's given. + /// + /// The Deompress object produced by this constructor expects gzip headers + /// for the compressed data. + /// + /// # Panics + /// + /// If `window_bits` does not fall into the range 9 ..= 15, + /// `new_with_window_bits` will panic. + /// + /// # Note + /// + /// This constructor is only available when the `zlib` feature is used. + /// Other backends currently do not support gzip headers for Decompress. + #[cfg(feature = "zlib")] + pub fn new_gzip(window_bits: u8) -> Decompress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); + Decompress { + inner: Inflate::make(true, window_bits + 16), + } + } + /// Returns the total number of input bytes which have been processed by /// this decompression object. pub fn total_in(&self) -> u64 { @@ -645,4 +706,30 @@ mod tests { assert_eq!(&decoded[..decoder.total_out() as usize], string); } + + #[cfg(feature = "zlib")] + #[test] + fn test_gzip_flate() { + let string = "hello, hello!".as_bytes(); + + let mut encoded = Vec::with_capacity(1024); + + let mut encoder = Compress::new_gzip(Compression::default(), 9); + + encoder + .compress_vec(string, &mut encoded, FlushCompress::Finish) + .unwrap(); + + assert_eq!(encoder.total_in(), string.len() as u64); + assert_eq!(encoder.total_out(), encoded.len() as u64); + + let mut decoder = Decompress::new_gzip(9); + + let mut decoded = [0; 1024]; + decoder + .decompress(&encoded, &mut decoded, FlushDecompress::Finish) + .unwrap(); + + assert_eq!(&decoded[..decoder.total_out() as usize], string); + } }