summaryrefslogtreecommitdiffstats
path: root/vendor/gix-features-0.35.0/src/zlib/stream/inflate.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-features-0.35.0/src/zlib/stream/inflate.rs')
-rw-r--r--vendor/gix-features-0.35.0/src/zlib/stream/inflate.rs40
1 files changed, 40 insertions, 0 deletions
diff --git a/vendor/gix-features-0.35.0/src/zlib/stream/inflate.rs b/vendor/gix-features-0.35.0/src/zlib/stream/inflate.rs
new file mode 100644
index 000000000..11dc92800
--- /dev/null
+++ b/vendor/gix-features-0.35.0/src/zlib/stream/inflate.rs
@@ -0,0 +1,40 @@
+use std::{io, io::BufRead};
+
+use flate2::{Decompress, FlushDecompress, Status};
+
+/// Read bytes from `rd` and decompress them using `state` into a pre-allocated fitting buffer `dst`, returning the amount of bytes written.
+pub fn read(rd: &mut impl BufRead, state: &mut Decompress, mut dst: &mut [u8]) -> io::Result<usize> {
+ let mut total_written = 0;
+ loop {
+ let (written, consumed, ret, eof);
+ {
+ let input = rd.fill_buf()?;
+ eof = input.is_empty();
+ let before_out = state.total_out();
+ let before_in = state.total_in();
+ let flush = if eof {
+ FlushDecompress::Finish
+ } else {
+ FlushDecompress::None
+ };
+ ret = state.decompress(input, dst, flush);
+ written = (state.total_out() - before_out) as usize;
+ total_written += written;
+ dst = &mut dst[written..];
+ consumed = (state.total_in() - before_in) as usize;
+ }
+ rd.consume(consumed);
+
+ match ret {
+ // The stream has officially ended, nothing more to do here.
+ Ok(Status::StreamEnd) => return Ok(total_written),
+ // Either input our output are depleted even though the stream is not depleted yet.
+ Ok(Status::Ok | Status::BufError) if eof || dst.is_empty() => return Ok(total_written),
+ // Some progress was made in both the input and the output, it must continue to reach the end.
+ Ok(Status::Ok | Status::BufError) if consumed != 0 || written != 0 => continue,
+ // A strange state, where zlib makes no progress but isn't done either. Call it out.
+ Ok(Status::Ok | Status::BufError) => unreachable!("Definitely a bug somewhere"),
+ Err(..) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "corrupt deflate stream")),
+ }
+ }
+}