diff --git a/src/codec/gzip/decoder.rs b/src/codec/gzip/decoder.rs index fc38a43c..6e9958fd 100644 --- a/src/codec/gzip/decoder.rs +++ b/src/codec/gzip/decoder.rs @@ -80,8 +80,20 @@ impl GzipDecoder { State::Decoding => { let prior = output.written().len(); - let done = inner(self, input, output)?; + + let done = inner(self, input, output).or_else(|e| match e { + // we need to make an exception, if output flushed + // from the decoder, to update the crc + e if e.kind() == std::io::ErrorKind::Other + && output.written().len() > 0 => + { + Ok(false) + } + _ => Err(e), + })?; + self.crc.update(&output.written()[prior..]); + 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..591bd306 100644 --- a/src/futures/bufread/generic/decoder.rs +++ b/src/futures/bufread/generic/decoder.rs @@ -65,18 +65,39 @@ 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))?; + let input = if first { + &[][..] + } else { + 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. *this.multiple_members = false; + } + + if input.is_empty() && !first { 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(|e| { + // ignore the first error, occurs when input is empty + // but we need to run decode to flush + if first { + Ok(false) + } else { + Err(e) + } + })?; + + first = false; + let len = input.written().len(); this.reader.as_mut().consume(len); if done {