Skip to content

Commit cdc1ed9

Browse files
committed
fix: attempt to decode from internal state even if nothing was read
Unlike zlib, miniz_oxide consumes data into internal state even if there is not enough space in the output buffer. Next time poll_fill_buf() is called we should try to decode from internal state even if no new compressed data was read.
1 parent 3337a1b commit cdc1ed9

File tree

2 files changed

+41
-16
lines changed

2 files changed

+41
-16
lines changed

src/codec/flate/decoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl Decode for FlateDecoder {
5151
match self.decode(input, output, FlushDecompress::None)? {
5252
Status::Ok => Ok(false),
5353
Status::StreamEnd => Ok(true),
54-
Status::BufError => Err(io::Error::new(io::ErrorKind::Other, "unexpected BufError")),
54+
Status::BufError => Ok(true), // Waiting for more input.
5555
}
5656
}
5757

src/tokio/bufread/generic/decoder.rs

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,21 +68,46 @@ impl<R: AsyncBufRead, D: Decode> Decoder<R, D> {
6868
loop {
6969
*this.state = match this.state {
7070
State::Decoding => {
71-
let input = ready!(this.reader.as_mut().poll_fill_buf(cx))?;
72-
if input.is_empty() {
73-
// Avoid attempting to reinitialise the decoder if the reader
74-
// has returned EOF.
75-
*this.multiple_members = false;
76-
State::Flushing
77-
} else {
78-
let mut input = PartialBuffer::new(input);
79-
let done = this.decoder.decode(&mut input, output)?;
80-
let len = input.written().len();
81-
this.reader.as_mut().consume(len);
82-
if done {
83-
State::Flushing
84-
} else {
85-
State::Decoding
71+
let fill_buf_result = this.reader.as_mut().poll_fill_buf(cx);
72+
73+
match fill_buf_result {
74+
Poll::Pending => {
75+
// Try to decode even if there is no new data.
76+
// Some data may be left in the internal state of the decoder
77+
// because there was not enough space in the output buffer.
78+
let written_before = output.written().len();
79+
80+
let mut input: Vec<u8> = vec![];
81+
let mut input = PartialBuffer::new(input);
82+
let done = this.decoder.decode(&mut input, output)?;
83+
if output.written().len() == written_before {
84+
return Poll::Pending;
85+
}
86+
87+
if done {
88+
State::Flushing
89+
} else {
90+
State::Decoding
91+
}
92+
}
93+
Poll::Ready(input) => {
94+
let input = input?;
95+
if input.is_empty() {
96+
// Avoid attempting to reinitialise the decoder if the reader
97+
// has returned EOF.
98+
*this.multiple_members = false;
99+
State::Flushing
100+
} else {
101+
let mut input = PartialBuffer::new(input);
102+
let done = this.decoder.decode(&mut input, output)?;
103+
let len = input.written().len();
104+
this.reader.as_mut().consume(len);
105+
if done {
106+
State::Flushing
107+
} else {
108+
State::Decoding
109+
}
110+
}
86111
}
87112
}
88113
}

0 commit comments

Comments
 (0)