diff --git a/src/decoder.rs b/src/decoder.rs index c13e3b1c3..f35af43dc 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -69,13 +69,13 @@ impl Read for Decoder { self.next }; self.len = self.r.read(&mut self.buf[0..need])?; - if self.len == 0 { - break; - } + // NOTE: we do not exit here if there was nothing read + // The lz4 context may still have more bytes to emit. + self.pos = 0; self.next -= self.len; } - while (dst_offset < buf.len()) && (self.pos < self.len) { + while (dst_offset < buf.len()) && ((self.pos < self.len) || self.len == 0) { let mut src_size = (self.len - self.pos) as size_t; let mut dst_size = (buf.len() - dst_offset) as size_t; let len = check_error(unsafe { @@ -90,6 +90,14 @@ impl Read for Decoder { })?; self.pos += src_size as usize; dst_offset += dst_size as usize; + + // We need to keep trying to read bytes from the decompressor + // until it is no longer emitting them, even after it + // has finished reading bytes. + if dst_size == 0 && src_size == 0 { + return Ok(dst_offset); + } + if len == 0 { self.next = 0; return Ok(dst_offset); @@ -290,6 +298,40 @@ mod test { finish_decode(decoder); } + /// Ensure that we emit the full decompressed stream even if we're + /// using a very small output buffer. + #[test] + fn issue_45() { + // create an encoder + let mut enc = crate::EncoderBuilder::new().build(Vec::new()).unwrap(); + + // write 'a' 100 times to the encoder + let text: Vec = vec!['a' as u8; 100]; + enc.write_all(&text[..]).unwrap(); + + // flush the encoder + enc.flush().unwrap(); + + // read from the decoder, buf_size bytes at a time + for buf_size in [5, 10, 15, 20, 25] { + let mut buf = vec![0; buf_size]; + + let mut total_bytes_read = 0; + + // create a decoder wrapping the backing buffer + let mut dec = crate::Decoder::new(&enc.writer()[..]).unwrap(); + while let Ok(n) = dec.read(&mut buf[..]) { + if n == 0 { + break; + } + + total_bytes_read += n; + } + + assert_eq!(total_bytes_read, text.len()); + } + } + fn random() -> StdRng { let seed: [u8; 32] = [ 157, 164, 190, 237, 231, 103, 60, 22, 197, 108, 51, 176, 30, 170, 155, 21, 163, 249, diff --git a/src/encoder.rs b/src/encoder.rs index 0c9fe2b2e..974117b55 100644 --- a/src/encoder.rs +++ b/src/encoder.rs @@ -39,7 +39,7 @@ impl EncoderBuilder { block_size: BlockSize::Default, block_mode: BlockMode::Linked, checksum: ContentChecksum::ChecksumEnabled, - block_checksum: BlockChecksum::NoBlockChecksum, + block_checksum: BlockChecksum::BlockChecksumEnabled, level: 0, auto_flush: false, favor_dec_speed: false, @@ -99,7 +99,7 @@ impl EncoderBuilder { content_size: self.content_size.clone(), frame_type: FrameType::Frame, dict_id: 0, - block_checksum_flag: BlockChecksum::BlockChecksumEnabled, + block_checksum_flag: self.block_checksum.clone(), }, compression_level: self.level, auto_flush: if self.auto_flush { 1 } else { 0 },