diff --git a/src/deflate/bufread.rs b/src/deflate/bufread.rs index c70a6303..65358374 100644 --- a/src/deflate/bufread.rs +++ b/src/deflate/bufread.rs @@ -243,3 +243,50 @@ impl Write for DeflateDecoder { self.get_mut().flush() } } + +#[cfg(test)] +mod test { + use crate::bufread::DeflateDecoder; + use crate::deflate::write; + use crate::Compression; + use std::io::{Read, Write}; + + // DeflateDecoder consumes one deflate archive and then returns 0 for subsequent reads, allowing any + // additional data to be consumed by the caller. + #[test] + fn decode_extra_data() { + let expected = "Hello World"; + + let compressed = { + let mut e = write::DeflateEncoder::new(Vec::new(), Compression::default()); + e.write(expected.as_ref()).unwrap(); + let mut b = e.finish().unwrap(); + b.push(b'x'); + b + }; + + let mut output = Vec::new(); + let mut decoder = DeflateDecoder::new(compressed.as_slice()); + let decoded_bytes = decoder.read_to_end(&mut output).unwrap(); + assert_eq!(decoded_bytes, output.len()); + let actual = std::str::from_utf8(&output).expect("String parsing error"); + assert_eq!( + actual, expected, + "after decompression we obtain the original input" + ); + + output.clear(); + assert_eq!( + decoder.read(&mut output).unwrap(), + 0, + "subsequent read of decoder returns 0, but inner reader can return additional data" + ); + let mut reader = decoder.into_inner(); + assert_eq!( + reader.read_to_end(&mut output).unwrap(), + 1, + "extra data is accessible in underlying buf-read" + ); + assert_eq!(output, b"x"); + } +} diff --git a/src/deflate/write.rs b/src/deflate/write.rs index 2c44556a..0bd8502c 100644 --- a/src/deflate/write.rs +++ b/src/deflate/write.rs @@ -320,3 +320,43 @@ impl Read for DeflateDecoder { self.inner.get_mut().read(buf) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::Compression; + + const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World"; + + // DeflateDecoder consumes one zlib archive and then returns 0 for subsequent writes, allowing any + // additional data to be consumed by the caller. + #[test] + fn decode_extra_data() { + let compressed = { + let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let mut b = e.finish().unwrap(); + b.push(b'x'); + b + }; + + let mut writer = Vec::new(); + let mut decoder = DeflateDecoder::new(writer); + let mut consumed_bytes = 0; + loop { + let n = decoder.write(&compressed[consumed_bytes..]).unwrap(); + if n == 0 { + break; + } + consumed_bytes += n; + } + writer = decoder.finish().unwrap(); + let actual = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(actual, STR); + assert_eq!(&compressed[consumed_bytes..], b"x"); + } +} diff --git a/src/zlib/bufread.rs b/src/zlib/bufread.rs index 85bbd38a..da7ed95e 100644 --- a/src/zlib/bufread.rs +++ b/src/zlib/bufread.rs @@ -251,3 +251,50 @@ impl Write for ZlibDecoder { self.get_mut().flush() } } + +#[cfg(test)] +mod test { + use crate::bufread::ZlibDecoder; + use crate::zlib::write; + use crate::Compression; + use std::io::{Read, Write}; + + // ZlibDecoder consumes one zlib archive and then returns 0 for subsequent reads, allowing any + // additional data to be consumed by the caller. + #[test] + fn decode_extra_data() { + let expected = "Hello World"; + + let compressed = { + let mut e = write::ZlibEncoder::new(Vec::new(), Compression::default()); + e.write(expected.as_ref()).unwrap(); + let mut b = e.finish().unwrap(); + b.push(b'x'); + b + }; + + let mut output = Vec::new(); + let mut decoder = ZlibDecoder::new(compressed.as_slice()); + let decoded_bytes = decoder.read_to_end(&mut output).unwrap(); + assert_eq!(decoded_bytes, output.len()); + let actual = std::str::from_utf8(&output).expect("String parsing error"); + assert_eq!( + actual, expected, + "after decompression we obtain the original input" + ); + + output.clear(); + assert_eq!( + decoder.read(&mut output).unwrap(), + 0, + "subsequent read of decoder returns 0, but inner reader can return additional data" + ); + let mut reader = decoder.into_inner(); + assert_eq!( + reader.read_to_end(&mut output).unwrap(), + 1, + "extra data is accessible in underlying buf-read" + ); + assert_eq!(output, b"x"); + } +} diff --git a/src/zlib/write.rs b/src/zlib/write.rs index d8ad2f26..64c2c872 100644 --- a/src/zlib/write.rs +++ b/src/zlib/write.rs @@ -338,3 +338,43 @@ impl Read for ZlibDecoder { self.inner.get_mut().read(buf) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::Compression; + + const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World"; + + // ZlibDecoder consumes one zlib archive and then returns 0 for subsequent writes, allowing any + // additional data to be consumed by the caller. + #[test] + fn decode_extra_data() { + let compressed = { + let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let mut b = e.finish().unwrap(); + b.push(b'x'); + b + }; + + let mut writer = Vec::new(); + let mut decoder = ZlibDecoder::new(writer); + let mut consumed_bytes = 0; + loop { + let n = decoder.write(&compressed[consumed_bytes..]).unwrap(); + if n == 0 { + break; + } + consumed_bytes += n; + } + writer = decoder.finish().unwrap(); + let actual = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(actual, STR); + assert_eq!(&compressed[consumed_bytes..], b"x"); + } +}