diff options
Diffstat (limited to 'vendor/flate2/src')
-rw-r--r-- | vendor/flate2/src/bufreader.rs | 104 | ||||
-rw-r--r-- | vendor/flate2/src/crc.rs | 184 | ||||
-rw-r--r-- | vendor/flate2/src/deflate/bufread.rs | 245 | ||||
-rw-r--r-- | vendor/flate2/src/deflate/mod.rs | 193 | ||||
-rw-r--r-- | vendor/flate2/src/deflate/read.rs | 241 | ||||
-rw-r--r-- | vendor/flate2/src/deflate/write.rs | 322 | ||||
-rw-r--r-- | vendor/flate2/src/ffi/c.rs | 433 | ||||
-rw-r--r-- | vendor/flate2/src/ffi/mod.rs | 52 | ||||
-rw-r--r-- | vendor/flate2/src/ffi/rust.rs | 183 | ||||
-rw-r--r-- | vendor/flate2/src/gz/bufread.rs | 483 | ||||
-rw-r--r-- | vendor/flate2/src/gz/mod.rs | 644 | ||||
-rw-r--r-- | vendor/flate2/src/gz/read.rs | 378 | ||||
-rw-r--r-- | vendor/flate2/src/gz/write.rs | 641 | ||||
-rw-r--r-- | vendor/flate2/src/lib.rs | 234 | ||||
-rw-r--r-- | vendor/flate2/src/mem.rs | 772 | ||||
-rw-r--r-- | vendor/flate2/src/zio.rs | 286 | ||||
-rw-r--r-- | vendor/flate2/src/zlib/bufread.rs | 253 | ||||
-rw-r--r-- | vendor/flate2/src/zlib/mod.rs | 159 | ||||
-rw-r--r-- | vendor/flate2/src/zlib/read.rs | 275 | ||||
-rw-r--r-- | vendor/flate2/src/zlib/write.rs | 340 |
20 files changed, 6422 insertions, 0 deletions
diff --git a/vendor/flate2/src/bufreader.rs b/vendor/flate2/src/bufreader.rs new file mode 100644 index 0000000..7e6f89d --- /dev/null +++ b/vendor/flate2/src/bufreader.rs @@ -0,0 +1,104 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// <https://github.com/rust-lang/rust/blob/HEAD/COPYRIGHT>. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::cmp; +use std::io; +use std::io::prelude::*; +use std::mem; + +pub struct BufReader<R> { + inner: R, + buf: Box<[u8]>, + pos: usize, + cap: usize, +} + +impl<R> ::std::fmt::Debug for BufReader<R> +where + R: ::std::fmt::Debug, +{ + fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> { + fmt.debug_struct("BufReader") + .field("reader", &self.inner) + .field( + "buffer", + &format_args!("{}/{}", self.cap - self.pos, self.buf.len()), + ) + .finish() + } +} + +impl<R: Read> BufReader<R> { + pub fn new(inner: R) -> BufReader<R> { + BufReader::with_buf(vec![0; 32 * 1024], inner) + } + + pub fn with_buf(buf: Vec<u8>, inner: R) -> BufReader<R> { + BufReader { + inner, + buf: buf.into_boxed_slice(), + pos: 0, + cap: 0, + } + } +} + +impl<R> BufReader<R> { + pub fn get_ref(&self) -> &R { + &self.inner + } + + pub fn get_mut(&mut self) -> &mut R { + &mut self.inner + } + + pub fn into_inner(self) -> R { + self.inner + } + + pub fn reset(&mut self, inner: R) -> R { + self.pos = 0; + self.cap = 0; + mem::replace(&mut self.inner, inner) + } +} + +impl<R: Read> Read for BufReader<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= self.buf.len() { + return self.inner.read(buf); + } + let nread = { + let mut rem = self.fill_buf()?; + rem.read(buf)? + }; + self.consume(nread); + Ok(nread) + } +} + +impl<R: Read> BufRead for BufReader<R> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + if self.pos == self.cap { + self.cap = self.inner.read(&mut self.buf)?; + self.pos = 0; + } + Ok(&self.buf[self.pos..self.cap]) + } + + fn consume(&mut self, amt: usize) { + self.pos = cmp::min(self.pos + amt, self.cap); + } +} diff --git a/vendor/flate2/src/crc.rs b/vendor/flate2/src/crc.rs new file mode 100644 index 0000000..16f5601 --- /dev/null +++ b/vendor/flate2/src/crc.rs @@ -0,0 +1,184 @@ +//! Simple CRC bindings backed by miniz.c + +use std::io; +use std::io::prelude::*; + +use crc32fast::Hasher; + +/// The CRC calculated by a [`CrcReader`]. +/// +/// [`CrcReader`]: struct.CrcReader.html +#[derive(Debug)] +pub struct Crc { + amt: u32, + hasher: Hasher, +} + +/// A wrapper around a [`Read`] that calculates the CRC. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +#[derive(Debug)] +pub struct CrcReader<R> { + inner: R, + crc: Crc, +} + +impl Default for Crc { + fn default() -> Self { + Self::new() + } +} + +impl Crc { + /// Create a new CRC. + pub fn new() -> Crc { + Crc { + amt: 0, + hasher: Hasher::new(), + } + } + + /// Returns the current crc32 checksum. + pub fn sum(&self) -> u32 { + self.hasher.clone().finalize() + } + + /// The number of bytes that have been used to calculate the CRC. + /// This value is only accurate if the amount is lower than 2<sup>32</sup>. + pub fn amount(&self) -> u32 { + self.amt + } + + /// Update the CRC with the bytes in `data`. + pub fn update(&mut self, data: &[u8]) { + self.amt = self.amt.wrapping_add(data.len() as u32); + self.hasher.update(data); + } + + /// Reset the CRC. + pub fn reset(&mut self) { + self.amt = 0; + self.hasher.reset(); + } + + /// Combine the CRC with the CRC for the subsequent block of bytes. + pub fn combine(&mut self, additional_crc: &Crc) { + self.amt = self.amt.wrapping_add(additional_crc.amt); + self.hasher.combine(&additional_crc.hasher); + } +} + +impl<R: Read> CrcReader<R> { + /// Create a new `CrcReader`. + pub fn new(r: R) -> CrcReader<R> { + CrcReader { + inner: r, + crc: Crc::new(), + } + } +} + +impl<R> CrcReader<R> { + /// Get the Crc for this `CrcReader`. + pub fn crc(&self) -> &Crc { + &self.crc + } + + /// Get the reader that is wrapped by this `CrcReader`. + pub fn into_inner(self) -> R { + self.inner + } + + /// Get the reader that is wrapped by this `CrcReader` by reference. + pub fn get_ref(&self) -> &R { + &self.inner + } + + /// Get a mutable reference to the reader that is wrapped by this `CrcReader`. + pub fn get_mut(&mut self) -> &mut R { + &mut self.inner + } + + /// Reset the Crc in this `CrcReader`. + pub fn reset(&mut self) { + self.crc.reset(); + } +} + +impl<R: Read> Read for CrcReader<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + let amt = self.inner.read(into)?; + self.crc.update(&into[..amt]); + Ok(amt) + } +} + +impl<R: BufRead> BufRead for CrcReader<R> { + fn fill_buf(&mut self) -> io::Result<&[u8]> { + self.inner.fill_buf() + } + fn consume(&mut self, amt: usize) { + if let Ok(data) = self.inner.fill_buf() { + self.crc.update(&data[..amt]); + } + self.inner.consume(amt); + } +} + +/// A wrapper around a [`Write`] that calculates the CRC. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +#[derive(Debug)] +pub struct CrcWriter<W> { + inner: W, + crc: Crc, +} + +impl<W> CrcWriter<W> { + /// Get the Crc for this `CrcWriter`. + pub fn crc(&self) -> &Crc { + &self.crc + } + + /// Get the writer that is wrapped by this `CrcWriter`. + pub fn into_inner(self) -> W { + self.inner + } + + /// Get the writer that is wrapped by this `CrcWriter` by reference. + pub fn get_ref(&self) -> &W { + &self.inner + } + + /// Get a mutable reference to the writer that is wrapped by this `CrcWriter`. + pub fn get_mut(&mut self) -> &mut W { + &mut self.inner + } + + /// Reset the Crc in this `CrcWriter`. + pub fn reset(&mut self) { + self.crc.reset(); + } +} + +impl<W: Write> CrcWriter<W> { + /// Create a new `CrcWriter`. + pub fn new(w: W) -> CrcWriter<W> { + CrcWriter { + inner: w, + crc: Crc::new(), + } + } +} + +impl<W: Write> Write for CrcWriter<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + let amt = self.inner.write(buf)?; + self.crc.update(&buf[..amt]); + Ok(amt) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} diff --git a/vendor/flate2/src/deflate/bufread.rs b/vendor/flate2/src/deflate/bufread.rs new file mode 100644 index 0000000..c70a630 --- /dev/null +++ b/vendor/flate2/src/deflate/bufread.rs @@ -0,0 +1,245 @@ +use std::io; +use std::io::prelude::*; +use std::mem; + +use crate::zio; +use crate::{Compress, Decompress}; + +/// A DEFLATE encoder, or compressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// uncompressed data from the underlying [`BufRead`] and provides the compressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// use flate2::Compression; +/// use flate2::bufread::DeflateEncoder; +/// use std::fs::File; +/// use std::io::BufReader; +/// +/// # fn main() { +/// # println!("{:?}", open_hello_world().unwrap()); +/// # } +/// # +/// // Opens sample file, compresses the contents and returns a Vector +/// fn open_hello_world() -> io::Result<Vec<u8>> { +/// let f = File::open("examples/hello_world.txt")?; +/// let b = BufReader::new(f); +/// let mut deflater = DeflateEncoder::new(b, Compression::fast()); +/// let mut buffer = Vec::new(); +/// deflater.read_to_end(&mut buffer)?; +/// Ok(buffer) +/// } +/// ``` +#[derive(Debug)] +pub struct DeflateEncoder<R> { + obj: R, + data: Compress, +} + +impl<R: BufRead> DeflateEncoder<R> { + /// Creates a new encoder which will read uncompressed data from the given + /// stream and emit the compressed stream. + pub fn new(r: R, level: crate::Compression) -> DeflateEncoder<R> { + DeflateEncoder { + obj: r, + data: Compress::new(level, false), + } + } +} + +pub fn reset_encoder_data<R>(zlib: &mut DeflateEncoder<R>) { + zlib.data.reset(); +} + +impl<R> DeflateEncoder<R> { + /// Resets the state of this encoder entirely, swapping out the input + /// stream for another. + /// + /// This function will reset the internal state of this encoder and replace + /// the input stream with the one provided, returning the previous input + /// stream. Future data read from this encoder will be the compressed + /// version of `r`'s data. + pub fn reset(&mut self, r: R) -> R { + reset_encoder_data(self); + mem::replace(&mut self.obj, r) + } + + /// Acquires a reference to the underlying reader + pub fn get_ref(&self) -> &R { + &self.obj + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + &mut self.obj + } + + /// Consumes this encoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.obj + } + + /// Returns the number of bytes that have been read into this compressor. + /// + /// Note that not all bytes read from the underlying object may be accounted + /// for, there may still be some active buffering. + pub fn total_in(&self) -> u64 { + self.data.total_in() + } + + /// Returns the number of bytes that the compressor has produced. + /// + /// Note that not all bytes may have been read yet, some may still be + /// buffered. + pub fn total_out(&self) -> u64 { + self.data.total_out() + } +} + +impl<R: BufRead> Read for DeflateEncoder<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + zio::read(&mut self.obj, &mut self.data, buf) + } +} + +impl<W: BufRead + Write> Write for DeflateEncoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A DEFLATE decoder, or decompressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`BufRead`] and provides the uncompressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::DeflateEncoder; +/// use flate2::bufread::DeflateDecoder; +/// +/// # fn main() { +/// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements Read +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut deflater = DeflateDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// deflater.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct DeflateDecoder<R> { + obj: R, + data: Decompress, +} + +pub fn reset_decoder_data<R>(zlib: &mut DeflateDecoder<R>) { + zlib.data = Decompress::new(false); +} + +impl<R: BufRead> DeflateDecoder<R> { + /// Creates a new decoder which will decompress data read from the given + /// stream. + pub fn new(r: R) -> DeflateDecoder<R> { + DeflateDecoder { + obj: r, + data: Decompress::new(false), + } + } +} + +impl<R> DeflateDecoder<R> { + /// Resets the state of this decoder entirely, swapping out the input + /// stream for another. + /// + /// This will reset the internal state of this decoder and replace the + /// input stream with the one provided, returning the previous input + /// stream. Future data read from this decoder will be the decompressed + /// version of `r`'s data. + pub fn reset(&mut self, r: R) -> R { + reset_decoder_data(self); + mem::replace(&mut self.obj, r) + } + + /// Resets the state of this decoder's data + /// + /// This will reset the internal state of this decoder. It will continue + /// reading from the same stream. + pub fn reset_data(&mut self) { + reset_decoder_data(self); + } + + /// Acquires a reference to the underlying stream + pub fn get_ref(&self) -> &R { + &self.obj + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + &mut self.obj + } + + /// Consumes this decoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.obj + } + + /// Returns the number of bytes that the decompressor has consumed. + /// + /// Note that this will likely be smaller than what the decompressor + /// actually read from the underlying stream due to buffering. + pub fn total_in(&self) -> u64 { + self.data.total_in() + } + + /// Returns the number of bytes that the decompressor has produced. + pub fn total_out(&self) -> u64 { + self.data.total_out() + } +} + +impl<R: BufRead> Read for DeflateDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + zio::read(&mut self.obj, &mut self.data, into) + } +} + +impl<W: BufRead + Write> Write for DeflateDecoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} diff --git a/vendor/flate2/src/deflate/mod.rs b/vendor/flate2/src/deflate/mod.rs new file mode 100644 index 0000000..7f3bf70 --- /dev/null +++ b/vendor/flate2/src/deflate/mod.rs @@ -0,0 +1,193 @@ +pub mod bufread; +pub mod read; +pub mod write; + +#[cfg(test)] +mod tests { + use std::io::prelude::*; + + use rand::{thread_rng, Rng}; + + use super::{read, write}; + use crate::Compression; + + #[test] + fn roundtrip() { + let mut real = Vec::new(); + let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); + let v = crate::random_bytes().take(1024).collect::<Vec<_>>(); + for _ in 0..200 { + let to_write = &v[..thread_rng().gen_range(0..v.len())]; + real.extend(to_write.iter().copied()); + w.write_all(to_write).unwrap(); + } + let result = w.finish().unwrap(); + let mut r = read::DeflateDecoder::new(&result[..]); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, real); + } + + #[test] + fn drop_writes() { + let mut data = Vec::new(); + write::DeflateEncoder::new(&mut data, Compression::default()) + .write_all(b"foo") + .unwrap(); + let mut r = read::DeflateDecoder::new(&data[..]); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, b"foo"); + } + + #[test] + fn total_in() { + let mut real = Vec::new(); + let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); + let v = crate::random_bytes().take(1024).collect::<Vec<_>>(); + for _ in 0..200 { + let to_write = &v[..thread_rng().gen_range(0..v.len())]; + real.extend(to_write.iter().copied()); + w.write_all(to_write).unwrap(); + } + let mut result = w.finish().unwrap(); + + let result_len = result.len(); + + for _ in 0..200 { + result.extend(v.iter().copied()); + } + + let mut r = read::DeflateDecoder::new(&result[..]); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, real); + assert_eq!(r.total_in(), result_len as u64); + } + + #[test] + fn roundtrip2() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut r = + read::DeflateDecoder::new(read::DeflateEncoder::new(&v[..], Compression::default())); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, v); + } + + #[test] + fn roundtrip3() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut w = write::DeflateEncoder::new( + write::DeflateDecoder::new(Vec::new()), + Compression::default(), + ); + w.write_all(&v).unwrap(); + let w = w.finish().unwrap().finish().unwrap(); + assert_eq!(w, v); + } + + #[test] + fn reset_writer() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); + w.write_all(&v).unwrap(); + let a = w.reset(Vec::new()).unwrap(); + w.write_all(&v).unwrap(); + let b = w.finish().unwrap(); + + let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); + w.write_all(&v).unwrap(); + let c = w.finish().unwrap(); + assert!(a == b && b == c); + } + + #[test] + fn reset_reader() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); + let mut r = read::DeflateEncoder::new(&v[..], Compression::default()); + r.read_to_end(&mut a).unwrap(); + r.reset(&v[..]); + r.read_to_end(&mut b).unwrap(); + + let mut r = read::DeflateEncoder::new(&v[..], Compression::default()); + r.read_to_end(&mut c).unwrap(); + assert!(a == b && b == c); + } + + #[test] + fn reset_decoder() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut w = write::DeflateEncoder::new(Vec::new(), Compression::default()); + w.write_all(&v).unwrap(); + let data = w.finish().unwrap(); + + { + let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); + let mut r = read::DeflateDecoder::new(&data[..]); + r.read_to_end(&mut a).unwrap(); + r.reset(&data); + r.read_to_end(&mut b).unwrap(); + + let mut r = read::DeflateDecoder::new(&data[..]); + r.read_to_end(&mut c).unwrap(); + assert!(a == b && b == c && c == v); + } + + { + let mut w = write::DeflateDecoder::new(Vec::new()); + w.write_all(&data).unwrap(); + let a = w.reset(Vec::new()).unwrap(); + w.write_all(&data).unwrap(); + let b = w.finish().unwrap(); + + let mut w = write::DeflateDecoder::new(Vec::new()); + w.write_all(&data).unwrap(); + let c = w.finish().unwrap(); + assert!(a == b && b == c && c == v); + } + } + + #[test] + fn zero_length_read_with_data() { + let m = vec![3u8; 128 * 1024 + 1]; + let mut c = read::DeflateEncoder::new(&m[..], Compression::default()); + + let mut result = Vec::new(); + c.read_to_end(&mut result).unwrap(); + + let mut d = read::DeflateDecoder::new(&result[..]); + let mut data = Vec::new(); + assert_eq!(d.read(&mut data).unwrap(), 0); + } + + #[test] + fn qc_reader() { + ::quickcheck::quickcheck(test as fn(_) -> _); + + fn test(v: Vec<u8>) -> bool { + let mut r = read::DeflateDecoder::new(read::DeflateEncoder::new( + &v[..], + Compression::default(), + )); + let mut v2 = Vec::new(); + r.read_to_end(&mut v2).unwrap(); + v == v2 + } + } + + #[test] + fn qc_writer() { + ::quickcheck::quickcheck(test as fn(_) -> _); + + fn test(v: Vec<u8>) -> bool { + let mut w = write::DeflateEncoder::new( + write::DeflateDecoder::new(Vec::new()), + Compression::default(), + ); + w.write_all(&v).unwrap(); + v == w.finish().unwrap().finish().unwrap() + } + } +} diff --git a/vendor/flate2/src/deflate/read.rs b/vendor/flate2/src/deflate/read.rs new file mode 100644 index 0000000..2b6b8f2 --- /dev/null +++ b/vendor/flate2/src/deflate/read.rs @@ -0,0 +1,241 @@ +use std::io; +use std::io::prelude::*; + +use super::bufread; +use crate::bufreader::BufReader; + +/// A DEFLATE encoder, or compressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// uncompressed data from the underlying [`Read`] and provides the compressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// use flate2::Compression; +/// use flate2::read::DeflateEncoder; +/// +/// # fn main() { +/// # println!("{:?}", deflateencoder_read_hello_world().unwrap()); +/// # } +/// # +/// // Return a vector containing the Deflate compressed version of hello world +/// fn deflateencoder_read_hello_world() -> io::Result<Vec<u8>> { +/// let mut ret_vec = Vec::new(); +/// let c = b"hello world"; +/// let mut deflater = DeflateEncoder::new(&c[..], Compression::fast()); +/// deflater.read_to_end(&mut ret_vec)?; +/// Ok(ret_vec) +/// } +/// ``` +#[derive(Debug)] +pub struct DeflateEncoder<R> { + inner: bufread::DeflateEncoder<BufReader<R>>, +} + +impl<R: Read> DeflateEncoder<R> { + /// Creates a new encoder which will read uncompressed data from the given + /// stream and emit the compressed stream. + pub fn new(r: R, level: crate::Compression) -> DeflateEncoder<R> { + DeflateEncoder { + inner: bufread::DeflateEncoder::new(BufReader::new(r), level), + } + } +} + +impl<R> DeflateEncoder<R> { + /// Resets the state of this encoder entirely, swapping out the input + /// stream for another. + /// + /// This function will reset the internal state of this encoder and replace + /// the input stream with the one provided, returning the previous input + /// stream. Future data read from this encoder will be the compressed + /// version of `r`'s data. + /// + /// Note that there may be currently buffered data when this function is + /// called, and in that case the buffered data is discarded. + pub fn reset(&mut self, r: R) -> R { + super::bufread::reset_encoder_data(&mut self.inner); + self.inner.get_mut().reset(r) + } + + /// Acquires a reference to the underlying reader + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Consumes this encoder, returning the underlying reader. + /// + /// Note that there may be buffered bytes which are not re-acquired as part + /// of this transition. It's recommended to only call this function after + /// EOF has been reached. + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } + + /// Returns the number of bytes that have been read into this compressor. + /// + /// Note that not all bytes read from the underlying object may be accounted + /// for, there may still be some active buffering. + pub fn total_in(&self) -> u64 { + self.inner.total_in() + } + + /// Returns the number of bytes that the compressor has produced. + /// + /// Note that not all bytes may have been read yet, some may still be + /// buffered. + pub fn total_out(&self) -> u64 { + self.inner.total_out() + } +} + +impl<R: Read> Read for DeflateEncoder<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.read(buf) + } +} + +impl<W: Read + Write> Write for DeflateEncoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A DEFLATE decoder, or decompressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`Read`] and provides the uncompressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::DeflateEncoder; +/// use flate2::read::DeflateDecoder; +/// +/// # fn main() { +/// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements Read +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut deflater = DeflateDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// deflater.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct DeflateDecoder<R> { + inner: bufread::DeflateDecoder<BufReader<R>>, +} + +impl<R: Read> DeflateDecoder<R> { + /// Creates a new decoder which will decompress data read from the given + /// stream. + pub fn new(r: R) -> DeflateDecoder<R> { + DeflateDecoder::new_with_buf(r, vec![0; 32 * 1024]) + } + + /// Same as `new`, but the intermediate buffer for data is specified. + /// + /// Note that the capacity of the intermediate buffer is never increased, + /// and it is recommended for it to be large. + pub fn new_with_buf(r: R, buf: Vec<u8>) -> DeflateDecoder<R> { + DeflateDecoder { + inner: bufread::DeflateDecoder::new(BufReader::with_buf(buf, r)), + } + } +} + +impl<R> DeflateDecoder<R> { + /// Resets the state of this decoder entirely, swapping out the input + /// stream for another. + /// + /// This will reset the internal state of this decoder and replace the + /// input stream with the one provided, returning the previous input + /// stream. Future data read from this decoder will be the decompressed + /// version of `r`'s data. + /// + /// Note that there may be currently buffered data when this function is + /// called, and in that case the buffered data is discarded. + pub fn reset(&mut self, r: R) -> R { + super::bufread::reset_decoder_data(&mut self.inner); + self.inner.get_mut().reset(r) + } + + /// Acquires a reference to the underlying stream + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Consumes this decoder, returning the underlying reader. + /// + /// Note that there may be buffered bytes which are not re-acquired as part + /// of this transition. It's recommended to only call this function after + /// EOF has been reached. + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } + + /// Returns the number of bytes that the decompressor has consumed. + /// + /// Note that this will likely be smaller than what the decompressor + /// actually read from the underlying stream due to buffering. + pub fn total_in(&self) -> u64 { + self.inner.total_in() + } + + /// Returns the number of bytes that the decompressor has produced. + pub fn total_out(&self) -> u64 { + self.inner.total_out() + } +} + +impl<R: Read> Read for DeflateDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + self.inner.read(into) + } +} + +impl<W: Read + Write> Write for DeflateDecoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} diff --git a/vendor/flate2/src/deflate/write.rs b/vendor/flate2/src/deflate/write.rs new file mode 100644 index 0000000..2c44556 --- /dev/null +++ b/vendor/flate2/src/deflate/write.rs @@ -0,0 +1,322 @@ +use std::io; +use std::io::prelude::*; + +use crate::zio; +use crate::{Compress, Decompress}; + +/// A DEFLATE encoder, or compressor. +/// +/// This structure implements a [`Write`] interface and takes a stream of +/// uncompressed data, writing the compressed data to the wrapped writer. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use flate2::Compression; +/// use flate2::write::DeflateEncoder; +/// +/// // Vec<u8> implements Write to print the compressed bytes of sample string +/// # fn main() { +/// +/// let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); +/// e.write_all(b"Hello World").unwrap(); +/// println!("{:?}", e.finish().unwrap()); +/// # } +/// ``` +#[derive(Debug)] +pub struct DeflateEncoder<W: Write> { + inner: zio::Writer<W, Compress>, +} + +impl<W: Write> DeflateEncoder<W> { + /// Creates a new encoder which will write compressed data to the stream + /// given at the given compression level. + /// + /// When this encoder is dropped or unwrapped the final pieces of data will + /// be flushed. + pub fn new(w: W, level: crate::Compression) -> DeflateEncoder<W> { + DeflateEncoder { + inner: zio::Writer::new(w, Compress::new(level, false)), + } + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutating the output/input state of the stream may corrupt this + /// object, so care must be taken when using this method. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Resets the state of this encoder entirely, swapping out the output + /// stream for another. + /// + /// This function will finish encoding the current stream into the current + /// output stream before swapping out the two output streams. If the stream + /// cannot be finished an error is returned. + /// + /// After the current stream has been finished, this will reset the internal + /// state of this encoder and replace the output stream with the one + /// provided, returning the previous output stream. Future data written to + /// this encoder will be the compressed into the stream `w` provided. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn reset(&mut self, w: W) -> io::Result<W> { + self.inner.finish()?; + self.inner.data.reset(); + Ok(self.inner.replace(w)) + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn try_finish(&mut self) -> io::Result<()> { + self.inner.finish() + } + + /// Consumes this encoder, flushing the output stream. + /// + /// This will flush the underlying data stream, close off the compressed + /// stream and, if successful, return the contained writer. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(mut self) -> io::Result<W> { + self.inner.finish()?; + Ok(self.inner.take_inner()) + } + + /// Consumes this encoder, flushing the output stream. + /// + /// This will flush the underlying data stream and then return the contained + /// writer if the flush succeeded. + /// The compressed stream will not closed but only flushed. This + /// means that obtained byte array can by extended by another deflated + /// stream. To close the stream add the two bytes 0x3 and 0x0. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn flush_finish(mut self) -> io::Result<W> { + self.inner.flush()?; + Ok(self.inner.take_inner()) + } + + /// Returns the number of bytes that have been written to this compressor. + /// + /// Note that not all bytes written to this object may be accounted for, + /// there may still be some active buffering. + pub fn total_in(&self) -> u64 { + self.inner.data.total_in() + } + + /// Returns the number of bytes that the compressor has produced. + /// + /// Note that not all bytes may have been written yet, some may still be + /// buffered. + pub fn total_out(&self) -> u64 { + self.inner.data.total_out() + } +} + +impl<W: Write> Write for DeflateEncoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.inner.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl<W: Read + Write> Read for DeflateEncoder<W> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.get_mut().read(buf) + } +} + +/// A DEFLATE decoder, or decompressor. +/// +/// This structure implements a [`Write`] and will emit a stream of decompressed +/// data when fed a stream of compressed data. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::DeflateEncoder; +/// use flate2::write::DeflateDecoder; +/// +/// # fn main() { +/// # let mut e = DeflateEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_writer(bytes).unwrap()); +/// # } +/// // Uncompresses a Deflate Encoded vector of bytes and returns a string or error +/// // Here Vec<u8> implements Write +/// fn decode_writer(bytes: Vec<u8>) -> io::Result<String> { +/// let mut writer = Vec::new(); +/// let mut deflater = DeflateDecoder::new(writer); +/// deflater.write_all(&bytes[..])?; +/// writer = deflater.finish()?; +/// let return_string = String::from_utf8(writer).expect("String parsing error"); +/// Ok(return_string) +/// } +/// ``` +#[derive(Debug)] +pub struct DeflateDecoder<W: Write> { + inner: zio::Writer<W, Decompress>, +} + +impl<W: Write> DeflateDecoder<W> { + /// Creates a new decoder which will write uncompressed data to the stream. + /// + /// When this encoder is dropped or unwrapped the final pieces of data will + /// be flushed. + pub fn new(w: W) -> DeflateDecoder<W> { + DeflateDecoder { + inner: zio::Writer::new(w, Decompress::new(false)), + } + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutating the output/input state of the stream may corrupt this + /// object, so care must be taken when using this method. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Resets the state of this decoder entirely, swapping out the output + /// stream for another. + /// + /// This function will finish encoding the current stream into the current + /// output stream before swapping out the two output streams. + /// + /// This will then reset the internal state of this decoder and replace the + /// output stream with the one provided, returning the previous output + /// stream. Future data written to this decoder will be decompressed into + /// the output stream `w`. + /// + /// # Errors + /// + /// This function will perform I/O to finish the stream, and if that I/O + /// returns an error then that will be returned from this function. + pub fn reset(&mut self, w: W) -> io::Result<W> { + self.inner.finish()?; + self.inner.data = Decompress::new(false); + Ok(self.inner.replace(w)) + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to finish the stream, returning any + /// errors which happen. + pub fn try_finish(&mut self) -> io::Result<()> { + self.inner.finish() + } + + /// Consumes this encoder, flushing the output stream. + /// + /// This will flush the underlying data stream and then return the contained + /// writer if the flush succeeded. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(mut self) -> io::Result<W> { + self.inner.finish()?; + Ok(self.inner.take_inner()) + } + + /// Returns the number of bytes that the decompressor has consumed for + /// decompression. + /// + /// Note that this will likely be smaller than the number of bytes + /// successfully written to this stream due to internal buffering. + pub fn total_in(&self) -> u64 { + self.inner.data.total_in() + } + + /// Returns the number of bytes that the decompressor has written to its + /// output stream. + pub fn total_out(&self) -> u64 { + self.inner.data.total_out() + } +} + +impl<W: Write> Write for DeflateDecoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.inner.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl<W: Read + Write> Read for DeflateDecoder<W> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.get_mut().read(buf) + } +} diff --git a/vendor/flate2/src/ffi/c.rs b/vendor/flate2/src/ffi/c.rs new file mode 100644 index 0000000..32864f8 --- /dev/null +++ b/vendor/flate2/src/ffi/c.rs @@ -0,0 +1,433 @@ +//! Implementation for C backends. +use std::alloc::{self, Layout}; +use std::cmp; +use std::convert::TryFrom; +use std::fmt; +use std::marker; +use std::ops::{Deref, DerefMut}; +use std::os::raw::{c_int, c_uint, c_void}; +use std::ptr; + +use super::*; +use crate::mem::{self, FlushDecompress, Status}; + +#[derive(Default)] +pub struct ErrorMessage(Option<&'static str>); + +impl ErrorMessage { + pub fn get(&self) -> Option<&str> { + self.0 + } +} + +pub struct StreamWrapper { + pub inner: Box<mz_stream>, +} + +impl fmt::Debug for StreamWrapper { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!(f, "StreamWrapper") + } +} + +impl Default for StreamWrapper { + fn default() -> StreamWrapper { + StreamWrapper { + inner: Box::new(mz_stream { + next_in: ptr::null_mut(), + avail_in: 0, + total_in: 0, + next_out: ptr::null_mut(), + avail_out: 0, + total_out: 0, + msg: ptr::null_mut(), + adler: 0, + data_type: 0, + reserved: 0, + opaque: ptr::null_mut(), + state: ptr::null_mut(), + #[cfg(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys")))] + zalloc, + #[cfg(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys")))] + zfree, + #[cfg(not(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys"))))] + zalloc: Some(zalloc), + #[cfg(not(all(feature = "any_zlib", not(feature = "cloudflare-zlib-sys"))))] + zfree: Some(zfree), + }), + } + } +} + +const ALIGN: usize = std::mem::align_of::<usize>(); + +fn align_up(size: usize, align: usize) -> usize { + (size + align - 1) & !(align - 1) +} + +extern "C" fn zalloc(_ptr: *mut c_void, items: AllocSize, item_size: AllocSize) -> *mut c_void { + // We need to multiply `items` and `item_size` to get the actual desired + // allocation size. Since `zfree` doesn't receive a size argument we + // also need to allocate space for a `usize` as a header so we can store + // how large the allocation is to deallocate later. + let size = match items + .checked_mul(item_size) + .and_then(|i| usize::try_from(i).ok()) + .map(|size| align_up(size, ALIGN)) + .and_then(|i| i.checked_add(std::mem::size_of::<usize>())) + { + Some(i) => i, + None => return ptr::null_mut(), + }; + + // Make sure the `size` isn't too big to fail `Layout`'s restrictions + let layout = match Layout::from_size_align(size, ALIGN) { + Ok(layout) => layout, + Err(_) => return ptr::null_mut(), + }; + + unsafe { + // Allocate the data, and if successful store the size we allocated + // at the beginning and then return an offset pointer. + let ptr = alloc::alloc(layout) as *mut usize; + if ptr.is_null() { + return ptr as *mut c_void; + } + *ptr = size; + ptr.add(1) as *mut c_void + } +} + +extern "C" fn zfree(_ptr: *mut c_void, address: *mut c_void) { + unsafe { + // Move our address being freed back one pointer, read the size we + // stored in `zalloc`, and then free it using the standard Rust + // allocator. + let ptr = (address as *mut usize).offset(-1); + let size = *ptr; + let layout = Layout::from_size_align_unchecked(size, ALIGN); + alloc::dealloc(ptr as *mut u8, layout) + } +} + +impl Deref for StreamWrapper { + type Target = mz_stream; + + fn deref(&self) -> &Self::Target { + &*self.inner + } +} + +impl DerefMut for StreamWrapper { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut *self.inner + } +} + +unsafe impl<D: Direction> Send for Stream<D> {} +unsafe impl<D: Direction> Sync for Stream<D> {} + +/// Trait used to call the right destroy/end function on the inner +/// stream object on drop. +pub trait Direction { + unsafe fn destroy(stream: *mut mz_stream) -> c_int; +} + +#[derive(Debug)] +pub enum DirCompress {} +#[derive(Debug)] +pub enum DirDecompress {} + +#[derive(Debug)] +pub struct Stream<D: Direction> { + pub stream_wrapper: StreamWrapper, + pub total_in: u64, + pub total_out: u64, + pub _marker: marker::PhantomData<D>, +} + +impl<D: Direction> Stream<D> { + pub fn msg(&self) -> ErrorMessage { + let msg = self.stream_wrapper.msg; + ErrorMessage(if msg.is_null() { + None + } else { + let s = unsafe { std::ffi::CStr::from_ptr(msg) }; + std::str::from_utf8(s.to_bytes()).ok() + }) + } +} + +impl<D: Direction> Drop for Stream<D> { + fn drop(&mut self) { + unsafe { + let _ = D::destroy(&mut *self.stream_wrapper); + } + } +} + +impl Direction for DirCompress { + unsafe fn destroy(stream: *mut mz_stream) -> c_int { + mz_deflateEnd(stream) + } +} +impl Direction for DirDecompress { + unsafe fn destroy(stream: *mut mz_stream) -> c_int { + mz_inflateEnd(stream) + } +} + +#[derive(Debug)] +pub struct Inflate { + pub inner: Stream<DirDecompress>, +} + +impl InflateBackend for Inflate { + fn make(zlib_header: bool, window_bits: u8) -> Self { + unsafe { + let mut state = StreamWrapper::default(); + let ret = mz_inflateInit2( + &mut *state, + if zlib_header { + window_bits as c_int + } else { + -(window_bits as c_int) + }, + ); + assert_eq!(ret, 0); + Inflate { + inner: Stream { + stream_wrapper: state, + total_in: 0, + total_out: 0, + _marker: marker::PhantomData, + }, + } + } + } + + fn decompress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushDecompress, + ) -> Result<Status, DecompressError> { + let raw = &mut *self.inner.stream_wrapper; + raw.msg = ptr::null_mut(); + raw.next_in = input.as_ptr() as *mut u8; + raw.avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint; + raw.next_out = output.as_mut_ptr(); + raw.avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint; + + let rc = unsafe { mz_inflate(raw, flush as c_int) }; + + // Unfortunately the total counters provided by zlib might be only + // 32 bits wide and overflow while processing large amounts of data. + self.inner.total_in += (raw.next_in as usize - input.as_ptr() as usize) as u64; + self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64; + + // reset these pointers so we don't accidentally read them later + raw.next_in = ptr::null_mut(); + raw.avail_in = 0; + raw.next_out = ptr::null_mut(); + raw.avail_out = 0; + + match rc { + MZ_DATA_ERROR | MZ_STREAM_ERROR => mem::decompress_failed(self.inner.msg()), + MZ_OK => Ok(Status::Ok), + MZ_BUF_ERROR => Ok(Status::BufError), + MZ_STREAM_END => Ok(Status::StreamEnd), + MZ_NEED_DICT => mem::decompress_need_dict(raw.adler as u32), + c => panic!("unknown return code: {}", c), + } + } + + fn reset(&mut self, zlib_header: bool) { + let bits = if zlib_header { + MZ_DEFAULT_WINDOW_BITS + } else { + -MZ_DEFAULT_WINDOW_BITS + }; + unsafe { + inflateReset2(&mut *self.inner.stream_wrapper, bits); + } + self.inner.total_out = 0; + self.inner.total_in = 0; + } +} + +impl Backend for Inflate { + #[inline] + fn total_in(&self) -> u64 { + self.inner.total_in + } + + #[inline] + fn total_out(&self) -> u64 { + self.inner.total_out + } +} + +#[derive(Debug)] +pub struct Deflate { + pub inner: Stream<DirCompress>, +} + +impl DeflateBackend for Deflate { + fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self { + unsafe { + let mut state = StreamWrapper::default(); + let ret = mz_deflateInit2( + &mut *state, + level.0 as c_int, + MZ_DEFLATED, + if zlib_header { + window_bits as c_int + } else { + -(window_bits as c_int) + }, + 8, + MZ_DEFAULT_STRATEGY, + ); + assert_eq!(ret, 0); + Deflate { + inner: Stream { + stream_wrapper: state, + total_in: 0, + total_out: 0, + _marker: marker::PhantomData, + }, + } + } + } + fn compress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushCompress, + ) -> Result<Status, CompressError> { + let raw = &mut *self.inner.stream_wrapper; + raw.msg = ptr::null_mut(); + raw.next_in = input.as_ptr() as *mut _; + raw.avail_in = cmp::min(input.len(), c_uint::MAX as usize) as c_uint; + raw.next_out = output.as_mut_ptr(); + raw.avail_out = cmp::min(output.len(), c_uint::MAX as usize) as c_uint; + + let rc = unsafe { mz_deflate(raw, flush as c_int) }; + + // Unfortunately the total counters provided by zlib might be only + // 32 bits wide and overflow while processing large amounts of data. + self.inner.total_in += (raw.next_in as usize - input.as_ptr() as usize) as u64; + self.inner.total_out += (raw.next_out as usize - output.as_ptr() as usize) as u64; + + // reset these pointers so we don't accidentally read them later + raw.next_in = ptr::null_mut(); + raw.avail_in = 0; + raw.next_out = ptr::null_mut(); + raw.avail_out = 0; + + match rc { + MZ_OK => Ok(Status::Ok), + MZ_BUF_ERROR => Ok(Status::BufError), + MZ_STREAM_END => Ok(Status::StreamEnd), + MZ_STREAM_ERROR => mem::compress_failed(self.inner.msg()), + c => panic!("unknown return code: {}", c), + } + } + + fn reset(&mut self) { + self.inner.total_in = 0; + self.inner.total_out = 0; + let rc = unsafe { mz_deflateReset(&mut *self.inner.stream_wrapper) }; + assert_eq!(rc, MZ_OK); + } +} + +impl Backend for Deflate { + #[inline] + fn total_in(&self) -> u64 { + self.inner.total_in + } + + #[inline] + fn total_out(&self) -> u64 { + self.inner.total_out + } +} + +pub use self::c_backend::*; + +/// For backwards compatibility, we provide symbols as `mz_` to mimic the miniz API +#[allow(bad_style)] +mod c_backend { + use std::mem; + use std::os::raw::{c_char, c_int}; + + #[cfg(feature = "zlib-ng")] + use libz_ng_sys as libz; + + #[cfg(all(not(feature = "zlib-ng"), feature = "cloudflare_zlib"))] + use cloudflare_zlib_sys as libz; + + #[cfg(all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng")))] + use libz_sys as libz; + + pub use libz::deflate as mz_deflate; + pub use libz::deflateEnd as mz_deflateEnd; + pub use libz::deflateReset as mz_deflateReset; + pub use libz::inflate as mz_inflate; + pub use libz::inflateEnd as mz_inflateEnd; + pub use libz::z_stream as mz_stream; + pub use libz::*; + + pub use libz::Z_BLOCK as MZ_BLOCK; + pub use libz::Z_BUF_ERROR as MZ_BUF_ERROR; + pub use libz::Z_DATA_ERROR as MZ_DATA_ERROR; + pub use libz::Z_DEFAULT_STRATEGY as MZ_DEFAULT_STRATEGY; + pub use libz::Z_DEFLATED as MZ_DEFLATED; + pub use libz::Z_FINISH as MZ_FINISH; + pub use libz::Z_FULL_FLUSH as MZ_FULL_FLUSH; + pub use libz::Z_NEED_DICT as MZ_NEED_DICT; + pub use libz::Z_NO_FLUSH as MZ_NO_FLUSH; + pub use libz::Z_OK as MZ_OK; + pub use libz::Z_PARTIAL_FLUSH as MZ_PARTIAL_FLUSH; + pub use libz::Z_STREAM_END as MZ_STREAM_END; + pub use libz::Z_STREAM_ERROR as MZ_STREAM_ERROR; + pub use libz::Z_SYNC_FLUSH as MZ_SYNC_FLUSH; + pub type AllocSize = libz::uInt; + + pub const MZ_DEFAULT_WINDOW_BITS: c_int = 15; + + #[cfg(feature = "zlib-ng")] + const ZLIB_VERSION: &'static str = "2.1.0.devel\0"; + #[cfg(not(feature = "zlib-ng"))] + const ZLIB_VERSION: &'static str = "1.2.8\0"; + + pub unsafe extern "C" fn mz_deflateInit2( + stream: *mut mz_stream, + level: c_int, + method: c_int, + window_bits: c_int, + mem_level: c_int, + strategy: c_int, + ) -> c_int { + libz::deflateInit2_( + stream, + level, + method, + window_bits, + mem_level, + strategy, + ZLIB_VERSION.as_ptr() as *const c_char, + mem::size_of::<mz_stream>() as c_int, + ) + } + pub unsafe extern "C" fn mz_inflateInit2(stream: *mut mz_stream, window_bits: c_int) -> c_int { + libz::inflateInit2_( + stream, + window_bits, + ZLIB_VERSION.as_ptr() as *const c_char, + mem::size_of::<mz_stream>() as c_int, + ) + } +} diff --git a/vendor/flate2/src/ffi/mod.rs b/vendor/flate2/src/ffi/mod.rs new file mode 100644 index 0000000..20b3cae --- /dev/null +++ b/vendor/flate2/src/ffi/mod.rs @@ -0,0 +1,52 @@ +//! This module contains backend-specific code. + +use crate::mem::{CompressError, DecompressError, FlushCompress, FlushDecompress, Status}; +use crate::Compression; + +/// Traits specifying the interface of the backends. +/// +/// Sync + Send are added as a condition to ensure they are available +/// for the frontend. +pub trait Backend: Sync + Send { + fn total_in(&self) -> u64; + fn total_out(&self) -> u64; +} + +pub trait InflateBackend: Backend { + fn make(zlib_header: bool, window_bits: u8) -> Self; + fn decompress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushDecompress, + ) -> Result<Status, DecompressError>; + fn reset(&mut self, zlib_header: bool); +} + +pub trait DeflateBackend: Backend { + fn make(level: Compression, zlib_header: bool, window_bits: u8) -> Self; + fn compress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushCompress, + ) -> Result<Status, CompressError>; + fn reset(&mut self); +} + +// Default to Rust implementation unless explicitly opted in to a different backend. +#[cfg(feature = "any_zlib")] +mod c; +#[cfg(feature = "any_zlib")] +pub use self::c::*; + +#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))] +mod rust; +#[cfg(all(not(feature = "any_zlib"), feature = "miniz_oxide"))] +pub use self::rust::*; + +impl std::fmt::Debug for ErrorMessage { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + self.get().fmt(f) + } +} diff --git a/vendor/flate2/src/ffi/rust.rs b/vendor/flate2/src/ffi/rust.rs new file mode 100644 index 0000000..bed6629 --- /dev/null +++ b/vendor/flate2/src/ffi/rust.rs @@ -0,0 +1,183 @@ +//! Implementation for `miniz_oxide` rust backend. + +use std::convert::TryInto; +use std::fmt; + +use miniz_oxide::deflate::core::CompressorOxide; +use miniz_oxide::inflate::stream::InflateState; +pub use miniz_oxide::*; + +pub const MZ_NO_FLUSH: isize = MZFlush::None as isize; +pub const MZ_PARTIAL_FLUSH: isize = MZFlush::Partial as isize; +pub const MZ_SYNC_FLUSH: isize = MZFlush::Sync as isize; +pub const MZ_FULL_FLUSH: isize = MZFlush::Full as isize; +pub const MZ_FINISH: isize = MZFlush::Finish as isize; + +use super::*; +use crate::mem; + +// miniz_oxide doesn't provide any error messages (yet?) +#[derive(Default)] +pub struct ErrorMessage; + +impl ErrorMessage { + pub fn get(&self) -> Option<&str> { + None + } +} + +fn format_from_bool(zlib_header: bool) -> DataFormat { + if zlib_header { + DataFormat::Zlib + } else { + DataFormat::Raw + } +} + +pub struct Inflate { + inner: Box<InflateState>, + total_in: u64, + total_out: u64, +} + +impl fmt::Debug for Inflate { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "miniz_oxide inflate internal state. total_in: {}, total_out: {}", + self.total_in, self.total_out, + ) + } +} + +impl InflateBackend for Inflate { + fn make(zlib_header: bool, _window_bits: u8) -> Self { + let format = format_from_bool(zlib_header); + + Inflate { + inner: InflateState::new_boxed(format), + total_in: 0, + total_out: 0, + } + } + + fn decompress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushDecompress, + ) -> Result<Status, DecompressError> { + let flush = MZFlush::new(flush as i32).unwrap(); + + let res = inflate::stream::inflate(&mut self.inner, input, output, flush); + self.total_in += res.bytes_consumed as u64; + self.total_out += res.bytes_written as u64; + + match res.status { + Ok(status) => match status { + MZStatus::Ok => Ok(Status::Ok), + MZStatus::StreamEnd => Ok(Status::StreamEnd), + MZStatus::NeedDict => { + mem::decompress_need_dict(self.inner.decompressor().adler32().unwrap_or(0)) + } + }, + Err(status) => match status { + MZError::Buf => Ok(Status::BufError), + _ => mem::decompress_failed(ErrorMessage), + }, + } + } + + fn reset(&mut self, zlib_header: bool) { + self.inner.reset(format_from_bool(zlib_header)); + self.total_in = 0; + self.total_out = 0; + } +} + +impl Backend for Inflate { + #[inline] + fn total_in(&self) -> u64 { + self.total_in + } + + #[inline] + fn total_out(&self) -> u64 { + self.total_out + } +} + +pub struct Deflate { + inner: Box<CompressorOxide>, + total_in: u64, + total_out: u64, +} + +impl fmt::Debug for Deflate { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + f, + "miniz_oxide deflate internal state. total_in: {}, total_out: {}", + self.total_in, self.total_out, + ) + } +} + +impl DeflateBackend for Deflate { + fn make(level: Compression, zlib_header: bool, _window_bits: u8) -> Self { + // Check in case the integer value changes at some point. + debug_assert!(level.level() <= 10); + + let mut inner: Box<CompressorOxide> = Box::default(); + let format = format_from_bool(zlib_header); + inner.set_format_and_level(format, level.level().try_into().unwrap_or(1)); + + Deflate { + inner, + total_in: 0, + total_out: 0, + } + } + + fn compress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushCompress, + ) -> Result<Status, CompressError> { + let flush = MZFlush::new(flush as i32).unwrap(); + let res = deflate::stream::deflate(&mut self.inner, input, output, flush); + self.total_in += res.bytes_consumed as u64; + self.total_out += res.bytes_written as u64; + + match res.status { + Ok(status) => match status { + MZStatus::Ok => Ok(Status::Ok), + MZStatus::StreamEnd => Ok(Status::StreamEnd), + MZStatus::NeedDict => mem::compress_failed(ErrorMessage), + }, + Err(status) => match status { + MZError::Buf => Ok(Status::BufError), + _ => mem::compress_failed(ErrorMessage), + }, + } + } + + fn reset(&mut self) { + self.total_in = 0; + self.total_out = 0; + self.inner.reset(); + } +} + +impl Backend for Deflate { + #[inline] + fn total_in(&self) -> u64 { + self.total_in + } + + #[inline] + fn total_out(&self) -> u64 { + self.total_out + } +} diff --git a/vendor/flate2/src/gz/bufread.rs b/vendor/flate2/src/gz/bufread.rs new file mode 100644 index 0000000..679b4a7 --- /dev/null +++ b/vendor/flate2/src/gz/bufread.rs @@ -0,0 +1,483 @@ +use std::cmp; +use std::io; +use std::io::prelude::*; +use std::mem; + +use super::{corrupt, read_into, GzBuilder, GzHeader, GzHeaderParser}; +use crate::crc::CrcReader; +use crate::deflate; +use crate::Compression; + +fn copy(into: &mut [u8], from: &[u8], pos: &mut usize) -> usize { + let min = cmp::min(into.len(), from.len() - *pos); + for (slot, val) in into.iter_mut().zip(from[*pos..*pos + min].iter()) { + *slot = *val; + } + *pos += min; + min +} + +/// A gzip streaming encoder +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// uncompressed data from the underlying [`BufRead`] and provides the compressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// use flate2::Compression; +/// use flate2::bufread::GzEncoder; +/// use std::fs::File; +/// use std::io::BufReader; +/// +/// // Opens sample file, compresses the contents and returns a Vector or error +/// // File wrapped in a BufReader implements BufRead +/// +/// fn open_hello_world() -> io::Result<Vec<u8>> { +/// let f = File::open("examples/hello_world.txt")?; +/// let b = BufReader::new(f); +/// let mut gz = GzEncoder::new(b, Compression::fast()); +/// let mut buffer = Vec::new(); +/// gz.read_to_end(&mut buffer)?; +/// Ok(buffer) +/// } +/// ``` +#[derive(Debug)] +pub struct GzEncoder<R> { + inner: deflate::bufread::DeflateEncoder<CrcReader<R>>, + header: Vec<u8>, + pos: usize, + eof: bool, +} + +pub fn gz_encoder<R: BufRead>(header: Vec<u8>, r: R, lvl: Compression) -> GzEncoder<R> { + let crc = CrcReader::new(r); + GzEncoder { + inner: deflate::bufread::DeflateEncoder::new(crc, lvl), + header, + pos: 0, + eof: false, + } +} + +impl<R: BufRead> GzEncoder<R> { + /// Creates a new encoder which will use the given compression level. + /// + /// The encoder is not configured specially for the emitted header. For + /// header configuration, see the `GzBuilder` type. + /// + /// The data read from the stream `r` will be compressed and available + /// through the returned reader. + pub fn new(r: R, level: Compression) -> GzEncoder<R> { + GzBuilder::new().buf_read(r, level) + } + + fn read_footer(&mut self, into: &mut [u8]) -> io::Result<usize> { + if self.pos == 8 { + return Ok(0); + } + let crc = self.inner.get_ref().crc(); + let ref arr = [ + (crc.sum() >> 0) as u8, + (crc.sum() >> 8) as u8, + (crc.sum() >> 16) as u8, + (crc.sum() >> 24) as u8, + (crc.amount() >> 0) as u8, + (crc.amount() >> 8) as u8, + (crc.amount() >> 16) as u8, + (crc.amount() >> 24) as u8, + ]; + Ok(copy(into, arr, &mut self.pos)) + } +} + +impl<R> GzEncoder<R> { + /// Acquires a reference to the underlying reader. + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying reader. + /// + /// Note that mutation of the reader may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Returns the underlying stream, consuming this encoder + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } +} + +#[inline] +fn finish(buf: &[u8; 8]) -> (u32, u32) { + let crc = ((buf[0] as u32) << 0) + | ((buf[1] as u32) << 8) + | ((buf[2] as u32) << 16) + | ((buf[3] as u32) << 24); + let amt = ((buf[4] as u32) << 0) + | ((buf[5] as u32) << 8) + | ((buf[6] as u32) << 16) + | ((buf[7] as u32) << 24); + (crc, amt) +} + +impl<R: BufRead> Read for GzEncoder<R> { + fn read(&mut self, mut into: &mut [u8]) -> io::Result<usize> { + let mut amt = 0; + if self.eof { + return self.read_footer(into); + } else if self.pos < self.header.len() { + amt += copy(into, &self.header, &mut self.pos); + if amt == into.len() { + return Ok(amt); + } + let tmp = into; + into = &mut tmp[amt..]; + } + match self.inner.read(into)? { + 0 => { + self.eof = true; + self.pos = 0; + self.read_footer(into) + } + n => Ok(amt + n), + } + } +} + +impl<R: BufRead + Write> Write for GzEncoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A decoder for a single member of a [gzip file]. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`BufRead`] and provides the uncompressed data. +/// +/// After reading a single member of the gzip data this reader will return +/// Ok(0) even if there are more bytes available in the underlying reader. +/// If you need the following bytes, call `into_inner()` after Ok(0) to +/// recover the underlying reader. +/// +/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`] +/// or read more +/// [in the introduction](../index.html#about-multi-member-gzip-files). +/// +/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5 +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::GzEncoder; +/// use flate2::bufread::GzDecoder; +/// +/// # fn main() { +/// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements BufRead +/// +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut gz = GzDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// gz.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct GzDecoder<R> { + state: GzState, + reader: CrcReader<deflate::bufread::DeflateDecoder<R>>, + multi: bool, +} + +#[derive(Debug)] +enum GzState { + Header(GzHeaderParser), + Body(GzHeader), + Finished(GzHeader, usize, [u8; 8]), + Err(io::Error), + End(Option<GzHeader>), +} + +impl<R: BufRead> GzDecoder<R> { + /// Creates a new decoder from the given reader, immediately parsing the + /// gzip header. + pub fn new(mut r: R) -> GzDecoder<R> { + let mut header_parser = GzHeaderParser::new(); + + let state = match header_parser.parse(&mut r) { + Ok(_) => GzState::Body(GzHeader::from(header_parser)), + Err(ref err) if io::ErrorKind::WouldBlock == err.kind() => { + GzState::Header(header_parser) + } + Err(err) => GzState::Err(err), + }; + + GzDecoder { + state, + reader: CrcReader::new(deflate::bufread::DeflateDecoder::new(r)), + multi: false, + } + } + + fn multi(mut self, flag: bool) -> GzDecoder<R> { + self.multi = flag; + self + } +} + +impl<R> GzDecoder<R> { + /// Returns the header associated with this stream, if it was valid + pub fn header(&self) -> Option<&GzHeader> { + match &self.state { + GzState::Body(header) | GzState::Finished(header, _, _) => Some(header), + GzState::End(header) => header.as_ref(), + _ => None, + } + } + + /// Acquires a reference to the underlying reader. + pub fn get_ref(&self) -> &R { + self.reader.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream. + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.reader.get_mut().get_mut() + } + + /// Consumes this decoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.reader.into_inner().into_inner() + } +} + +impl<R: BufRead> Read for GzDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + loop { + match &mut self.state { + GzState::Header(parser) => { + parser.parse(self.reader.get_mut().get_mut())?; + self.state = GzState::Body(GzHeader::from(mem::take(parser))); + } + GzState::Body(header) => { + if into.is_empty() { + return Ok(0); + } + match self.reader.read(into)? { + 0 => { + self.state = GzState::Finished(mem::take(header), 0, [0; 8]); + } + n => { + return Ok(n); + } + } + } + GzState::Finished(header, pos, buf) => { + if *pos < buf.len() { + *pos += read_into(self.reader.get_mut().get_mut(), &mut buf[*pos..])?; + } else { + let (crc, amt) = finish(&buf); + + if crc != self.reader.crc().sum() || amt != self.reader.crc().amount() { + self.state = GzState::End(Some(mem::take(header))); + return Err(corrupt()); + } else if self.multi { + let is_eof = self + .reader + .get_mut() + .get_mut() + .fill_buf() + .map(|buf| buf.is_empty())?; + + if is_eof { + self.state = GzState::End(Some(mem::take(header))); + } else { + self.reader.reset(); + self.reader.get_mut().reset_data(); + self.state = GzState::Header(GzHeaderParser::new()) + } + } else { + self.state = GzState::End(Some(mem::take(header))); + } + } + } + GzState::Err(err) => { + let result = Err(mem::replace(err, io::ErrorKind::Other.into())); + self.state = GzState::End(None); + return result; + } + GzState::End(_) => return Ok(0), + } + } + } +} + +impl<R: BufRead + Write> Write for GzDecoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A gzip streaming decoder that decodes a [gzip file] that may have multiple members. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`BufRead`] and provides the uncompressed data. +/// +/// A gzip file consists of a series of *members* concatenated one after another. +/// MultiGzDecoder decodes all members from the data and only returns Ok(0) when the +/// underlying reader does. For a file, this reads to the end of the file. +/// +/// To handle members seperately, see [GzDecoder] or read more +/// [in the introduction](../index.html#about-multi-member-gzip-files). +/// +/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5 +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::GzEncoder; +/// use flate2::bufread::MultiGzDecoder; +/// +/// # fn main() { +/// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements BufRead +/// +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut gz = MultiGzDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// gz.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct MultiGzDecoder<R>(GzDecoder<R>); + +impl<R: BufRead> MultiGzDecoder<R> { + /// Creates a new decoder from the given reader, immediately parsing the + /// (first) gzip header. If the gzip stream contains multiple members all will + /// be decoded. + pub fn new(r: R) -> MultiGzDecoder<R> { + MultiGzDecoder(GzDecoder::new(r).multi(true)) + } +} + +impl<R> MultiGzDecoder<R> { + /// Returns the current header associated with this stream, if it's valid + pub fn header(&self) -> Option<&GzHeader> { + self.0.header() + } + + /// Acquires a reference to the underlying reader. + pub fn get_ref(&self) -> &R { + self.0.get_ref() + } + + /// Acquires a mutable reference to the underlying stream. + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.0.get_mut() + } + + /// Consumes this decoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.0.into_inner() + } +} + +impl<R: BufRead> Read for MultiGzDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + self.0.read(into) + } +} + +#[cfg(test)] +mod test { + use crate::bufread::GzDecoder; + use crate::gz::write; + use crate::Compression; + use std::io::{Read, Write}; + + // GzDecoder consumes one gzip member and then returns 0 for subsequent reads, allowing any + // additional data to be consumed by the caller. + #[test] + fn decode_extra_data() { + let expected = "Hello World"; + + let compressed = { + let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); + e.write(expected.as_ref()).unwrap(); + let mut b = e.finish().unwrap(); + b.push(b'x'); + b + }; + + let mut output = Vec::new(); + let mut decoder = GzDecoder::new(compressed.as_slice()); + let decoded_bytes = decoder.read_to_end(&mut output).unwrap(); + assert_eq!(decoded_bytes, output.len()); + let actual = std::str::from_utf8(&output).expect("String parsing error"); + assert_eq!( + actual, expected, + "after decompression we obtain the original input" + ); + + output.clear(); + assert_eq!( + decoder.read(&mut output).unwrap(), + 0, + "subsequent read of decoder returns 0, but inner reader can return additional data" + ); + let mut reader = decoder.into_inner(); + assert_eq!( + reader.read_to_end(&mut output).unwrap(), + 1, + "extra data is accessible in underlying buf-read" + ); + assert_eq!(output, b"x"); + } +} diff --git a/vendor/flate2/src/gz/mod.rs b/vendor/flate2/src/gz/mod.rs new file mode 100644 index 0000000..31a6961 --- /dev/null +++ b/vendor/flate2/src/gz/mod.rs @@ -0,0 +1,644 @@ +use std::ffi::CString; +use std::io::{BufRead, Error, ErrorKind, Read, Result, Write}; +use std::time; + +use crate::bufreader::BufReader; +use crate::{Compression, Crc}; + +pub static FHCRC: u8 = 1 << 1; +pub static FEXTRA: u8 = 1 << 2; +pub static FNAME: u8 = 1 << 3; +pub static FCOMMENT: u8 = 1 << 4; +pub static FRESERVED: u8 = 1 << 5 | 1 << 6 | 1 << 7; + +pub mod bufread; +pub mod read; +pub mod write; + +// The maximum length of the header filename and comment fields. More than +// enough for these fields in reasonable use, but prevents possible attacks. +const MAX_HEADER_BUF: usize = 65535; + +/// A structure representing the header of a gzip stream. +/// +/// The header can contain metadata about the file that was compressed, if +/// present. +#[derive(PartialEq, Clone, Debug, Default)] +pub struct GzHeader { + extra: Option<Vec<u8>>, + filename: Option<Vec<u8>>, + comment: Option<Vec<u8>>, + operating_system: u8, + mtime: u32, +} + +impl GzHeader { + /// Returns the `filename` field of this gzip stream's header, if present. + pub fn filename(&self) -> Option<&[u8]> { + self.filename.as_ref().map(|s| &s[..]) + } + + /// Returns the `extra` field of this gzip stream's header, if present. + pub fn extra(&self) -> Option<&[u8]> { + self.extra.as_ref().map(|s| &s[..]) + } + + /// Returns the `comment` field of this gzip stream's header, if present. + pub fn comment(&self) -> Option<&[u8]> { + self.comment.as_ref().map(|s| &s[..]) + } + + /// Returns the `operating_system` field of this gzip stream's header. + /// + /// There are predefined values for various operating systems. + /// 255 means that the value is unknown. + pub fn operating_system(&self) -> u8 { + self.operating_system + } + + /// This gives the most recent modification time of the original file being compressed. + /// + /// The time is in Unix format, i.e., seconds since 00:00:00 GMT, Jan. 1, 1970. + /// (Note that this may cause problems for MS-DOS and other systems that use local + /// rather than Universal time.) If the compressed data did not come from a file, + /// `mtime` is set to the time at which compression started. + /// `mtime` = 0 means no time stamp is available. + /// + /// The usage of `mtime` is discouraged because of Year 2038 problem. + pub fn mtime(&self) -> u32 { + self.mtime + } + + /// Returns the most recent modification time represented by a date-time type. + /// Returns `None` if the value of the underlying counter is 0, + /// indicating no time stamp is available. + /// + /// + /// The time is measured as seconds since 00:00:00 GMT, Jan. 1 1970. + /// See [`mtime`](#method.mtime) for more detail. + pub fn mtime_as_datetime(&self) -> Option<time::SystemTime> { + if self.mtime == 0 { + None + } else { + let duration = time::Duration::new(u64::from(self.mtime), 0); + let datetime = time::UNIX_EPOCH + duration; + Some(datetime) + } + } +} + +#[derive(Debug)] +pub enum GzHeaderState { + Start(u8, [u8; 10]), + Xlen(Option<Box<Crc>>, u8, [u8; 2]), + Extra(Option<Box<Crc>>, u16), + Filename(Option<Box<Crc>>), + Comment(Option<Box<Crc>>), + Crc(Option<Box<Crc>>, u8, [u8; 2]), + Complete, +} + +impl Default for GzHeaderState { + fn default() -> Self { + Self::Complete + } +} + +#[derive(Debug, Default)] +pub struct GzHeaderParser { + state: GzHeaderState, + flags: u8, + header: GzHeader, +} + +impl GzHeaderParser { + fn new() -> Self { + GzHeaderParser { + state: GzHeaderState::Start(0, [0; 10]), + flags: 0, + header: GzHeader::default(), + } + } + + fn parse<'a, R: Read>(&mut self, r: &'a mut R) -> Result<()> { + loop { + match &mut self.state { + GzHeaderState::Start(count, buffer) => { + while (*count as usize) < buffer.len() { + *count += read_into(r, &mut buffer[*count as usize..])? as u8; + } + // Gzip identification bytes + if buffer[0] != 0x1f || buffer[1] != 0x8b { + return Err(bad_header()); + } + // Gzip compression method (8 = deflate) + if buffer[2] != 8 { + return Err(bad_header()); + } + self.flags = buffer[3]; + // RFC1952: "must give an error indication if any reserved bit is non-zero" + if self.flags & FRESERVED != 0 { + return Err(bad_header()); + } + self.header.mtime = ((buffer[4] as u32) << 0) + | ((buffer[5] as u32) << 8) + | ((buffer[6] as u32) << 16) + | ((buffer[7] as u32) << 24); + let _xfl = buffer[8]; + self.header.operating_system = buffer[9]; + let crc = if self.flags & FHCRC != 0 { + let mut crc = Box::new(Crc::new()); + crc.update(buffer); + Some(crc) + } else { + None + }; + self.state = GzHeaderState::Xlen(crc, 0, [0; 2]); + } + GzHeaderState::Xlen(crc, count, buffer) => { + if self.flags & FEXTRA != 0 { + while (*count as usize) < buffer.len() { + *count += read_into(r, &mut buffer[*count as usize..])? as u8; + } + if let Some(crc) = crc { + crc.update(buffer); + } + let xlen = parse_le_u16(&buffer); + self.header.extra = Some(vec![0; xlen as usize]); + self.state = GzHeaderState::Extra(crc.take(), 0); + } else { + self.state = GzHeaderState::Filename(crc.take()); + } + } + GzHeaderState::Extra(crc, count) => { + debug_assert!(self.header.extra.is_some()); + let extra = self.header.extra.as_mut().unwrap(); + while (*count as usize) < extra.len() { + *count += read_into(r, &mut extra[*count as usize..])? as u16; + } + if let Some(crc) = crc { + crc.update(extra); + } + self.state = GzHeaderState::Filename(crc.take()); + } + GzHeaderState::Filename(crc) => { + if self.flags & FNAME != 0 { + let filename = self.header.filename.get_or_insert_with(Vec::new); + read_to_nul(r, filename)?; + if let Some(crc) = crc { + crc.update(filename); + crc.update(b"\0"); + } + } + self.state = GzHeaderState::Comment(crc.take()); + } + GzHeaderState::Comment(crc) => { + if self.flags & FCOMMENT != 0 { + let comment = self.header.comment.get_or_insert_with(Vec::new); + read_to_nul(r, comment)?; + if let Some(crc) = crc { + crc.update(comment); + crc.update(b"\0"); + } + } + self.state = GzHeaderState::Crc(crc.take(), 0, [0; 2]); + } + GzHeaderState::Crc(crc, count, buffer) => { + if let Some(crc) = crc { + debug_assert!(self.flags & FHCRC != 0); + while (*count as usize) < buffer.len() { + *count += read_into(r, &mut buffer[*count as usize..])? as u8; + } + let stored_crc = parse_le_u16(&buffer); + let calced_crc = crc.sum() as u16; + if stored_crc != calced_crc { + return Err(corrupt()); + } + } + self.state = GzHeaderState::Complete; + } + GzHeaderState::Complete => { + return Ok(()); + } + } + } + } + + fn header(&self) -> Option<&GzHeader> { + match self.state { + GzHeaderState::Complete => Some(&self.header), + _ => None, + } + } +} + +impl From<GzHeaderParser> for GzHeader { + fn from(parser: GzHeaderParser) -> Self { + debug_assert!(matches!(parser.state, GzHeaderState::Complete)); + parser.header + } +} + +// Attempt to fill the `buffer` from `r`. Return the number of bytes read. +// Return an error if EOF is read before the buffer is full. This differs +// from `read` in that Ok(0) means that more data may be available. +fn read_into<R: Read>(r: &mut R, buffer: &mut [u8]) -> Result<usize> { + debug_assert!(!buffer.is_empty()); + match r.read(buffer) { + Ok(0) => Err(ErrorKind::UnexpectedEof.into()), + Ok(n) => Ok(n), + Err(ref e) if e.kind() == ErrorKind::Interrupted => Ok(0), + Err(e) => Err(e), + } +} + +// Read `r` up to the first nul byte, pushing non-nul bytes to `buffer`. +fn read_to_nul<R: Read>(r: &mut R, buffer: &mut Vec<u8>) -> Result<()> { + let mut bytes = r.bytes(); + loop { + match bytes.next().transpose()? { + Some(byte) if byte == 0 => { + return Ok(()); + } + Some(_) if buffer.len() == MAX_HEADER_BUF => { + return Err(Error::new( + ErrorKind::InvalidInput, + "gzip header field too long", + )); + } + Some(byte) => { + buffer.push(byte); + } + None => { + return Err(ErrorKind::UnexpectedEof.into()); + } + } + } +} + +fn parse_le_u16(buffer: &[u8; 2]) -> u16 { + (buffer[0] as u16) | ((buffer[1] as u16) << 8) +} + +fn bad_header() -> Error { + Error::new(ErrorKind::InvalidInput, "invalid gzip header") +} + +fn corrupt() -> Error { + Error::new( + ErrorKind::InvalidInput, + "corrupt gzip stream does not have a matching checksum", + ) +} + +/// A builder structure to create a new gzip Encoder. +/// +/// This structure controls header configuration options such as the filename. +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// # use std::io; +/// use std::fs::File; +/// use flate2::GzBuilder; +/// use flate2::Compression; +/// +/// // GzBuilder opens a file and writes a sample string using GzBuilder pattern +/// +/// # fn sample_builder() -> Result<(), io::Error> { +/// let f = File::create("examples/hello_world.gz")?; +/// let mut gz = GzBuilder::new() +/// .filename("hello_world.txt") +/// .comment("test file, please delete") +/// .write(f, Compression::default()); +/// gz.write_all(b"hello world")?; +/// gz.finish()?; +/// # Ok(()) +/// # } +/// ``` +#[derive(Debug)] +pub struct GzBuilder { + extra: Option<Vec<u8>>, + filename: Option<CString>, + comment: Option<CString>, + operating_system: Option<u8>, + mtime: u32, +} + +impl Default for GzBuilder { + fn default() -> Self { + Self::new() + } +} + +impl GzBuilder { + /// Create a new blank builder with no header by default. + pub fn new() -> GzBuilder { + GzBuilder { + extra: None, + filename: None, + comment: None, + operating_system: None, + mtime: 0, + } + } + + /// Configure the `mtime` field in the gzip header. + pub fn mtime(mut self, mtime: u32) -> GzBuilder { + self.mtime = mtime; + self + } + + /// Configure the `operating_system` field in the gzip header. + pub fn operating_system(mut self, os: u8) -> GzBuilder { + self.operating_system = Some(os); + self + } + + /// Configure the `extra` field in the gzip header. + pub fn extra<T: Into<Vec<u8>>>(mut self, extra: T) -> GzBuilder { + self.extra = Some(extra.into()); + self + } + + /// Configure the `filename` field in the gzip header. + /// + /// # Panics + /// + /// Panics if the `filename` slice contains a zero. + pub fn filename<T: Into<Vec<u8>>>(mut self, filename: T) -> GzBuilder { + self.filename = Some(CString::new(filename.into()).unwrap()); + self + } + + /// Configure the `comment` field in the gzip header. + /// + /// # Panics + /// + /// Panics if the `comment` slice contains a zero. + pub fn comment<T: Into<Vec<u8>>>(mut self, comment: T) -> GzBuilder { + self.comment = Some(CString::new(comment.into()).unwrap()); + self + } + + /// Consume this builder, creating a writer encoder in the process. + /// + /// The data written to the returned encoder will be compressed and then + /// written out to the supplied parameter `w`. + pub fn write<W: Write>(self, w: W, lvl: Compression) -> write::GzEncoder<W> { + write::gz_encoder(self.into_header(lvl), w, lvl) + } + + /// Consume this builder, creating a reader encoder in the process. + /// + /// Data read from the returned encoder will be the compressed version of + /// the data read from the given reader. + pub fn read<R: Read>(self, r: R, lvl: Compression) -> read::GzEncoder<R> { + read::gz_encoder(self.buf_read(BufReader::new(r), lvl)) + } + + /// Consume this builder, creating a reader encoder in the process. + /// + /// Data read from the returned encoder will be the compressed version of + /// the data read from the given reader. + pub fn buf_read<R>(self, r: R, lvl: Compression) -> bufread::GzEncoder<R> + where + R: BufRead, + { + bufread::gz_encoder(self.into_header(lvl), r, lvl) + } + + fn into_header(self, lvl: Compression) -> Vec<u8> { + let GzBuilder { + extra, + filename, + comment, + operating_system, + mtime, + } = self; + let mut flg = 0; + let mut header = vec![0u8; 10]; + if let Some(v) = extra { + flg |= FEXTRA; + header.push((v.len() >> 0) as u8); + header.push((v.len() >> 8) as u8); + header.extend(v); + } + if let Some(filename) = filename { + flg |= FNAME; + header.extend(filename.as_bytes_with_nul().iter().copied()); + } + if let Some(comment) = comment { + flg |= FCOMMENT; + header.extend(comment.as_bytes_with_nul().iter().copied()); + } + header[0] = 0x1f; + header[1] = 0x8b; + header[2] = 8; + header[3] = flg; + header[4] = (mtime >> 0) as u8; + header[5] = (mtime >> 8) as u8; + header[6] = (mtime >> 16) as u8; + header[7] = (mtime >> 24) as u8; + header[8] = if lvl.0 >= Compression::best().0 { + 2 + } else if lvl.0 <= Compression::fast().0 { + 4 + } else { + 0 + }; + + // Typically this byte indicates what OS the gz stream was created on, + // but in an effort to have cross-platform reproducible streams just + // default this value to 255. I'm not sure that if we "correctly" set + // this it'd do anything anyway... + header[9] = operating_system.unwrap_or(255); + header + } +} + +#[cfg(test)] +mod tests { + use std::io::prelude::*; + + use super::{read, write, GzBuilder, GzHeaderParser}; + use crate::{Compression, GzHeader}; + use rand::{thread_rng, Rng}; + + #[test] + fn roundtrip() { + let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); + e.write_all(b"foo bar baz").unwrap(); + let inner = e.finish().unwrap(); + let mut d = read::GzDecoder::new(&inner[..]); + let mut s = String::new(); + d.read_to_string(&mut s).unwrap(); + assert_eq!(s, "foo bar baz"); + } + + #[test] + fn roundtrip_zero() { + let e = write::GzEncoder::new(Vec::new(), Compression::default()); + let inner = e.finish().unwrap(); + let mut d = read::GzDecoder::new(&inner[..]); + let mut s = String::new(); + d.read_to_string(&mut s).unwrap(); + assert_eq!(s, ""); + } + + #[test] + fn roundtrip_big() { + let mut real = Vec::new(); + let mut w = write::GzEncoder::new(Vec::new(), Compression::default()); + let v = crate::random_bytes().take(1024).collect::<Vec<_>>(); + for _ in 0..200 { + let to_write = &v[..thread_rng().gen_range(0..v.len())]; + real.extend(to_write.iter().copied()); + w.write_all(to_write).unwrap(); + } + let result = w.finish().unwrap(); + let mut r = read::GzDecoder::new(&result[..]); + let mut v = Vec::new(); + r.read_to_end(&mut v).unwrap(); + assert_eq!(v, real); + } + + #[test] + fn roundtrip_big2() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut r = read::GzDecoder::new(read::GzEncoder::new(&v[..], Compression::default())); + let mut res = Vec::new(); + r.read_to_end(&mut res).unwrap(); + assert_eq!(res, v); + } + + // A Rust implementation of CRC that closely matches the C code in RFC1952. + // Only use this to create CRCs for tests. + struct Rfc1952Crc { + /* Table of CRCs of all 8-bit messages. */ + crc_table: [u32; 256], + } + + impl Rfc1952Crc { + fn new() -> Self { + let mut crc = Rfc1952Crc { + crc_table: [0; 256], + }; + /* Make the table for a fast CRC. */ + for n in 0usize..256 { + let mut c = n as u32; + for _k in 0..8 { + if c & 1 != 0 { + c = 0xedb88320 ^ (c >> 1); + } else { + c = c >> 1; + } + } + crc.crc_table[n] = c; + } + crc + } + + /* + Update a running crc with the bytes buf and return + the updated crc. The crc should be initialized to zero. Pre- and + post-conditioning (one's complement) is performed within this + function so it shouldn't be done by the caller. + */ + fn update_crc(&self, crc: u32, buf: &[u8]) -> u32 { + let mut c = crc ^ 0xffffffff; + + for b in buf { + c = self.crc_table[(c as u8 ^ *b) as usize] ^ (c >> 8); + } + c ^ 0xffffffff + } + + /* Return the CRC of the bytes buf. */ + fn crc(&self, buf: &[u8]) -> u32 { + self.update_crc(0, buf) + } + } + + #[test] + fn roundtrip_header() { + let mut header = GzBuilder::new() + .mtime(1234) + .operating_system(57) + .filename("filename") + .comment("comment") + .into_header(Compression::fast()); + + // Add a CRC to the header + header[3] = header[3] ^ super::FHCRC; + let rfc1952_crc = Rfc1952Crc::new(); + let crc32 = rfc1952_crc.crc(&header); + let crc16 = crc32 as u16; + header.extend(&crc16.to_le_bytes()); + + let mut parser = GzHeaderParser::new(); + parser.parse(&mut header.as_slice()).unwrap(); + let actual = parser.header().unwrap(); + assert_eq!( + actual, + &GzHeader { + extra: None, + filename: Some("filename".as_bytes().to_vec()), + comment: Some("comment".as_bytes().to_vec()), + operating_system: 57, + mtime: 1234 + } + ) + } + + #[test] + fn fields() { + let r = vec![0, 2, 4, 6]; + let e = GzBuilder::new() + .filename("foo.rs") + .comment("bar") + .extra(vec![0, 1, 2, 3]) + .read(&r[..], Compression::default()); + let mut d = read::GzDecoder::new(e); + assert_eq!(d.header().unwrap().filename(), Some(&b"foo.rs"[..])); + assert_eq!(d.header().unwrap().comment(), Some(&b"bar"[..])); + assert_eq!(d.header().unwrap().extra(), Some(&b"\x00\x01\x02\x03"[..])); + let mut res = Vec::new(); + d.read_to_end(&mut res).unwrap(); + assert_eq!(res, vec![0, 2, 4, 6]); + } + + #[test] + fn keep_reading_after_end() { + let mut e = write::GzEncoder::new(Vec::new(), Compression::default()); + e.write_all(b"foo bar baz").unwrap(); + let inner = e.finish().unwrap(); + let mut d = read::GzDecoder::new(&inner[..]); + let mut s = String::new(); + d.read_to_string(&mut s).unwrap(); + assert_eq!(s, "foo bar baz"); + d.read_to_string(&mut s).unwrap(); + assert_eq!(s, "foo bar baz"); + } + + #[test] + fn qc_reader() { + ::quickcheck::quickcheck(test as fn(_) -> _); + + fn test(v: Vec<u8>) -> bool { + let r = read::GzEncoder::new(&v[..], Compression::default()); + let mut r = read::GzDecoder::new(r); + let mut v2 = Vec::new(); + r.read_to_end(&mut v2).unwrap(); + v == v2 + } + } + + #[test] + fn flush_after_write() { + let mut f = write::GzEncoder::new(Vec::new(), Compression::default()); + write!(f, "Hello world").unwrap(); + f.flush().unwrap(); + } +} diff --git a/vendor/flate2/src/gz/read.rs b/vendor/flate2/src/gz/read.rs new file mode 100644 index 0000000..9dbadbd --- /dev/null +++ b/vendor/flate2/src/gz/read.rs @@ -0,0 +1,378 @@ +use std::io; +use std::io::prelude::*; + +use super::bufread; +use super::{GzBuilder, GzHeader}; +use crate::bufreader::BufReader; +use crate::Compression; + +/// A gzip streaming encoder +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// uncompressed data from the underlying [`Read`] and provides the compressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// use flate2::Compression; +/// use flate2::read::GzEncoder; +/// +/// // Return a vector containing the GZ compressed version of hello world +/// +/// fn gzencode_hello_world() -> io::Result<Vec<u8>> { +/// let mut ret_vec = Vec::new(); +/// let bytestring = b"hello world"; +/// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast()); +/// gz.read_to_end(&mut ret_vec)?; +/// Ok(ret_vec) +/// } +/// ``` +#[derive(Debug)] +pub struct GzEncoder<R> { + inner: bufread::GzEncoder<BufReader<R>>, +} + +pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> { + GzEncoder { inner } +} + +impl<R: Read> GzEncoder<R> { + /// Creates a new encoder which will use the given compression level. + /// + /// The encoder is not configured specially for the emitted header. For + /// header configuration, see the `GzBuilder` type. + /// + /// The data read from the stream `r` will be compressed and available + /// through the returned reader. + pub fn new(r: R, level: Compression) -> GzEncoder<R> { + GzBuilder::new().read(r, level) + } +} + +impl<R> GzEncoder<R> { + /// Acquires a reference to the underlying reader. + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying reader. + /// + /// Note that mutation of the reader may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Returns the underlying stream, consuming this encoder + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } +} + +impl<R: Read> Read for GzEncoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + self.inner.read(into) + } +} + +impl<R: Read + Write> Write for GzEncoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A decoder for a single member of a [gzip file]. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`Read`] and provides the uncompressed data. +/// +/// After reading a single member of the gzip data this reader will return +/// Ok(0) even if there are more bytes available in the underlying reader. +/// `GzDecoder` may have read additional bytes past the end of the gzip data. +/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader` +/// and use `bufread::GzDecoder` instead. +/// +/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`] +/// or read more +/// [in the introduction](../index.html#about-multi-member-gzip-files). +/// +/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5 +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::GzEncoder; +/// use flate2::read::GzDecoder; +/// +/// # fn main() { +/// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements Read +/// +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut gz = GzDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// gz.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct GzDecoder<R> { + inner: bufread::GzDecoder<BufReader<R>>, +} + +impl<R: Read> GzDecoder<R> { + /// Creates a new decoder from the given reader, immediately parsing the + /// gzip header. + pub fn new(r: R) -> GzDecoder<R> { + GzDecoder { + inner: bufread::GzDecoder::new(BufReader::new(r)), + } + } +} + +impl<R> GzDecoder<R> { + /// Returns the header associated with this stream, if it was valid. + pub fn header(&self) -> Option<&GzHeader> { + self.inner.header() + } + + /// Acquires a reference to the underlying reader. + /// + /// Note that the decoder may have read past the end of the gzip data. + /// To prevent this use [`bufread::GzDecoder`] instead. + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream. + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder continues to be used. + /// + /// Note that the decoder may have read past the end of the gzip data. + /// To prevent this use [`bufread::GzDecoder`] instead. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Consumes this decoder, returning the underlying reader. + /// + /// Note that the decoder may have read past the end of the gzip data. + /// Subsequent reads will skip those bytes. To prevent this use + /// [`bufread::GzDecoder`] instead. + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } +} + +impl<R: Read> Read for GzDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + self.inner.read(into) + } +} + +impl<R: Read + Write> Write for GzDecoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A gzip streaming decoder that decodes a [gzip file] that may have multiple members. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`Read`] and provides the uncompressed +/// data. +/// +/// A gzip file consists of a series of *members* concatenated one after another. +/// MultiGzDecoder decodes all members of a file and returns Ok(0) once the +/// underlying reader does. +/// +/// To handle members seperately, see [GzDecoder] or read more +/// [in the introduction](../index.html#about-multi-member-gzip-files). +/// +/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5 +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::GzEncoder; +/// use flate2::read::MultiGzDecoder; +/// +/// # fn main() { +/// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements Read +/// +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut gz = MultiGzDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// gz.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct MultiGzDecoder<R> { + inner: bufread::MultiGzDecoder<BufReader<R>>, +} + +impl<R: Read> MultiGzDecoder<R> { + /// Creates a new decoder from the given reader, immediately parsing the + /// (first) gzip header. If the gzip stream contains multiple members all will + /// be decoded. + pub fn new(r: R) -> MultiGzDecoder<R> { + MultiGzDecoder { + inner: bufread::MultiGzDecoder::new(BufReader::new(r)), + } + } +} + +impl<R> MultiGzDecoder<R> { + /// Returns the current header associated with this stream, if it's valid. + pub fn header(&self) -> Option<&GzHeader> { + self.inner.header() + } + + /// Acquires a reference to the underlying reader. + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream. + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Consumes this decoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } +} + +impl<R: Read> Read for MultiGzDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + self.inner.read(into) + } +} + +impl<R: Read + Write> Write for MultiGzDecoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +#[cfg(test)] +mod tests { + use std::io::{Cursor, ErrorKind, Read, Result, Write}; + + use super::GzDecoder; + + //a cursor turning EOF into blocking errors + #[derive(Debug)] + pub struct BlockingCursor { + pub cursor: Cursor<Vec<u8>>, + } + + impl BlockingCursor { + pub fn new() -> BlockingCursor { + BlockingCursor { + cursor: Cursor::new(Vec::new()), + } + } + + pub fn set_position(&mut self, pos: u64) { + return self.cursor.set_position(pos); + } + } + + impl Write for BlockingCursor { + fn write(&mut self, buf: &[u8]) -> Result<usize> { + return self.cursor.write(buf); + } + fn flush(&mut self) -> Result<()> { + return self.cursor.flush(); + } + } + + impl Read for BlockingCursor { + fn read(&mut self, buf: &mut [u8]) -> Result<usize> { + //use the cursor, except it turns eof into blocking error + let r = self.cursor.read(buf); + match r { + Err(ref err) => { + if err.kind() == ErrorKind::UnexpectedEof { + return Err(ErrorKind::WouldBlock.into()); + } + } + Ok(0) => { + //regular EOF turned into blocking error + return Err(ErrorKind::WouldBlock.into()); + } + Ok(_n) => {} + } + return r; + } + } + + #[test] + fn blocked_partial_header_read() { + // this is a reader which receives data afterwards + let mut r = BlockingCursor::new(); + let data = vec![1, 2, 3]; + + match r.write_all(&data) { + Ok(()) => {} + _ => { + panic!("Unexpected result for write_all"); + } + } + r.set_position(0); + + // this is unused except for the buffering + let mut decoder = GzDecoder::new(r); + let mut out = Vec::with_capacity(7); + match decoder.read(&mut out) { + Err(e) => { + assert_eq!(e.kind(), ErrorKind::WouldBlock); + } + _ => { + panic!("Unexpected result for decoder.read"); + } + } + } +} diff --git a/vendor/flate2/src/gz/write.rs b/vendor/flate2/src/gz/write.rs new file mode 100644 index 0000000..74d6c5a --- /dev/null +++ b/vendor/flate2/src/gz/write.rs @@ -0,0 +1,641 @@ +use std::cmp; +use std::io; +use std::io::prelude::*; + +use super::{corrupt, GzBuilder, GzHeader, GzHeaderParser}; +use crate::crc::{Crc, CrcWriter}; +use crate::zio; +use crate::{Compress, Compression, Decompress, Status}; + +/// A gzip streaming encoder +/// +/// This structure exposes a [`Write`] interface that will emit compressed data +/// to the underlying writer `W`. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use flate2::Compression; +/// use flate2::write::GzEncoder; +/// +/// // Vec<u8> implements Write to print the compressed bytes of sample string +/// # fn main() { +/// +/// let mut e = GzEncoder::new(Vec::new(), Compression::default()); +/// e.write_all(b"Hello World").unwrap(); +/// println!("{:?}", e.finish().unwrap()); +/// # } +/// ``` +#[derive(Debug)] +pub struct GzEncoder<W: Write> { + inner: zio::Writer<W, Compress>, + crc: Crc, + crc_bytes_written: usize, + header: Vec<u8>, +} + +pub fn gz_encoder<W: Write>(header: Vec<u8>, w: W, lvl: Compression) -> GzEncoder<W> { + GzEncoder { + inner: zio::Writer::new(w, Compress::new(lvl, false)), + crc: Crc::new(), + header, + crc_bytes_written: 0, + } +} + +impl<W: Write> GzEncoder<W> { + /// Creates a new encoder which will use the given compression level. + /// + /// The encoder is not configured specially for the emitted header. For + /// header configuration, see the `GzBuilder` type. + /// + /// The data written to the returned encoder will be compressed and then + /// written to the stream `w`. + pub fn new(w: W, level: Compression) -> GzEncoder<W> { + GzBuilder::new().write(w, level) + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutation of the writer may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn try_finish(&mut self) -> io::Result<()> { + self.write_header()?; + self.inner.finish()?; + + while self.crc_bytes_written < 8 { + let (sum, amt) = (self.crc.sum(), self.crc.amount()); + let buf = [ + (sum >> 0) as u8, + (sum >> 8) as u8, + (sum >> 16) as u8, + (sum >> 24) as u8, + (amt >> 0) as u8, + (amt >> 8) as u8, + (amt >> 16) as u8, + (amt >> 24) as u8, + ]; + let inner = self.inner.get_mut(); + let n = inner.write(&buf[self.crc_bytes_written..])?; + self.crc_bytes_written += n; + } + Ok(()) + } + + /// Finish encoding this stream, returning the underlying writer once the + /// encoding is done. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(mut self) -> io::Result<W> { + self.try_finish()?; + Ok(self.inner.take_inner()) + } + + fn write_header(&mut self) -> io::Result<()> { + while !self.header.is_empty() { + let n = self.inner.get_mut().write(&self.header)?; + self.header.drain(..n); + } + Ok(()) + } +} + +impl<W: Write> Write for GzEncoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + assert_eq!(self.crc_bytes_written, 0); + self.write_header()?; + let n = self.inner.write(buf)?; + self.crc.update(&buf[..n]); + Ok(n) + } + + fn flush(&mut self) -> io::Result<()> { + assert_eq!(self.crc_bytes_written, 0); + self.write_header()?; + self.inner.flush() + } +} + +impl<R: Read + Write> Read for GzEncoder<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.get_mut().read(buf) + } +} + +impl<W: Write> Drop for GzEncoder<W> { + fn drop(&mut self) { + if self.inner.is_present() { + let _ = self.try_finish(); + } + } +} + +/// A decoder for a single member of a [gzip file]. +/// +/// This structure exposes a [`Write`] interface, receiving compressed data and +/// writing uncompressed data to the underlying writer. +/// +/// After decoding a single member of the gzip data this writer will return the number of bytes up to +/// to the end of the gzip member and subsequent writes will return Ok(0) allowing the caller to +/// handle any data following the gzip member. +/// +/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`] +/// or read more +/// [in the introduction](../index.html#about-multi-member-gzip-files). +/// +/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5 +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// use flate2::Compression; +/// use flate2::write::{GzEncoder, GzDecoder}; +/// +/// # fn main() { +/// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); +/// # e.write(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # assert_eq!("Hello World", decode_writer(bytes).unwrap()); +/// # } +/// // Uncompresses a gzip encoded vector of bytes and returns a string or error +/// // Here Vec<u8> implements Write +/// fn decode_writer(bytes: Vec<u8>) -> io::Result<String> { +/// let mut writer = Vec::new(); +/// let mut decoder = GzDecoder::new(writer); +/// decoder.write_all(&bytes[..])?; +/// writer = decoder.finish()?; +/// let return_string = String::from_utf8(writer).expect("String parsing error"); +/// Ok(return_string) +/// } +/// ``` +#[derive(Debug)] +pub struct GzDecoder<W: Write> { + inner: zio::Writer<CrcWriter<W>, Decompress>, + crc_bytes: Vec<u8>, + header_parser: GzHeaderParser, +} + +const CRC_BYTES_LEN: usize = 8; + +impl<W: Write> GzDecoder<W> { + /// Creates a new decoder which will write uncompressed data to the stream. + /// + /// When this encoder is dropped or unwrapped the final pieces of data will + /// be flushed. + pub fn new(w: W) -> GzDecoder<W> { + GzDecoder { + inner: zio::Writer::new(CrcWriter::new(w), Decompress::new(false)), + crc_bytes: Vec::with_capacity(CRC_BYTES_LEN), + header_parser: GzHeaderParser::new(), + } + } + + /// Returns the header associated with this stream. + pub fn header(&self) -> Option<&GzHeader> { + self.header_parser.header() + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutating the output/input state of the stream may corrupt this + /// object, so care must be taken when using this method. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut().get_mut() + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to finish the stream, returning any + /// errors which happen. + pub fn try_finish(&mut self) -> io::Result<()> { + self.finish_and_check_crc()?; + Ok(()) + } + + /// Consumes this decoder, flushing the output stream. + /// + /// This will flush the underlying data stream and then return the contained + /// writer if the flush succeeded. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(mut self) -> io::Result<W> { + self.finish_and_check_crc()?; + Ok(self.inner.take_inner().into_inner()) + } + + fn finish_and_check_crc(&mut self) -> io::Result<()> { + self.inner.finish()?; + + if self.crc_bytes.len() != 8 { + return Err(corrupt()); + } + + let crc = ((self.crc_bytes[0] as u32) << 0) + | ((self.crc_bytes[1] as u32) << 8) + | ((self.crc_bytes[2] as u32) << 16) + | ((self.crc_bytes[3] as u32) << 24); + let amt = ((self.crc_bytes[4] as u32) << 0) + | ((self.crc_bytes[5] as u32) << 8) + | ((self.crc_bytes[6] as u32) << 16) + | ((self.crc_bytes[7] as u32) << 24); + if crc != self.inner.get_ref().crc().sum() { + return Err(corrupt()); + } + if amt != self.inner.get_ref().crc().amount() { + return Err(corrupt()); + } + Ok(()) + } +} + +impl<W: Write> Write for GzDecoder<W> { + fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> { + let buflen = buf.len(); + if self.header().is_none() { + match self.header_parser.parse(&mut buf) { + Err(err) => { + if err.kind() == io::ErrorKind::UnexpectedEof { + // all data read but header still not complete + Ok(buflen) + } else { + Err(err) + } + } + Ok(_) => { + debug_assert!(self.header().is_some()); + // buf now contains the unread part of the original buf + let n = buflen - buf.len(); + Ok(n) + } + } + } else { + let (n, status) = self.inner.write_with_status(buf)?; + + if status == Status::StreamEnd && n < buf.len() && self.crc_bytes.len() < 8 { + let remaining = buf.len() - n; + let crc_bytes = cmp::min(remaining, CRC_BYTES_LEN - self.crc_bytes.len()); + self.crc_bytes.extend(&buf[n..n + crc_bytes]); + return Ok(n + crc_bytes); + } + Ok(n) + } + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl<W: Read + Write> Read for GzDecoder<W> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.get_mut().get_mut().read(buf) + } +} + +/// A gzip streaming decoder that decodes a [gzip file] with multiple members. +/// +/// This structure exposes a [`Write`] interface that will consume compressed data and +/// write uncompressed data to the underlying writer. +/// +/// A gzip file consists of a series of *members* concatenated one after another. +/// `MultiGzDecoder` decodes all members of a file and writes them to the +/// underlying writer one after another. +/// +/// To handle members separately, see [GzDecoder] or read more +/// [in the introduction](../index.html#about-multi-member-gzip-files). +/// +/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5 +#[derive(Debug)] +pub struct MultiGzDecoder<W: Write> { + inner: GzDecoder<W>, +} + +impl<W: Write> MultiGzDecoder<W> { + /// Creates a new decoder which will write uncompressed data to the stream. + /// If the gzip stream contains multiple members all will be decoded. + pub fn new(w: W) -> MultiGzDecoder<W> { + MultiGzDecoder { + inner: GzDecoder::new(w), + } + } + + /// Returns the header associated with the current member. + pub fn header(&self) -> Option<&GzHeader> { + self.inner.header() + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutating the output/input state of the stream may corrupt this + /// object, so care must be taken when using this method. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to finish the stream, returning any + /// errors which happen. + pub fn try_finish(&mut self) -> io::Result<()> { + self.inner.try_finish() + } + + /// Consumes this decoder, flushing the output stream. + /// + /// This will flush the underlying data stream and then return the contained + /// writer if the flush succeeded. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(self) -> io::Result<W> { + self.inner.finish() + } +} + +impl<W: Write> Write for MultiGzDecoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + if buf.is_empty() { + Ok(0) + } else { + match self.inner.write(buf) { + Ok(0) => { + // When the GzDecoder indicates that it has finished + // create a new GzDecoder to handle additional data. + self.inner.try_finish()?; + let w = self.inner.inner.take_inner().into_inner(); + self.inner = GzDecoder::new(w); + self.inner.write(buf) + } + res => res, + } + } + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + const STR: &str = "Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World \ + Hello World Hello World Hello World Hello World Hello World"; + + #[test] + fn decode_writer_one_chunk() { + let mut e = GzEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let bytes = e.finish().unwrap(); + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + let n = decoder.write(&bytes[..]).unwrap(); + decoder.write(&bytes[n..]).unwrap(); + decoder.try_finish().unwrap(); + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(return_string, STR); + } + + #[test] + fn decode_writer_partial_header() { + let mut e = GzEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let bytes = e.finish().unwrap(); + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + assert_eq!(decoder.write(&bytes[..5]).unwrap(), 5); + let n = decoder.write(&bytes[5..]).unwrap(); + if n < bytes.len() - 5 { + decoder.write(&bytes[n + 5..]).unwrap(); + } + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(return_string, STR); + } + + #[test] + fn decode_writer_partial_header_filename() { + let filename = "test.txt"; + let mut e = GzBuilder::new() + .filename(filename) + .read(STR.as_bytes(), Compression::default()); + let mut bytes = Vec::new(); + e.read_to_end(&mut bytes).unwrap(); + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12); + let n = decoder.write(&bytes[12..]).unwrap(); + if n < bytes.len() - 12 { + decoder.write(&bytes[n + 12..]).unwrap(); + } + assert_eq!( + decoder.header().unwrap().filename().unwrap(), + filename.as_bytes() + ); + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(return_string, STR); + } + + #[test] + fn decode_writer_partial_header_comment() { + let comment = "test comment"; + let mut e = GzBuilder::new() + .comment(comment) + .read(STR.as_bytes(), Compression::default()); + let mut bytes = Vec::new(); + e.read_to_end(&mut bytes).unwrap(); + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12); + let n = decoder.write(&bytes[12..]).unwrap(); + if n < bytes.len() - 12 { + decoder.write(&bytes[n + 12..]).unwrap(); + } + assert_eq!( + decoder.header().unwrap().comment().unwrap(), + comment.as_bytes() + ); + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(return_string, STR); + } + + #[test] + fn decode_writer_exact_header() { + let mut e = GzEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let bytes = e.finish().unwrap(); + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + assert_eq!(decoder.write(&bytes[..10]).unwrap(), 10); + decoder.write(&bytes[10..]).unwrap(); + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(return_string, STR); + } + + #[test] + fn decode_writer_partial_crc() { + let mut e = GzEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let bytes = e.finish().unwrap(); + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + let l = bytes.len() - 5; + let n = decoder.write(&bytes[..l]).unwrap(); + decoder.write(&bytes[n..]).unwrap(); + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(return_string, STR); + } + + // Two or more gzip files concatenated form a multi-member gzip file. MultiGzDecoder will + // concatenate the decoded contents of all members. + #[test] + fn decode_multi_writer() { + let mut e = GzEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let bytes = e.finish().unwrap().repeat(2); + + let mut writer = Vec::new(); + let mut decoder = MultiGzDecoder::new(writer); + let mut count = 0; + while count < bytes.len() { + let n = decoder.write(&bytes[count..]).unwrap(); + assert!(n != 0); + count += n; + } + writer = decoder.finish().unwrap(); + let return_string = String::from_utf8(writer).expect("String parsing error"); + let expected = STR.repeat(2); + assert_eq!(return_string, expected); + } + + // GzDecoder consumes one gzip member and then returns 0 for subsequent writes, allowing any + // additional data to be consumed by the caller. + #[test] + fn decode_extra_data() { + let compressed = { + let mut e = GzEncoder::new(Vec::new(), Compression::default()); + e.write(STR.as_ref()).unwrap(); + let mut b = e.finish().unwrap(); + b.push(b'x'); + b + }; + + let mut writer = Vec::new(); + let mut decoder = GzDecoder::new(writer); + let mut consumed_bytes = 0; + loop { + let n = decoder.write(&compressed[consumed_bytes..]).unwrap(); + if n == 0 { + break; + } + consumed_bytes += n; + } + writer = decoder.finish().unwrap(); + let actual = String::from_utf8(writer).expect("String parsing error"); + assert_eq!(actual, STR); + assert_eq!(&compressed[consumed_bytes..], b"x"); + } +} diff --git a/vendor/flate2/src/lib.rs b/vendor/flate2/src/lib.rs new file mode 100644 index 0000000..8c000b0 --- /dev/null +++ b/vendor/flate2/src/lib.rs @@ -0,0 +1,234 @@ +//! A DEFLATE-based stream compression/decompression library +//! +//! This library provides support for compression and decompression of +//! DEFLATE-based streams: +//! +//! * the DEFLATE format itself +//! * the zlib format +//! * gzip +//! +//! These three formats are all closely related and largely only differ in their +//! headers/footers. This crate has three types in each submodule for dealing +//! with these three formats. +//! +//! # Implementation +//! +//! In addition to supporting three formats, this crate supports several different +//! backends, controlled through this crate's features: +//! +//! * `default`, or `rust_backend` - this implementation uses the `miniz_oxide` +//! crate which is a port of `miniz.c` (below) to Rust. This feature does not +//! require a C compiler and only requires Rust code. +//! +//! * `zlib` - this feature will enable linking against the `libz` library, typically found on most +//! Linux systems by default. If the library isn't found to already be on the system it will be +//! compiled from source (this is a C library). +//! +//! There's various tradeoffs associated with each implementation, but in general you probably +//! won't have to tweak the defaults. The default choice is selected to avoid the need for a C +//! compiler at build time. `zlib-ng-compat` is useful if you're using zlib for compatibility but +//! want performance via zlib-ng's zlib-compat mode. `zlib` is useful if something else in your +//! dependencies links the original zlib so you cannot use zlib-ng-compat. The compression ratios +//! and performance of each of these feature should be roughly comparable, but you'll likely want +//! to run your own tests if you're curious about the performance. +//! +//! # Organization +//! +//! This crate consists mainly of three modules, [`read`], [`write`], and +//! [`bufread`]. Each module contains a number of types used to encode and +//! decode various streams of data. +//! +//! All types in the [`write`] module work on instances of [`Write`][write], +//! whereas all types in the [`read`] module work on instances of +//! [`Read`][read] and [`bufread`] works with [`BufRead`][bufread]. If you +//! are decoding directly from a `&[u8]`, use the [`bufread`] types. +//! +//! ``` +//! use flate2::write::GzEncoder; +//! use flate2::Compression; +//! use std::io; +//! use std::io::prelude::*; +//! +//! # fn main() { let _ = run(); } +//! # fn run() -> io::Result<()> { +//! let mut encoder = GzEncoder::new(Vec::new(), Compression::default()); +//! encoder.write_all(b"Example")?; +//! # Ok(()) +//! # } +//! ``` +//! +//! +//! Other various types are provided at the top-level of the crate for +//! management and dealing with encoders/decoders. Also note that types which +//! operate over a specific trait often implement the mirroring trait as well. +//! For example a `flate2::read::DeflateDecoder<T>` *also* implements the +//! `Write` trait if `T: Write`. That is, the "dual trait" is forwarded directly +//! to the underlying object if available. +//! +//! # About multi-member Gzip files +//! +//! While most `gzip` files one encounters will have a single *member* that can be read +//! with the [`GzDecoder`], there may be some files which have multiple members. +//! +//! A [`GzDecoder`] will only read the first member of gzip data, which may unexpectedly +//! provide partial results when a multi-member gzip file is encountered. `GzDecoder` is appropriate +//! for data that is designed to be read as single members from a multi-member file. `bufread::GzDecoder` +//! and `write::GzDecoder` also allow non-gzip data following gzip data to be handled. +//! +//! The [`MultiGzDecoder`] on the other hand will decode all members of a `gzip` file +//! into one consecutive stream of bytes, which hides the underlying *members* entirely. +//! If a file contains contains non-gzip data after the gzip data, MultiGzDecoder will +//! emit an error after decoding the gzip data. This behavior matches the `gzip`, +//! `gunzip`, and `zcat` command line tools. +//! +//! [`read`]: read/index.html +//! [`bufread`]: bufread/index.html +//! [`write`]: write/index.html +//! [read]: https://doc.rust-lang.org/std/io/trait.Read.html +//! [write]: https://doc.rust-lang.org/std/io/trait.Write.html +//! [bufread]: https://doc.rust-lang.org/std/io/trait.BufRead.html +//! [`GzDecoder`]: read/struct.GzDecoder.html +//! [`MultiGzDecoder`]: read/struct.MultiGzDecoder.html +#![doc(html_root_url = "https://docs.rs/flate2/0.2")] +#![deny(missing_docs)] +#![deny(missing_debug_implementations)] +#![allow(trivial_numeric_casts)] +#![cfg_attr(test, deny(warnings))] +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +#[cfg(not(feature = "any_impl",))] +compile_error!("You need to choose a zlib backend"); + +pub use crate::crc::{Crc, CrcReader, CrcWriter}; +pub use crate::gz::GzBuilder; +pub use crate::gz::GzHeader; +pub use crate::mem::{Compress, CompressError, Decompress, DecompressError, Status}; +pub use crate::mem::{FlushCompress, FlushDecompress}; + +mod bufreader; +mod crc; +mod deflate; +mod ffi; +mod gz; +mod mem; +mod zio; +mod zlib; + +/// Types which operate over [`Read`] streams, both encoders and decoders for +/// various formats. +/// +/// Note that the `read` decoder types may read past the end of the compressed +/// data while decoding. If the caller requires subsequent reads to start +/// immediately following the compressed data wrap the `Read` type in a +/// [`BufReader`] and use the `BufReader` with the equivalent decoder from the +/// `bufread` module and also for the subsequent reads. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufReader`]: https://doc.rust-lang.org/std/io/struct.BufReader.html +pub mod read { + pub use crate::deflate::read::DeflateDecoder; + pub use crate::deflate::read::DeflateEncoder; + pub use crate::gz::read::GzDecoder; + pub use crate::gz::read::GzEncoder; + pub use crate::gz::read::MultiGzDecoder; + pub use crate::zlib::read::ZlibDecoder; + pub use crate::zlib::read::ZlibEncoder; +} + +/// Types which operate over [`Write`] streams, both encoders and decoders for +/// various formats. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +pub mod write { + pub use crate::deflate::write::DeflateDecoder; + pub use crate::deflate::write::DeflateEncoder; + pub use crate::gz::write::GzDecoder; + pub use crate::gz::write::GzEncoder; + pub use crate::gz::write::MultiGzDecoder; + pub use crate::zlib::write::ZlibDecoder; + pub use crate::zlib::write::ZlibEncoder; +} + +/// Types which operate over [`BufRead`] streams, both encoders and decoders for +/// various formats. +/// +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +pub mod bufread { + pub use crate::deflate::bufread::DeflateDecoder; + pub use crate::deflate::bufread::DeflateEncoder; + pub use crate::gz::bufread::GzDecoder; + pub use crate::gz::bufread::GzEncoder; + pub use crate::gz::bufread::MultiGzDecoder; + pub use crate::zlib::bufread::ZlibDecoder; + pub use crate::zlib::bufread::ZlibEncoder; +} + +fn _assert_send_sync() { + fn _assert_send_sync<T: Send + Sync>() {} + + _assert_send_sync::<read::DeflateEncoder<&[u8]>>(); + _assert_send_sync::<read::DeflateDecoder<&[u8]>>(); + _assert_send_sync::<read::ZlibEncoder<&[u8]>>(); + _assert_send_sync::<read::ZlibDecoder<&[u8]>>(); + _assert_send_sync::<read::GzEncoder<&[u8]>>(); + _assert_send_sync::<read::GzDecoder<&[u8]>>(); + _assert_send_sync::<read::MultiGzDecoder<&[u8]>>(); + _assert_send_sync::<write::DeflateEncoder<Vec<u8>>>(); + _assert_send_sync::<write::DeflateDecoder<Vec<u8>>>(); + _assert_send_sync::<write::ZlibEncoder<Vec<u8>>>(); + _assert_send_sync::<write::ZlibDecoder<Vec<u8>>>(); + _assert_send_sync::<write::GzEncoder<Vec<u8>>>(); + _assert_send_sync::<write::GzDecoder<Vec<u8>>>(); +} + +/// When compressing data, the compression level can be specified by a value in +/// this struct. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub struct Compression(u32); + +impl Compression { + /// Creates a new description of the compression level with an explicitly + /// specified integer. + /// + /// The integer here is typically on a scale of 0-9 where 0 means "no + /// compression" and 9 means "take as long as you'd like". + pub const fn new(level: u32) -> Compression { + Compression(level) + } + + /// No compression is to be performed, this may actually inflate data + /// slightly when encoding. + pub const fn none() -> Compression { + Compression(0) + } + + /// Optimize for the best speed of encoding. + pub const fn fast() -> Compression { + Compression(1) + } + + /// Optimize for the size of data being encoded. + pub const fn best() -> Compression { + Compression(9) + } + + /// Returns an integer representing the compression level, typically on a + /// scale of 0-9 + pub fn level(&self) -> u32 { + self.0 + } +} + +impl Default for Compression { + fn default() -> Compression { + Compression(6) + } +} + +#[cfg(test)] +fn random_bytes() -> impl Iterator<Item = u8> { + use rand::Rng; + use std::iter; + + iter::repeat(()).map(|_| rand::thread_rng().gen()) +} diff --git a/vendor/flate2/src/mem.rs b/vendor/flate2/src/mem.rs new file mode 100644 index 0000000..d4a5091 --- /dev/null +++ b/vendor/flate2/src/mem.rs @@ -0,0 +1,772 @@ +use std::error::Error; +use std::fmt; +use std::io; + +use crate::ffi::{self, Backend, Deflate, DeflateBackend, ErrorMessage, Inflate, InflateBackend}; +use crate::Compression; + +/// Raw in-memory compression stream for blocks of data. +/// +/// This type is the building block for the I/O streams in the rest of this +/// crate. It requires more management than the [`Read`]/[`Write`] API but is +/// maximally flexible in terms of accepting input from any source and being +/// able to produce output to any memory location. +/// +/// It is recommended to use the I/O stream adaptors over this type as they're +/// easier to use. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +#[derive(Debug)] +pub struct Compress { + inner: Deflate, +} + +/// Raw in-memory decompression stream for blocks of data. +/// +/// This type is the building block for the I/O streams in the rest of this +/// crate. It requires more management than the [`Read`]/[`Write`] API but is +/// maximally flexible in terms of accepting input from any source and being +/// able to produce output to any memory location. +/// +/// It is recommended to use the I/O stream adaptors over this type as they're +/// easier to use. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +#[derive(Debug)] +pub struct Decompress { + inner: Inflate, +} + +/// Values which indicate the form of flushing to be used when compressing +/// in-memory data. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[non_exhaustive] +pub enum FlushCompress { + /// A typical parameter for passing to compression/decompression functions, + /// this indicates that the underlying stream to decide how much data to + /// accumulate before producing output in order to maximize compression. + None = ffi::MZ_NO_FLUSH as isize, + + /// All pending output is flushed to the output buffer and the output is + /// aligned on a byte boundary so that the decompressor can get all input + /// data available so far. + /// + /// Flushing may degrade compression for some compression algorithms and so + /// it should only be used when necessary. This will complete the current + /// deflate block and follow it with an empty stored block. + Sync = ffi::MZ_SYNC_FLUSH as isize, + + /// All pending output is flushed to the output buffer, but the output is + /// not aligned to a byte boundary. + /// + /// All of the input data so far will be available to the decompressor (as + /// with `Flush::Sync`. This completes the current deflate block and follows + /// it with an empty fixed codes block that is 10 bites long, and it assures + /// that enough bytes are output in order for the decompressor to finish the + /// block before the empty fixed code block. + Partial = ffi::MZ_PARTIAL_FLUSH as isize, + + /// All output is flushed as with `Flush::Sync` and the compression state is + /// reset so decompression can restart from this point if previous + /// compressed data has been damaged or if random access is desired. + /// + /// Using this option too often can seriously degrade compression. + Full = ffi::MZ_FULL_FLUSH as isize, + + /// Pending input is processed and pending output is flushed. + /// + /// The return value may indicate that the stream is not yet done and more + /// data has yet to be processed. + Finish = ffi::MZ_FINISH as isize, +} + +/// Values which indicate the form of flushing to be used when +/// decompressing in-memory data. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[non_exhaustive] +pub enum FlushDecompress { + /// A typical parameter for passing to compression/decompression functions, + /// this indicates that the underlying stream to decide how much data to + /// accumulate before producing output in order to maximize compression. + None = ffi::MZ_NO_FLUSH as isize, + + /// All pending output is flushed to the output buffer and the output is + /// aligned on a byte boundary so that the decompressor can get all input + /// data available so far. + /// + /// Flushing may degrade compression for some compression algorithms and so + /// it should only be used when necessary. This will complete the current + /// deflate block and follow it with an empty stored block. + Sync = ffi::MZ_SYNC_FLUSH as isize, + + /// Pending input is processed and pending output is flushed. + /// + /// The return value may indicate that the stream is not yet done and more + /// data has yet to be processed. + Finish = ffi::MZ_FINISH as isize, +} + +/// The inner state for an error when decompressing +#[derive(Debug)] +pub(crate) enum DecompressErrorInner { + General { msg: ErrorMessage }, + NeedsDictionary(u32), +} + +/// Error returned when a decompression object finds that the input stream of +/// bytes was not a valid input stream of bytes. +#[derive(Debug)] +pub struct DecompressError(pub(crate) DecompressErrorInner); + +impl DecompressError { + /// Indicates whether decompression failed due to requiring a dictionary. + /// + /// The resulting integer is the Adler-32 checksum of the dictionary + /// required. + pub fn needs_dictionary(&self) -> Option<u32> { + match self.0 { + DecompressErrorInner::NeedsDictionary(adler) => Some(adler), + _ => None, + } + } +} + +#[inline] +pub(crate) fn decompress_failed<T>(msg: ErrorMessage) -> Result<T, DecompressError> { + Err(DecompressError(DecompressErrorInner::General { msg })) +} + +#[inline] +pub(crate) fn decompress_need_dict<T>(adler: u32) -> Result<T, DecompressError> { + Err(DecompressError(DecompressErrorInner::NeedsDictionary( + adler, + ))) +} + +/// Error returned when a compression object is used incorrectly or otherwise +/// generates an error. +#[derive(Debug)] +pub struct CompressError { + pub(crate) msg: ErrorMessage, +} + +#[inline] +pub(crate) fn compress_failed<T>(msg: ErrorMessage) -> Result<T, CompressError> { + Err(CompressError { msg }) +} + +/// Possible status results of compressing some data or successfully +/// decompressing a block of data. +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +pub enum Status { + /// Indicates success. + /// + /// Means that more input may be needed but isn't available + /// and/or there's more output to be written but the output buffer is full. + Ok, + + /// Indicates that forward progress is not possible due to input or output + /// buffers being empty. + /// + /// For compression it means the input buffer needs some more data or the + /// output buffer needs to be freed up before trying again. + /// + /// For decompression this means that more input is needed to continue or + /// the output buffer isn't large enough to contain the result. The function + /// can be called again after fixing both. + BufError, + + /// Indicates that all input has been consumed and all output bytes have + /// been written. Decompression/compression should not be called again. + /// + /// For decompression with zlib streams the adler-32 of the decompressed + /// data has also been verified. + StreamEnd, +} + +impl Compress { + /// Creates a new object ready for compressing data that it's given. + /// + /// The `level` argument here indicates what level of compression is going + /// to be performed, and the `zlib_header` argument indicates whether the + /// output data should have a zlib header or not. + pub fn new(level: Compression, zlib_header: bool) -> Compress { + Compress { + inner: Deflate::make(level, zlib_header, ffi::MZ_DEFAULT_WINDOW_BITS as u8), + } + } + + /// Creates a new object ready for compressing data that it's given. + /// + /// The `level` argument here indicates what level of compression is going + /// to be performed, and the `zlib_header` argument indicates whether the + /// output data should have a zlib header or not. The `window_bits` parameter + /// indicates the base-2 logarithm of the sliding window size and must be + /// between 9 and 15. + /// + /// # Panics + /// + /// If `window_bits` does not fall into the range 9 ..= 15, + /// `new_with_window_bits` will panic. + #[cfg(feature = "any_zlib")] + pub fn new_with_window_bits( + level: Compression, + zlib_header: bool, + window_bits: u8, + ) -> Compress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); + Compress { + inner: Deflate::make(level, zlib_header, window_bits), + } + } + + /// Creates a new object ready for compressing data that it's given. + /// + /// The `level` argument here indicates what level of compression is going + /// to be performed. + /// + /// The Compress object produced by this constructor outputs gzip headers + /// for the compressed data. + /// + /// # Panics + /// + /// If `window_bits` does not fall into the range 9 ..= 15, + /// `new_with_window_bits` will panic. + #[cfg(feature = "any_zlib")] + pub fn new_gzip(level: Compression, window_bits: u8) -> Compress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); + Compress { + inner: Deflate::make(level, true, window_bits + 16), + } + } + + /// Returns the total number of input bytes which have been processed by + /// this compression object. + pub fn total_in(&self) -> u64 { + self.inner.total_in() + } + + /// Returns the total number of output bytes which have been produced by + /// this compression object. + pub fn total_out(&self) -> u64 { + self.inner.total_out() + } + + /// Specifies the compression dictionary to use. + /// + /// Returns the Adler-32 checksum of the dictionary. + #[cfg(feature = "any_zlib")] + pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, CompressError> { + let stream = &mut *self.inner.inner.stream_wrapper; + stream.msg = std::ptr::null_mut(); + let rc = unsafe { + assert!(dictionary.len() < ffi::uInt::MAX as usize); + ffi::deflateSetDictionary(stream, dictionary.as_ptr(), dictionary.len() as ffi::uInt) + }; + + match rc { + ffi::MZ_STREAM_ERROR => compress_failed(self.inner.inner.msg()), + ffi::MZ_OK => Ok(stream.adler as u32), + c => panic!("unknown return code: {}", c), + } + } + + /// Quickly resets this compressor without having to reallocate anything. + /// + /// This is equivalent to dropping this object and then creating a new one. + pub fn reset(&mut self) { + self.inner.reset(); + } + + /// Dynamically updates the compression level. + /// + /// This can be used to switch between compression levels for different + /// kinds of data, or it can be used in conjunction with a call to reset + /// to reuse the compressor. + /// + /// This may return an error if there wasn't enough output space to complete + /// the compression of the available input data before changing the + /// compression level. Flushing the stream before calling this method + /// ensures that the function will succeed on the first call. + #[cfg(feature = "any_zlib")] + pub fn set_level(&mut self, level: Compression) -> Result<(), CompressError> { + use std::os::raw::c_int; + let stream = &mut *self.inner.inner.stream_wrapper; + stream.msg = std::ptr::null_mut(); + + let rc = unsafe { ffi::deflateParams(stream, level.0 as c_int, ffi::MZ_DEFAULT_STRATEGY) }; + + match rc { + ffi::MZ_OK => Ok(()), + ffi::MZ_BUF_ERROR => compress_failed(self.inner.inner.msg()), + c => panic!("unknown return code: {}", c), + } + } + + /// Compresses the input data into the output, consuming only as much + /// input as needed and writing as much output as possible. + /// + /// The flush option can be any of the available `FlushCompress` parameters. + /// + /// To learn how much data was consumed or how much output was produced, use + /// the `total_in` and `total_out` functions before/after this is called. + pub fn compress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushCompress, + ) -> Result<Status, CompressError> { + self.inner.compress(input, output, flush) + } + + /// Compresses the input data into the extra space of the output, consuming + /// only as much input as needed and writing as much output as possible. + /// + /// This function has the same semantics as `compress`, except that the + /// length of `vec` is managed by this function. This will not reallocate + /// the vector provided or attempt to grow it, so space for the output must + /// be reserved in the output vector by the caller before calling this + /// function. + pub fn compress_vec( + &mut self, + input: &[u8], + output: &mut Vec<u8>, + flush: FlushCompress, + ) -> Result<Status, CompressError> { + write_to_spare_capacity_of_vec(output, |out| { + let before = self.total_out(); + let ret = self.compress(input, out, flush); + let bytes_written = self.total_out() - before; + (bytes_written as usize, ret) + }) + } +} + +impl Decompress { + /// Creates a new object ready for decompressing data that it's given. + /// + /// The `zlib_header` argument indicates whether the input data is expected + /// to have a zlib header or not. + pub fn new(zlib_header: bool) -> Decompress { + Decompress { + inner: Inflate::make(zlib_header, ffi::MZ_DEFAULT_WINDOW_BITS as u8), + } + } + + /// Creates a new object ready for decompressing data that it's given. + /// + /// The `zlib_header` argument indicates whether the input data is expected + /// to have a zlib header or not. The `window_bits` parameter indicates the + /// base-2 logarithm of the sliding window size and must be between 9 and 15. + /// + /// # Panics + /// + /// If `window_bits` does not fall into the range 9 ..= 15, + /// `new_with_window_bits` will panic. + #[cfg(feature = "any_zlib")] + pub fn new_with_window_bits(zlib_header: bool, window_bits: u8) -> Decompress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); + Decompress { + inner: Inflate::make(zlib_header, window_bits), + } + } + + /// Creates a new object ready for decompressing data that it's given. + /// + /// The Decompress object produced by this constructor expects gzip headers + /// for the compressed data. + /// + /// # Panics + /// + /// If `window_bits` does not fall into the range 9 ..= 15, + /// `new_with_window_bits` will panic. + #[cfg(feature = "any_zlib")] + pub fn new_gzip(window_bits: u8) -> Decompress { + assert!( + window_bits > 8 && window_bits < 16, + "window_bits must be within 9 ..= 15" + ); + Decompress { + inner: Inflate::make(true, window_bits + 16), + } + } + + /// Returns the total number of input bytes which have been processed by + /// this decompression object. + pub fn total_in(&self) -> u64 { + self.inner.total_in() + } + + /// Returns the total number of output bytes which have been produced by + /// this decompression object. + pub fn total_out(&self) -> u64 { + self.inner.total_out() + } + + /// Decompresses the input data into the output, consuming only as much + /// input as needed and writing as much output as possible. + /// + /// The flush option can be any of the available `FlushDecompress` parameters. + /// + /// If the first call passes `FlushDecompress::Finish` it is assumed that + /// the input and output buffers are both sized large enough to decompress + /// the entire stream in a single call. + /// + /// A flush value of `FlushDecompress::Finish` indicates that there are no + /// more source bytes available beside what's already in the input buffer, + /// and the output buffer is large enough to hold the rest of the + /// decompressed data. + /// + /// To learn how much data was consumed or how much output was produced, use + /// the `total_in` and `total_out` functions before/after this is called. + /// + /// # Errors + /// + /// If the input data to this instance of `Decompress` is not a valid + /// zlib/deflate stream then this function may return an instance of + /// `DecompressError` to indicate that the stream of input bytes is corrupted. + pub fn decompress( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushDecompress, + ) -> Result<Status, DecompressError> { + self.inner.decompress(input, output, flush) + } + + /// Decompresses the input data into the extra space in the output vector + /// specified by `output`. + /// + /// This function has the same semantics as `decompress`, except that the + /// length of `vec` is managed by this function. This will not reallocate + /// the vector provided or attempt to grow it, so space for the output must + /// be reserved in the output vector by the caller before calling this + /// function. + /// + /// # Errors + /// + /// If the input data to this instance of `Decompress` is not a valid + /// zlib/deflate stream then this function may return an instance of + /// `DecompressError` to indicate that the stream of input bytes is corrupted. + pub fn decompress_vec( + &mut self, + input: &[u8], + output: &mut Vec<u8>, + flush: FlushDecompress, + ) -> Result<Status, DecompressError> { + write_to_spare_capacity_of_vec(output, |out| { + let before = self.total_out(); + let ret = self.decompress(input, out, flush); + let bytes_written = self.total_out() - before; + (bytes_written as usize, ret) + }) + } + + /// Specifies the decompression dictionary to use. + #[cfg(feature = "any_zlib")] + pub fn set_dictionary(&mut self, dictionary: &[u8]) -> Result<u32, DecompressError> { + let stream = &mut *self.inner.inner.stream_wrapper; + stream.msg = std::ptr::null_mut(); + let rc = unsafe { + assert!(dictionary.len() < ffi::uInt::MAX as usize); + ffi::inflateSetDictionary(stream, dictionary.as_ptr(), dictionary.len() as ffi::uInt) + }; + + match rc { + ffi::MZ_STREAM_ERROR => decompress_failed(self.inner.inner.msg()), + ffi::MZ_DATA_ERROR => decompress_need_dict(stream.adler as u32), + ffi::MZ_OK => Ok(stream.adler as u32), + c => panic!("unknown return code: {}", c), + } + } + + /// Performs the equivalent of replacing this decompression state with a + /// freshly allocated copy. + /// + /// This function may not allocate memory, though, and attempts to reuse any + /// previously existing resources. + /// + /// The argument provided here indicates whether the reset state will + /// attempt to decode a zlib header first or not. + pub fn reset(&mut self, zlib_header: bool) { + self.inner.reset(zlib_header); + } +} + +impl Error for DecompressError {} + +impl DecompressError { + /// Retrieve the implementation's message about why the operation failed, if one exists. + pub fn message(&self) -> Option<&str> { + match &self.0 { + DecompressErrorInner::General { msg } => msg.get(), + _ => None, + } + } +} + +impl From<DecompressError> for io::Error { + fn from(data: DecompressError) -> io::Error { + io::Error::new(io::ErrorKind::Other, data) + } +} + +impl fmt::Display for DecompressError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let msg = match &self.0 { + DecompressErrorInner::General { msg } => msg.get(), + DecompressErrorInner::NeedsDictionary { .. } => Some("requires a dictionary"), + }; + match msg { + Some(msg) => write!(f, "deflate decompression error: {}", msg), + None => write!(f, "deflate decompression error"), + } + } +} + +impl Error for CompressError {} + +impl CompressError { + /// Retrieve the implementation's message about why the operation failed, if one exists. + pub fn message(&self) -> Option<&str> { + self.msg.get() + } +} + +impl From<CompressError> for io::Error { + fn from(data: CompressError) -> io::Error { + io::Error::new(io::ErrorKind::Other, data) + } +} + +impl fmt::Display for CompressError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.msg.get() { + Some(msg) => write!(f, "deflate compression error: {}", msg), + None => write!(f, "deflate compression error"), + } + } +} + +/// Allows `writer` to write data into the spare capacity of the `output` vector. +/// This will not reallocate the vector provided or attempt to grow it, so space +/// for the `output` must be reserved by the caller before calling this +/// function. +/// +/// `writer` needs to return the number of bytes written (and can also return +/// another arbitrary return value). +fn write_to_spare_capacity_of_vec<T>( + output: &mut Vec<u8>, + writer: impl FnOnce(&mut [u8]) -> (usize, T), +) -> T { + let cap = output.capacity(); + let len = output.len(); + + output.resize(output.capacity(), 0); + let (bytes_written, ret) = writer(&mut output[len..]); + + let new_len = core::cmp::min(len + bytes_written, cap); // Sanitizes `bytes_written`. + output.resize(new_len, 0 /* unused */); + + ret +} + +#[cfg(test)] +mod tests { + use std::io::Write; + + use crate::write; + use crate::{Compression, Decompress, FlushDecompress}; + + #[cfg(feature = "any_zlib")] + use crate::{Compress, FlushCompress}; + + #[test] + fn issue51() { + let data = vec![ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xb3, 0xc9, 0x28, 0xc9, + 0xcd, 0xb1, 0xe3, 0xe5, 0xb2, 0xc9, 0x48, 0x4d, 0x4c, 0xb1, 0xb3, 0x29, 0xc9, 0x2c, + 0xc9, 0x49, 0xb5, 0x33, 0x31, 0x30, 0x51, 0xf0, 0xcb, 0x2f, 0x51, 0x70, 0xcb, 0x2f, + 0xcd, 0x4b, 0xb1, 0xd1, 0x87, 0x08, 0xda, 0xe8, 0x83, 0x95, 0x00, 0x95, 0x26, 0xe5, + 0xa7, 0x54, 0x2a, 0x24, 0xa5, 0x27, 0xe7, 0xe7, 0xe4, 0x17, 0xd9, 0x2a, 0x95, 0x67, + 0x64, 0x96, 0xa4, 0x2a, 0x81, 0x8c, 0x48, 0x4e, 0xcd, 0x2b, 0x49, 0x2d, 0xb2, 0xb3, + 0xc9, 0x30, 0x44, 0x37, 0x01, 0x28, 0x62, 0xa3, 0x0f, 0x95, 0x06, 0xd9, 0x05, 0x54, + 0x04, 0xe5, 0xe5, 0xa5, 0x67, 0xe6, 0x55, 0xe8, 0x1b, 0xea, 0x99, 0xe9, 0x19, 0x21, + 0xab, 0xd0, 0x07, 0xd9, 0x01, 0x32, 0x53, 0x1f, 0xea, 0x3e, 0x00, 0x94, 0x85, 0xeb, + 0xe4, 0xa8, 0x00, 0x00, 0x00, + ]; + + let mut decoded = Vec::with_capacity(data.len() * 2); + + let mut d = Decompress::new(false); + // decompressed whole deflate stream + assert!(d + .decompress_vec(&data[10..], &mut decoded, FlushDecompress::Finish) + .is_ok()); + + // decompress data that has nothing to do with the deflate stream (this + // used to panic) + drop(d.decompress_vec(&[0], &mut decoded, FlushDecompress::None)); + } + + #[test] + fn reset() { + let string = "hello world".as_bytes(); + let mut zlib = Vec::new(); + let mut deflate = Vec::new(); + + let comp = Compression::default(); + write::ZlibEncoder::new(&mut zlib, comp) + .write_all(string) + .unwrap(); + write::DeflateEncoder::new(&mut deflate, comp) + .write_all(string) + .unwrap(); + + let mut dst = [0; 1024]; + let mut decoder = Decompress::new(true); + decoder + .decompress(&zlib, &mut dst, FlushDecompress::Finish) + .unwrap(); + assert_eq!(decoder.total_out(), string.len() as u64); + assert!(dst.starts_with(string)); + + decoder.reset(false); + decoder + .decompress(&deflate, &mut dst, FlushDecompress::Finish) + .unwrap(); + assert_eq!(decoder.total_out(), string.len() as u64); + assert!(dst.starts_with(string)); + } + + #[cfg(feature = "any_zlib")] + #[test] + fn set_dictionary_with_zlib_header() { + let string = "hello, hello!".as_bytes(); + let dictionary = "hello".as_bytes(); + + let mut encoded = Vec::with_capacity(1024); + + let mut encoder = Compress::new(Compression::default(), true); + + let dictionary_adler = encoder.set_dictionary(&dictionary).unwrap(); + + encoder + .compress_vec(string, &mut encoded, FlushCompress::Finish) + .unwrap(); + + assert_eq!(encoder.total_in(), string.len() as u64); + assert_eq!(encoder.total_out(), encoded.len() as u64); + + let mut decoder = Decompress::new(true); + let mut decoded = [0; 1024]; + let decompress_error = decoder + .decompress(&encoded, &mut decoded, FlushDecompress::Finish) + .expect_err("decompression should fail due to requiring a dictionary"); + + let required_adler = decompress_error.needs_dictionary() + .expect("the first call to decompress should indicate a dictionary is required along with the required Adler-32 checksum"); + + assert_eq!(required_adler, dictionary_adler, + "the Adler-32 checksum should match the value when the dictionary was set on the compressor"); + + let actual_adler = decoder.set_dictionary(&dictionary).unwrap(); + + assert_eq!(required_adler, actual_adler); + + // Decompress the rest of the input to the remainder of the output buffer + let total_in = decoder.total_in(); + let total_out = decoder.total_out(); + + let decompress_result = decoder.decompress( + &encoded[total_in as usize..], + &mut decoded[total_out as usize..], + FlushDecompress::Finish, + ); + assert!(decompress_result.is_ok()); + + assert_eq!(&decoded[..decoder.total_out() as usize], string); + } + + #[cfg(feature = "any_zlib")] + #[test] + fn set_dictionary_raw() { + let string = "hello, hello!".as_bytes(); + let dictionary = "hello".as_bytes(); + + let mut encoded = Vec::with_capacity(1024); + + let mut encoder = Compress::new(Compression::default(), false); + + encoder.set_dictionary(&dictionary).unwrap(); + + encoder + .compress_vec(string, &mut encoded, FlushCompress::Finish) + .unwrap(); + + assert_eq!(encoder.total_in(), string.len() as u64); + assert_eq!(encoder.total_out(), encoded.len() as u64); + + let mut decoder = Decompress::new(false); + + decoder.set_dictionary(&dictionary).unwrap(); + + let mut decoded = [0; 1024]; + let decompress_result = decoder.decompress(&encoded, &mut decoded, FlushDecompress::Finish); + + assert!(decompress_result.is_ok()); + + assert_eq!(&decoded[..decoder.total_out() as usize], string); + } + + #[cfg(feature = "any_zlib")] + #[test] + fn test_gzip_flate() { + let string = "hello, hello!".as_bytes(); + + let mut encoded = Vec::with_capacity(1024); + + let mut encoder = Compress::new_gzip(Compression::default(), 9); + + encoder + .compress_vec(string, &mut encoded, FlushCompress::Finish) + .unwrap(); + + assert_eq!(encoder.total_in(), string.len() as u64); + assert_eq!(encoder.total_out(), encoded.len() as u64); + + let mut decoder = Decompress::new_gzip(9); + + let mut decoded = [0; 1024]; + decoder + .decompress(&encoded, &mut decoded, FlushDecompress::Finish) + .unwrap(); + + assert_eq!(&decoded[..decoder.total_out() as usize], string); + } + + #[cfg(feature = "any_zlib")] + #[test] + fn test_error_message() { + let mut decoder = Decompress::new(false); + let mut decoded = [0; 128]; + let garbage = b"xbvxzi"; + + let err = decoder + .decompress(&*garbage, &mut decoded, FlushDecompress::Finish) + .unwrap_err(); + + assert_eq!(err.message(), Some("invalid stored block lengths")); + } +} diff --git a/vendor/flate2/src/zio.rs b/vendor/flate2/src/zio.rs new file mode 100644 index 0000000..ea25922 --- /dev/null +++ b/vendor/flate2/src/zio.rs @@ -0,0 +1,286 @@ +use std::io; +use std::io::prelude::*; +use std::mem; + +use crate::{Compress, Decompress, DecompressError, FlushCompress, FlushDecompress, Status}; + +#[derive(Debug)] +pub struct Writer<W: Write, D: Ops> { + obj: Option<W>, + pub data: D, + buf: Vec<u8>, +} + +pub trait Ops { + type Flush: Flush; + fn total_in(&self) -> u64; + fn total_out(&self) -> u64; + fn run( + &mut self, + input: &[u8], + output: &mut [u8], + flush: Self::Flush, + ) -> Result<Status, DecompressError>; + fn run_vec( + &mut self, + input: &[u8], + output: &mut Vec<u8>, + flush: Self::Flush, + ) -> Result<Status, DecompressError>; +} + +impl Ops for Compress { + type Flush = FlushCompress; + fn total_in(&self) -> u64 { + self.total_in() + } + fn total_out(&self) -> u64 { + self.total_out() + } + fn run( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushCompress, + ) -> Result<Status, DecompressError> { + Ok(self.compress(input, output, flush).unwrap()) + } + fn run_vec( + &mut self, + input: &[u8], + output: &mut Vec<u8>, + flush: FlushCompress, + ) -> Result<Status, DecompressError> { + Ok(self.compress_vec(input, output, flush).unwrap()) + } +} + +impl Ops for Decompress { + type Flush = FlushDecompress; + fn total_in(&self) -> u64 { + self.total_in() + } + fn total_out(&self) -> u64 { + self.total_out() + } + fn run( + &mut self, + input: &[u8], + output: &mut [u8], + flush: FlushDecompress, + ) -> Result<Status, DecompressError> { + self.decompress(input, output, flush) + } + fn run_vec( + &mut self, + input: &[u8], + output: &mut Vec<u8>, + flush: FlushDecompress, + ) -> Result<Status, DecompressError> { + self.decompress_vec(input, output, flush) + } +} + +pub trait Flush { + fn none() -> Self; + fn sync() -> Self; + fn finish() -> Self; +} + +impl Flush for FlushCompress { + fn none() -> Self { + FlushCompress::None + } + + fn sync() -> Self { + FlushCompress::Sync + } + + fn finish() -> Self { + FlushCompress::Finish + } +} + +impl Flush for FlushDecompress { + fn none() -> Self { + FlushDecompress::None + } + + fn sync() -> Self { + FlushDecompress::Sync + } + + fn finish() -> Self { + FlushDecompress::Finish + } +} + +pub fn read<R, D>(obj: &mut R, data: &mut D, dst: &mut [u8]) -> io::Result<usize> +where + R: BufRead, + D: Ops, +{ + loop { + let (read, consumed, ret, eof); + { + let input = obj.fill_buf()?; + eof = input.is_empty(); + let before_out = data.total_out(); + let before_in = data.total_in(); + let flush = if eof { + D::Flush::finish() + } else { + D::Flush::none() + }; + ret = data.run(input, dst, flush); + read = (data.total_out() - before_out) as usize; + consumed = (data.total_in() - before_in) as usize; + } + obj.consume(consumed); + + match ret { + // If we haven't ready any data and we haven't hit EOF yet, + // then we need to keep asking for more data because if we + // return that 0 bytes of data have been read then it will + // be interpreted as EOF. + Ok(Status::Ok | Status::BufError) if read == 0 && !eof && !dst.is_empty() => continue, + Ok(Status::Ok | Status::BufError | Status::StreamEnd) => return Ok(read), + + Err(..) => { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "corrupt deflate stream", + )) + } + } + } +} + +impl<W: Write, D: Ops> Writer<W, D> { + pub fn new(w: W, d: D) -> Writer<W, D> { + Writer { + obj: Some(w), + data: d, + buf: Vec::with_capacity(32 * 1024), + } + } + + pub fn finish(&mut self) -> io::Result<()> { + loop { + self.dump()?; + + let before = self.data.total_out(); + self.data.run_vec(&[], &mut self.buf, D::Flush::finish())?; + if before == self.data.total_out() { + return Ok(()); + } + } + } + + pub fn replace(&mut self, w: W) -> W { + self.buf.truncate(0); + mem::replace(self.get_mut(), w) + } + + pub fn get_ref(&self) -> &W { + self.obj.as_ref().unwrap() + } + + pub fn get_mut(&mut self) -> &mut W { + self.obj.as_mut().unwrap() + } + + // Note that this should only be called if the outer object is just about + // to be consumed! + // + // (e.g. an implementation of `into_inner`) + pub fn take_inner(&mut self) -> W { + self.obj.take().unwrap() + } + + pub fn is_present(&self) -> bool { + self.obj.is_some() + } + + // Returns total written bytes and status of underlying codec + pub(crate) fn write_with_status(&mut self, buf: &[u8]) -> io::Result<(usize, Status)> { + // miniz isn't guaranteed to actually write any of the buffer provided, + // it may be in a flushing mode where it's just giving us data before + // we're actually giving it any data. We don't want to spuriously return + // `Ok(0)` when possible as it will cause calls to write_all() to fail. + // As a result we execute this in a loop to ensure that we try our + // darndest to write the data. + loop { + self.dump()?; + + let before_in = self.data.total_in(); + let ret = self.data.run_vec(buf, &mut self.buf, D::Flush::none()); + let written = (self.data.total_in() - before_in) as usize; + let is_stream_end = matches!(ret, Ok(Status::StreamEnd)); + + if !buf.is_empty() && written == 0 && ret.is_ok() && !is_stream_end { + continue; + } + return match ret { + Ok(st) => match st { + Status::Ok | Status::BufError | Status::StreamEnd => Ok((written, st)), + }, + Err(..) => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "corrupt deflate stream", + )), + }; + } + } + + fn dump(&mut self) -> io::Result<()> { + // TODO: should manage this buffer not with `drain` but probably more of + // a deque-like strategy. + while !self.buf.is_empty() { + let n = self.obj.as_mut().unwrap().write(&self.buf)?; + if n == 0 { + return Err(io::ErrorKind::WriteZero.into()); + } + self.buf.drain(..n); + } + Ok(()) + } +} + +impl<W: Write, D: Ops> Write for Writer<W, D> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.write_with_status(buf).map(|res| res.0) + } + + fn flush(&mut self) -> io::Result<()> { + self.data + .run_vec(&[], &mut self.buf, D::Flush::sync()) + .unwrap(); + + // Unfortunately miniz doesn't actually tell us when we're done with + // pulling out all the data from the internal stream. To remedy this we + // have to continually ask the stream for more memory until it doesn't + // give us a chunk of memory the same size as our own internal buffer, + // at which point we assume it's reached the end. + loop { + self.dump()?; + let before = self.data.total_out(); + self.data + .run_vec(&[], &mut self.buf, D::Flush::none()) + .unwrap(); + if before == self.data.total_out() { + break; + } + } + + self.obj.as_mut().unwrap().flush() + } +} + +impl<W: Write, D: Ops> Drop for Writer<W, D> { + fn drop(&mut self) { + if self.obj.is_some() { + let _ = self.finish(); + } + } +} diff --git a/vendor/flate2/src/zlib/bufread.rs b/vendor/flate2/src/zlib/bufread.rs new file mode 100644 index 0000000..85bbd38 --- /dev/null +++ b/vendor/flate2/src/zlib/bufread.rs @@ -0,0 +1,253 @@ +use std::io; +use std::io::prelude::*; +use std::mem; + +use crate::zio; +use crate::{Compress, Decompress}; + +/// A ZLIB encoder, or compressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// uncompressed data from the underlying [`BufRead`] and provides the compressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use flate2::Compression; +/// use flate2::bufread::ZlibEncoder; +/// use std::fs::File; +/// use std::io::BufReader; +/// +/// // Use a buffered file to compress contents into a Vec<u8> +/// +/// # fn open_hello_world() -> std::io::Result<Vec<u8>> { +/// let f = File::open("examples/hello_world.txt")?; +/// let b = BufReader::new(f); +/// let mut z = ZlibEncoder::new(b, Compression::fast()); +/// let mut buffer = Vec::new(); +/// z.read_to_end(&mut buffer)?; +/// # Ok(buffer) +/// # } +/// ``` +#[derive(Debug)] +pub struct ZlibEncoder<R> { + obj: R, + data: Compress, +} + +impl<R: BufRead> ZlibEncoder<R> { + /// Creates a new encoder which will read uncompressed data from the given + /// stream and emit the compressed stream. + pub fn new(r: R, level: crate::Compression) -> ZlibEncoder<R> { + ZlibEncoder { + obj: r, + data: Compress::new(level, true), + } + } + + /// Creates a new encoder with the given `compression` settings which will + /// read uncompressed data from the given stream `r` and emit the compressed stream. + pub fn new_with_compress(r: R, compression: Compress) -> ZlibEncoder<R> { + ZlibEncoder { + obj: r, + data: compression, + } + } +} + +pub fn reset_encoder_data<R>(zlib: &mut ZlibEncoder<R>) { + zlib.data.reset() +} + +impl<R> ZlibEncoder<R> { + /// Resets the state of this encoder entirely, swapping out the input + /// stream for another. + /// + /// This function will reset the internal state of this encoder and replace + /// the input stream with the one provided, returning the previous input + /// stream. Future data read from this encoder will be the compressed + /// version of `r`'s data. + pub fn reset(&mut self, r: R) -> R { + reset_encoder_data(self); + mem::replace(&mut self.obj, r) + } + + /// Acquires a reference to the underlying reader + pub fn get_ref(&self) -> &R { + &self.obj + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + &mut self.obj + } + + /// Consumes this encoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.obj + } + + /// Returns the number of bytes that have been read into this compressor. + /// + /// Note that not all bytes read from the underlying object may be accounted + /// for, there may still be some active buffering. + pub fn total_in(&self) -> u64 { + self.data.total_in() + } + + /// Returns the number of bytes that the compressor has produced. + /// + /// Note that not all bytes may have been read yet, some may still be + /// buffered. + pub fn total_out(&self) -> u64 { + self.data.total_out() + } +} + +impl<R: BufRead> Read for ZlibEncoder<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + zio::read(&mut self.obj, &mut self.data, buf) + } +} + +impl<R: BufRead + Write> Write for ZlibEncoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A ZLIB decoder, or decompressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`BufRead`] and provides the uncompressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::ZlibEncoder; +/// use flate2::bufread::ZlibDecoder; +/// +/// # fn main() { +/// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_bufreader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements BufRead +/// +/// fn decode_bufreader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut z = ZlibDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// z.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct ZlibDecoder<R> { + obj: R, + data: Decompress, +} + +impl<R: BufRead> ZlibDecoder<R> { + /// Creates a new decoder which will decompress data read from the given + /// stream. + pub fn new(r: R) -> ZlibDecoder<R> { + ZlibDecoder { + obj: r, + data: Decompress::new(true), + } + } + + /// Creates a new decoder which will decompress data read from the given + /// stream, using the given `decompression` settings. + pub fn new_with_decompress(r: R, decompression: Decompress) -> ZlibDecoder<R> { + ZlibDecoder { + obj: r, + data: decompression, + } + } +} + +pub fn reset_decoder_data<R>(zlib: &mut ZlibDecoder<R>) { + zlib.data = Decompress::new(true); +} + +impl<R> ZlibDecoder<R> { + /// Resets the state of this decoder entirely, swapping out the input + /// stream for another. + /// + /// This will reset the internal state of this decoder and replace the + /// input stream with the one provided, returning the previous input + /// stream. Future data read from this decoder will be the decompressed + /// version of `r`'s data. + pub fn reset(&mut self, r: R) -> R { + reset_decoder_data(self); + mem::replace(&mut self.obj, r) + } + + /// Acquires a reference to the underlying stream + pub fn get_ref(&self) -> &R { + &self.obj + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + &mut self.obj + } + + /// Consumes this decoder, returning the underlying reader. + pub fn into_inner(self) -> R { + self.obj + } + + /// Returns the number of bytes that the decompressor has consumed. + /// + /// Note that this will likely be smaller than what the decompressor + /// actually read from the underlying stream due to buffering. + pub fn total_in(&self) -> u64 { + self.data.total_in() + } + + /// Returns the number of bytes that the decompressor has produced. + pub fn total_out(&self) -> u64 { + self.data.total_out() + } +} + +impl<R: BufRead> Read for ZlibDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + zio::read(&mut self.obj, &mut self.data, into) + } +} + +impl<R: BufRead + Write> Write for ZlibDecoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} diff --git a/vendor/flate2/src/zlib/mod.rs b/vendor/flate2/src/zlib/mod.rs new file mode 100644 index 0000000..1a293ba --- /dev/null +++ b/vendor/flate2/src/zlib/mod.rs @@ -0,0 +1,159 @@ +pub mod bufread; +pub mod read; +pub mod write; + +#[cfg(test)] +mod tests { + use std::io; + use std::io::prelude::*; + + use rand::{thread_rng, Rng}; + + use crate::zlib::{read, write}; + use crate::Compression; + + #[test] + fn roundtrip() { + let mut real = Vec::new(); + let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); + let v = crate::random_bytes().take(1024).collect::<Vec<_>>(); + for _ in 0..200 { + let to_write = &v[..thread_rng().gen_range(0..v.len())]; + real.extend(to_write.iter().copied()); + w.write_all(to_write).unwrap(); + } + let result = w.finish().unwrap(); + let mut r = read::ZlibDecoder::new(&result[..]); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, real); + } + + #[test] + fn drop_writes() { + let mut data = Vec::new(); + write::ZlibEncoder::new(&mut data, Compression::default()) + .write_all(b"foo") + .unwrap(); + let mut r = read::ZlibDecoder::new(&data[..]); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, b"foo"); + } + + #[test] + fn total_in() { + let mut real = Vec::new(); + let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); + let v = crate::random_bytes().take(1024).collect::<Vec<_>>(); + for _ in 0..200 { + let to_write = &v[..thread_rng().gen_range(0..v.len())]; + real.extend(to_write.iter().copied()); + w.write_all(to_write).unwrap(); + } + let mut result = w.finish().unwrap(); + + let result_len = result.len(); + + for _ in 0..200 { + result.extend(v.iter().copied()); + } + + let mut r = read::ZlibDecoder::new(&result[..]); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, real); + assert_eq!(r.total_in(), result_len as u64); + } + + #[test] + fn roundtrip2() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut r = read::ZlibDecoder::new(read::ZlibEncoder::new(&v[..], Compression::default())); + let mut ret = Vec::new(); + r.read_to_end(&mut ret).unwrap(); + assert_eq!(ret, v); + } + + #[test] + fn roundtrip3() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut w = + write::ZlibEncoder::new(write::ZlibDecoder::new(Vec::new()), Compression::default()); + w.write_all(&v).unwrap(); + let w = w.finish().unwrap().finish().unwrap(); + assert_eq!(w, v); + } + + #[test] + fn reset_decoder() { + let v = crate::random_bytes().take(1024 * 1024).collect::<Vec<_>>(); + let mut w = write::ZlibEncoder::new(Vec::new(), Compression::default()); + w.write_all(&v).unwrap(); + let data = w.finish().unwrap(); + + { + let (mut a, mut b, mut c) = (Vec::new(), Vec::new(), Vec::new()); + let mut r = read::ZlibDecoder::new(&data[..]); + r.read_to_end(&mut a).unwrap(); + r.reset(&data); + r.read_to_end(&mut b).unwrap(); + + let mut r = read::ZlibDecoder::new(&data[..]); + r.read_to_end(&mut c).unwrap(); + assert!(a == b && b == c && c == v); + } + + { + let mut w = write::ZlibDecoder::new(Vec::new()); + w.write_all(&data).unwrap(); + let a = w.reset(Vec::new()).unwrap(); + w.write_all(&data).unwrap(); + let b = w.finish().unwrap(); + + let mut w = write::ZlibDecoder::new(Vec::new()); + w.write_all(&data).unwrap(); + let c = w.finish().unwrap(); + assert!(a == b && b == c && c == v); + } + } + + #[test] + fn bad_input() { + // regress tests: previously caused a panic on drop + let mut out: Vec<u8> = Vec::new(); + let data: Vec<u8> = (0..255).cycle().take(1024).collect(); + let mut w = write::ZlibDecoder::new(&mut out); + match w.write_all(&data[..]) { + Ok(_) => panic!("Expected an error to be returned!"), + Err(e) => assert_eq!(e.kind(), io::ErrorKind::InvalidInput), + } + } + + #[test] + fn qc_reader() { + ::quickcheck::quickcheck(test as fn(_) -> _); + + fn test(v: Vec<u8>) -> bool { + let mut r = + read::ZlibDecoder::new(read::ZlibEncoder::new(&v[..], Compression::default())); + let mut v2 = Vec::new(); + r.read_to_end(&mut v2).unwrap(); + v == v2 + } + } + + #[test] + fn qc_writer() { + ::quickcheck::quickcheck(test as fn(_) -> _); + + fn test(v: Vec<u8>) -> bool { + let mut w = write::ZlibEncoder::new( + write::ZlibDecoder::new(Vec::new()), + Compression::default(), + ); + w.write_all(&v).unwrap(); + v == w.finish().unwrap().finish().unwrap() + } + } +} diff --git a/vendor/flate2/src/zlib/read.rs b/vendor/flate2/src/zlib/read.rs new file mode 100644 index 0000000..3b41ae6 --- /dev/null +++ b/vendor/flate2/src/zlib/read.rs @@ -0,0 +1,275 @@ +use std::io; +use std::io::prelude::*; + +use super::bufread; +use crate::bufreader::BufReader; +use crate::Decompress; + +/// A ZLIB encoder, or compressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// uncompressed data from the underlying [`Read`] and provides the compressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use flate2::Compression; +/// use flate2::read::ZlibEncoder; +/// use std::fs::File; +/// +/// // Open example file and compress the contents using Read interface +/// +/// # fn open_hello_world() -> std::io::Result<Vec<u8>> { +/// let f = File::open("examples/hello_world.txt")?; +/// let mut z = ZlibEncoder::new(f, Compression::fast()); +/// let mut buffer = Vec::new(); +/// z.read_to_end(&mut buffer)?; +/// # Ok(buffer) +/// # } +/// ``` +#[derive(Debug)] +pub struct ZlibEncoder<R> { + inner: bufread::ZlibEncoder<BufReader<R>>, +} + +impl<R: Read> ZlibEncoder<R> { + /// Creates a new encoder which will read uncompressed data from the given + /// stream and emit the compressed stream. + pub fn new(r: R, level: crate::Compression) -> ZlibEncoder<R> { + ZlibEncoder { + inner: bufread::ZlibEncoder::new(BufReader::new(r), level), + } + } + + /// Creates a new encoder with the given `compression` settings which will + /// read uncompressed data from the given stream `r` and emit the compressed stream. + pub fn new_with_compress(r: R, compression: crate::Compress) -> ZlibEncoder<R> { + ZlibEncoder { + inner: bufread::ZlibEncoder::new_with_compress(BufReader::new(r), compression), + } + } +} + +impl<R> ZlibEncoder<R> { + /// Resets the state of this encoder entirely, swapping out the input + /// stream for another. + /// + /// This function will reset the internal state of this encoder and replace + /// the input stream with the one provided, returning the previous input + /// stream. Future data read from this encoder will be the compressed + /// version of `r`'s data. + /// + /// Note that there may be currently buffered data when this function is + /// called, and in that case the buffered data is discarded. + pub fn reset(&mut self, r: R) -> R { + super::bufread::reset_encoder_data(&mut self.inner); + self.inner.get_mut().reset(r) + } + + /// Acquires a reference to the underlying stream + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this encoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Consumes this encoder, returning the underlying reader. + /// + /// Note that there may be buffered bytes which are not re-acquired as part + /// of this transition. It's recommended to only call this function after + /// EOF has been reached. + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } + + /// Returns the number of bytes that have been read into this compressor. + /// + /// Note that not all bytes read from the underlying object may be accounted + /// for, there may still be some active buffering. + pub fn total_in(&self) -> u64 { + self.inner.total_in() + } + + /// Returns the number of bytes that the compressor has produced. + /// + /// Note that not all bytes may have been read yet, some may still be + /// buffered. + pub fn total_out(&self) -> u64 { + self.inner.total_out() + } +} + +impl<R: Read> Read for ZlibEncoder<R> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.read(buf) + } +} + +impl<W: Read + Write> Write for ZlibEncoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} + +/// A ZLIB decoder, or decompressor. +/// +/// This structure implements a [`Read`] interface. When read from, it reads +/// compressed data from the underlying [`Read`] and provides the uncompressed data. +/// +/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::ZlibEncoder; +/// use flate2::read::ZlibDecoder; +/// +/// # fn main() { +/// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error +/// // Here &[u8] implements Read +/// +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut z = ZlibDecoder::new(&bytes[..]); +/// let mut s = String::new(); +/// z.read_to_string(&mut s)?; +/// Ok(s) +/// } +/// ``` +#[derive(Debug)] +pub struct ZlibDecoder<R> { + inner: bufread::ZlibDecoder<BufReader<R>>, +} + +impl<R: Read> ZlibDecoder<R> { + /// Creates a new decoder which will decompress data read from the given + /// stream. + pub fn new(r: R) -> ZlibDecoder<R> { + ZlibDecoder::new_with_buf(r, vec![0; 32 * 1024]) + } + + /// Creates a new decoder which will decompress data read from the given + /// stream `r`, using `buf` as backing to speed up reading. + /// + /// Note that the specified buffer will only be used up to its current + /// length. The buffer's capacity will also not grow over time. + pub fn new_with_buf(r: R, buf: Vec<u8>) -> ZlibDecoder<R> { + ZlibDecoder { + inner: bufread::ZlibDecoder::new(BufReader::with_buf(buf, r)), + } + } + + /// Creates a new decoder which will decompress data read from the given + /// stream `r`, along with `decompression` settings. + pub fn new_with_decompress(r: R, decompression: Decompress) -> ZlibDecoder<R> { + ZlibDecoder::new_with_decompress_and_buf(r, vec![0; 32 * 1024], decompression) + } + + /// Creates a new decoder which will decompress data read from the given + /// stream `r`, using `buf` as backing to speed up reading, + /// along with `decompression` settings to configure decoder. + /// + /// Note that the specified buffer will only be used up to its current + /// length. The buffer's capacity will also not grow over time. + pub fn new_with_decompress_and_buf( + r: R, + buf: Vec<u8>, + decompression: Decompress, + ) -> ZlibDecoder<R> { + ZlibDecoder { + inner: bufread::ZlibDecoder::new_with_decompress( + BufReader::with_buf(buf, r), + decompression, + ), + } + } +} + +impl<R> ZlibDecoder<R> { + /// Resets the state of this decoder entirely, swapping out the input + /// stream for another. + /// + /// This will reset the internal state of this decoder and replace the + /// input stream with the one provided, returning the previous input + /// stream. Future data read from this decoder will be the decompressed + /// version of `r`'s data. + /// + /// Note that there may be currently buffered data when this function is + /// called, and in that case the buffered data is discarded. + pub fn reset(&mut self, r: R) -> R { + super::bufread::reset_decoder_data(&mut self.inner); + self.inner.get_mut().reset(r) + } + + /// Acquires a reference to the underlying stream + pub fn get_ref(&self) -> &R { + self.inner.get_ref().get_ref() + } + + /// Acquires a mutable reference to the underlying stream + /// + /// Note that mutation of the stream may result in surprising results if + /// this decoder is continued to be used. + pub fn get_mut(&mut self) -> &mut R { + self.inner.get_mut().get_mut() + } + + /// Consumes this decoder, returning the underlying reader. + /// + /// Note that there may be buffered bytes which are not re-acquired as part + /// of this transition. It's recommended to only call this function after + /// EOF has been reached. + pub fn into_inner(self) -> R { + self.inner.into_inner().into_inner() + } + + /// Returns the number of bytes that the decompressor has consumed. + /// + /// Note that this will likely be smaller than what the decompressor + /// actually read from the underlying stream due to buffering. + pub fn total_in(&self) -> u64 { + self.inner.total_in() + } + + /// Returns the number of bytes that the decompressor has produced. + pub fn total_out(&self) -> u64 { + self.inner.total_out() + } +} + +impl<R: Read> Read for ZlibDecoder<R> { + fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { + self.inner.read(into) + } +} + +impl<R: Read + Write> Write for ZlibDecoder<R> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.get_mut().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.get_mut().flush() + } +} diff --git a/vendor/flate2/src/zlib/write.rs b/vendor/flate2/src/zlib/write.rs new file mode 100644 index 0000000..d8ad2f2 --- /dev/null +++ b/vendor/flate2/src/zlib/write.rs @@ -0,0 +1,340 @@ +use std::io; +use std::io::prelude::*; + +use crate::zio; +use crate::{Compress, Decompress}; + +/// A ZLIB encoder, or compressor. +/// +/// This structure implements a [`Write`] interface and takes a stream of +/// uncompressed data, writing the compressed data to the wrapped writer. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use flate2::Compression; +/// use flate2::write::ZlibEncoder; +/// +/// // Vec<u8> implements Write, assigning the compressed bytes of sample string +/// +/// # fn zlib_encoding() -> std::io::Result<()> { +/// let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); +/// e.write_all(b"Hello World")?; +/// let compressed = e.finish()?; +/// # Ok(()) +/// # } +/// ``` +#[derive(Debug)] +pub struct ZlibEncoder<W: Write> { + inner: zio::Writer<W, Compress>, +} + +impl<W: Write> ZlibEncoder<W> { + /// Creates a new encoder which will write compressed data to the stream + /// given at the given compression level. + /// + /// When this encoder is dropped or unwrapped the final pieces of data will + /// be flushed. + pub fn new(w: W, level: crate::Compression) -> ZlibEncoder<W> { + ZlibEncoder { + inner: zio::Writer::new(w, Compress::new(level, true)), + } + } + + /// Creates a new encoder which will write compressed data to the stream + /// `w` with the given `compression` settings. + pub fn new_with_compress(w: W, compression: Compress) -> ZlibEncoder<W> { + ZlibEncoder { + inner: zio::Writer::new(w, compression), + } + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutating the output/input state of the stream may corrupt this + /// object, so care must be taken when using this method. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Resets the state of this encoder entirely, swapping out the output + /// stream for another. + /// + /// This function will finish encoding the current stream into the current + /// output stream before swapping out the two output streams. + /// + /// After the current stream has been finished, this will reset the internal + /// state of this encoder and replace the output stream with the one + /// provided, returning the previous output stream. Future data written to + /// this encoder will be the compressed into the stream `w` provided. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn reset(&mut self, w: W) -> io::Result<W> { + self.inner.finish()?; + self.inner.data.reset(); + Ok(self.inner.replace(w)) + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn try_finish(&mut self) -> io::Result<()> { + self.inner.finish() + } + + /// Consumes this encoder, flushing the output stream. + /// + /// This will flush the underlying data stream, close off the compressed + /// stream and, if successful, return the contained writer. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(mut self) -> io::Result<W> { + self.inner.finish()?; + Ok(self.inner.take_inner()) + } + + /// Consumes this encoder, flushing the output stream. + /// + /// This will flush the underlying data stream and then return the contained + /// writer if the flush succeeded. + /// The compressed stream will not closed but only flushed. This + /// means that obtained byte array can by extended by another deflated + /// stream. To close the stream add the two bytes 0x3 and 0x0. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn flush_finish(mut self) -> io::Result<W> { + self.inner.flush()?; + Ok(self.inner.take_inner()) + } + + /// Returns the number of bytes that have been written to this compressor. + /// + /// Note that not all bytes written to this object may be accounted for, + /// there may still be some active buffering. + pub fn total_in(&self) -> u64 { + self.inner.data.total_in() + } + + /// Returns the number of bytes that the compressor has produced. + /// + /// Note that not all bytes may have been written yet, some may still be + /// buffered. + pub fn total_out(&self) -> u64 { + self.inner.data.total_out() + } +} + +impl<W: Write> Write for ZlibEncoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.inner.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl<W: Read + Write> Read for ZlibEncoder<W> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.get_mut().read(buf) + } +} + +/// A ZLIB decoder, or decompressor. +/// +/// This structure implements a [`Write`] and will emit a stream of decompressed +/// data when fed a stream of compressed data. +/// +/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html +/// +/// # Examples +/// +/// ``` +/// use std::io::prelude::*; +/// use std::io; +/// # use flate2::Compression; +/// # use flate2::write::ZlibEncoder; +/// use flate2::write::ZlibDecoder; +/// +/// # fn main() { +/// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); +/// # e.write_all(b"Hello World").unwrap(); +/// # let bytes = e.finish().unwrap(); +/// # println!("{}", decode_reader(bytes).unwrap()); +/// # } +/// # +/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error +/// // Here Vec<u8> implements Write +/// +/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { +/// let mut writer = Vec::new(); +/// let mut z = ZlibDecoder::new(writer); +/// z.write_all(&bytes[..])?; +/// writer = z.finish()?; +/// let return_string = String::from_utf8(writer).expect("String parsing error"); +/// Ok(return_string) +/// } +/// ``` +#[derive(Debug)] +pub struct ZlibDecoder<W: Write> { + inner: zio::Writer<W, Decompress>, +} + +impl<W: Write> ZlibDecoder<W> { + /// Creates a new decoder which will write uncompressed data to the stream. + /// + /// When this decoder is dropped or unwrapped the final pieces of data will + /// be flushed. + pub fn new(w: W) -> ZlibDecoder<W> { + ZlibDecoder { + inner: zio::Writer::new(w, Decompress::new(true)), + } + } + + /// Creates a new decoder which will write uncompressed data to the stream `w` + /// using the given `decompression` settings. + /// + /// When this decoder is dropped or unwrapped the final pieces of data will + /// be flushed. + pub fn new_with_decompress(w: W, decompression: Decompress) -> ZlibDecoder<W> { + ZlibDecoder { + inner: zio::Writer::new(w, decompression), + } + } + + /// Acquires a reference to the underlying writer. + pub fn get_ref(&self) -> &W { + self.inner.get_ref() + } + + /// Acquires a mutable reference to the underlying writer. + /// + /// Note that mutating the output/input state of the stream may corrupt this + /// object, so care must be taken when using this method. + pub fn get_mut(&mut self) -> &mut W { + self.inner.get_mut() + } + + /// Resets the state of this decoder entirely, swapping out the output + /// stream for another. + /// + /// This will reset the internal state of this decoder and replace the + /// output stream with the one provided, returning the previous output + /// stream. Future data written to this decoder will be decompressed into + /// the output stream `w`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn reset(&mut self, w: W) -> io::Result<W> { + self.inner.finish()?; + self.inner.data = Decompress::new(true); + Ok(self.inner.replace(w)) + } + + /// Attempt to finish this output stream, writing out final chunks of data. + /// + /// Note that this function can only be used once data has finished being + /// written to the output stream. After this function is called then further + /// calls to `write` may result in a panic. + /// + /// # Panics + /// + /// Attempts to write data to this stream may result in a panic after this + /// function is called. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn try_finish(&mut self) -> io::Result<()> { + self.inner.finish() + } + + /// Consumes this encoder, flushing the output stream. + /// + /// This will flush the underlying data stream and then return the contained + /// writer if the flush succeeded. + /// + /// Note that this function may not be suitable to call in a situation where + /// the underlying stream is an asynchronous I/O stream. To finish a stream + /// the `try_finish` (or `shutdown`) method should be used instead. To + /// re-acquire ownership of a stream it is safe to call this method after + /// `try_finish` or `shutdown` has returned `Ok`. + /// + /// # Errors + /// + /// This function will perform I/O to complete this stream, and any I/O + /// errors which occur will be returned from this function. + pub fn finish(mut self) -> io::Result<W> { + self.inner.finish()?; + Ok(self.inner.take_inner()) + } + + /// Returns the number of bytes that the decompressor has consumed for + /// decompression. + /// + /// Note that this will likely be smaller than the number of bytes + /// successfully written to this stream due to internal buffering. + pub fn total_in(&self) -> u64 { + self.inner.data.total_in() + } + + /// Returns the number of bytes that the decompressor has written to its + /// output stream. + pub fn total_out(&self) -> u64 { + self.inner.data.total_out() + } +} + +impl<W: Write> Write for ZlibDecoder<W> { + fn write(&mut self, buf: &[u8]) -> io::Result<usize> { + self.inner.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} + +impl<W: Read + Write> Read for ZlibDecoder<W> { + fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { + self.inner.get_mut().read(buf) + } +} |