diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d8152b0..732309eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0), ## Unreleased +- Flush available data in decoder even when there's no incoming input. + ## 0.4.5 - Add `{Lzma, Xz}Decoder::with_mem_limit()` methods. diff --git a/src/codec/gzip/decoder.rs b/src/codec/gzip/decoder.rs index fc38a43c..4bb42606 100644 --- a/src/codec/gzip/decoder.rs +++ b/src/codec/gzip/decoder.rs @@ -80,8 +80,16 @@ impl GzipDecoder { State::Decoding => { let prior = output.written().len(); - let done = inner(self, input, output)?; - self.crc.update(&output.written()[prior..]); + + let res = inner(self, input, output); + + if (output.written().len() > prior) { + // update CRC even if there was an error + self.crc.update(&output.written()[prior..]); + } + + let done = res?; + if done { self.state = State::Footer(vec![0; 8].into()) } diff --git a/src/futures/bufread/generic/decoder.rs b/src/futures/bufread/generic/decoder.rs index d19daae5..a3a968a7 100644 --- a/src/futures/bufread/generic/decoder.rs +++ b/src/futures/bufread/generic/decoder.rs @@ -65,18 +65,37 @@ impl Decoder { ) -> Poll> { let mut this = self.project(); + let mut first = true; + loop { *this.state = match this.state { State::Decoding => { - let input = ready!(this.reader.as_mut().poll_fill_buf(cx))?; - if input.is_empty() { - // Avoid attempting to reinitialise the decoder if the reader - // has returned EOF. + let input = if first { + &[][..] + } else { + ready!(this.reader.as_mut().poll_fill_buf(cx))? + }; + + if input.is_empty() && !first { + // Avoid attempting to reinitialise the decoder if the + // reader has returned EOF. *this.multiple_members = false; + State::Flushing } else { let mut input = PartialBuffer::new(input); - let done = this.decoder.decode(&mut input, output)?; + let done = this.decoder.decode(&mut input, output).or_else(|err| { + // ignore the first error, occurs when input is empty + // but we need to run decode to flush + if first { + Ok(false) + } else { + Err(err) + } + })?; + + first = false; + let len = input.written().len(); this.reader.as_mut().consume(len); if done {