Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

104
vendor/flate2/src/bufreader.rs vendored Normal file
View File

@@ -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);
}
}

175
vendor/flate2/src/crc.rs vendored Normal file
View File

@@ -0,0 +1,175 @@
//! 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, Default)]
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 Crc {
/// Create a new CRC.
pub fn new() -> Self {
Self::default()
}
/// 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()
}
}

297
vendor/flate2/src/deflate/bufread.rs vendored Normal file
View File

@@ -0,0 +1,297 @@
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.
///
/// After reading a single member of the DEFLATE 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.
///
/// [`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()
}
}
#[cfg(test)]
mod test {
use crate::bufread::DeflateDecoder;
use crate::deflate::write;
use crate::Compression;
use std::io::{Read, Write};
// DeflateDecoder consumes one deflate archive 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::DeflateEncoder::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 = DeflateDecoder::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");
}
}

193
vendor/flate2/src/deflate/mod.rs vendored Normal file
View File

@@ -0,0 +1,193 @@
pub mod bufread;
pub mod read;
pub mod write;
#[cfg(test)]
mod tests {
use std::io::prelude::*;
use rand::{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[..rng().random_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[..rng().random_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()
}
}
}

247
vendor/flate2/src/deflate/read.rs vendored Normal file
View File

@@ -0,0 +1,247 @@
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.
///
/// After reading a single member of the DEFLATE data this reader will return
/// Ok(0) even if there are more bytes available in the underlying reader.
/// `DeflateDecoder` may have read additional bytes past the end of the DEFLATE data.
/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader`
/// and use `bufread::DeflateDecoder` instead.
///
/// [`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()
}
}

366
vendor/flate2/src/deflate/write.rs vendored Normal file
View File

@@ -0,0 +1,366 @@
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.
///
/// After decoding a single member of the DEFLATE data this writer will return the number of bytes up to
/// to the end of the DEFLATE member and subsequent writes will return Ok(0) allowing the caller to
/// handle any data following the DEFLATE member.
///
/// [`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)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Compression;
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";
// DeflateDecoder consumes one zlib archive 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 = DeflateEncoder::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 = DeflateDecoder::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");
}
}

502
vendor/flate2/src/ffi/c.rs vendored Normal file
View File

@@ -0,0 +1,502 @@
//! Implementation for C backends.
use std::cmp;
use std::fmt;
use std::marker;
use std::os::raw::{c_int, c_uint};
use std::ptr;
use super::*;
use crate::mem;
#[derive(Clone, Default)]
pub struct ErrorMessage(Option<&'static str>);
impl ErrorMessage {
pub fn get(&self) -> Option<&str> {
self.0
}
}
pub struct StreamWrapper {
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure, and it must never be copied
// by Rust.
pub inner: *mut 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 {
// SAFETY: The field `state` will be initialized across the FFI to
// point to the opaque type `mz_internal_state`, which will contain a copy
// of `inner`. This cyclic structure breaks the uniqueness invariant of
// &mut mz_stream, so we must use a raw pointer instead of Box<mz_stream>.
StreamWrapper {
inner: Box::into_raw(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(any(
// zlib-ng
feature = "zlib-ng",
// libz-sys
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs"))
))]
zalloc: allocator::zalloc,
#[cfg(any(
// zlib-ng
feature = "zlib-ng",
// libz-sys
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs"))
))]
zfree: allocator::zfree,
#[cfg(
// cloudflare-zlib
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
)]
zalloc: Some(allocator::zalloc),
#[cfg(
// cloudflare-zlib
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
)]
zfree: Some(allocator::zfree),
// for zlib-rs, it is most efficient to have it provide the allocator.
// The libz-rs-sys dependency is configured to use the rust system allocator
#[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))]
zalloc: None,
#[cfg(all(feature = "zlib-rs", not(feature = "zlib-ng")))]
zfree: None,
})),
}
}
}
impl Drop for StreamWrapper {
fn drop(&mut self) {
// SAFETY: At this point, every other allocation for struct has been freed by
// `inflateEnd` or `deflateEnd`, and no copies of `inner` are retained by `C`,
// so it is safe to drop the struct as long as the user respects the invariant that
// `inner` must never be copied by Rust.
drop(unsafe { Box::from_raw(self.inner) });
}
}
#[cfg(any(
// zlib-ng
feature = "zlib-ng",
// cloudflare-zlib
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
// libz-sys
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")),
))]
mod allocator {
use super::*;
use std::alloc::{self, Layout};
use std::convert::TryFrom;
use std::os::raw::c_void;
const ALIGN: usize = std::mem::align_of::<usize>();
fn align_up(size: usize, align: usize) -> usize {
(size + align - 1) & !(align - 1)
}
pub extern "C" fn zalloc(_ptr: *mut c_void, items: uInt, item_size: uInt) -> *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
}
}
pub 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)
}
}
}
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 {
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure. No copies of `inner` can be
// retained for longer than the lifetime of `self`.
let msg = unsafe { (*self.stream_wrapper.inner).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(self.stream_wrapper.inner);
}
}
}
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 state = StreamWrapper::default();
let ret = mz_inflateInit2(
state.inner,
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 = self.inner.stream_wrapper.inner;
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure. No copies of `inner` can be
// retained for longer than the lifetime of `self`.
unsafe {
(*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 = 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 | MZ_MEM_ERROR => {
mem::decompress_failed(self.inner.msg())
}
MZ_OK => Ok(Status::Ok),
MZ_BUF_ERROR => Ok(Status::BufError),
MZ_STREAM_END => Ok(Status::StreamEnd),
#[allow(clippy::unnecessary_cast)]
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(self.inner.stream_wrapper.inner, 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 state = StreamWrapper::default();
let ret = mz_deflateInit2(
state.inner,
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 = self.inner.stream_wrapper.inner;
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure. No copies of `inner` can be
// retained for longer than the lifetime of `self`.
unsafe {
(*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 = 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(self.inner.stream_wrapper.inner) };
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)]
#[allow(unused_imports)]
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(feature = "zlib-rs", not(feature = "zlib-ng")))]
use libz_rs_sys as libz;
#[cfg(
// cloudflare-zlib
all(feature = "cloudflare_zlib", not(feature = "zlib-rs"), not(feature = "zlib-ng")),
)]
use cloudflare_zlib_sys as libz;
#[cfg(
// libz-sys
all(not(feature = "cloudflare_zlib"), not(feature = "zlib-ng"), not(feature = "zlib-rs")),
)]
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_MEM_ERROR as MZ_MEM_ERROR;
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 const MZ_DEFAULT_WINDOW_BITS: c_int = 15;
#[cfg(feature = "zlib-ng")]
const ZLIB_VERSION: &str = "2.1.0.devel\0";
#[cfg(all(not(feature = "zlib-ng"), feature = "zlib-rs"))]
const ZLIB_VERSION: &str = "1.3.0-zlib-rs-0.5.1\0";
#[cfg(not(any(feature = "zlib-ng", feature = "zlib-rs")))]
const ZLIB_VERSION: &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,
)
}
}

52
vendor/flate2/src/ffi/mod.rs vendored Normal file
View File

@@ -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)
}
}

203
vendor/flate2/src/ffi/rust.rs vendored Normal file
View File

@@ -0,0 +1,203 @@
//! 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(Clone, 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 From<FlushDecompress> for MZFlush {
fn from(value: FlushDecompress) -> Self {
match value {
FlushDecompress::None => Self::None,
FlushDecompress::Sync => Self::Sync,
FlushDecompress::Finish => Self::Finish,
}
}
}
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 mz_flush = flush.into();
let res = inflate::stream::inflate(&mut self.inner, input, output, mz_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 From<FlushCompress> for MZFlush {
fn from(value: FlushCompress) -> Self {
match value {
FlushCompress::None => Self::None,
FlushCompress::Partial | FlushCompress::Sync => Self::Sync,
FlushCompress::Full => Self::Full,
FlushCompress::Finish => Self::Finish,
}
}
}
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 mz_flush = flush.into();
let res = deflate::stream::deflate(&mut self.inner, input, output, mz_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
}
}

482
vendor/flate2/src/gz/bufread.rs vendored Normal file
View File

@@ -0,0 +1,482 @@
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);
into[..min].copy_from_slice(&from[*pos..*pos + min]);
*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 calced_crc_bytes = crc.sum().to_le_bytes();
let arr = [
calced_crc_bytes[0],
calced_crc_bytes[1],
calced_crc_bytes[2],
calced_crc_bytes[3],
crc.amount() 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)
| ((buf[1] as u32) << 8)
| ((buf[2] as u32) << 16)
| ((buf[3] as u32) << 24);
let amt = (buf[4] as u32)
| ((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 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
/// [`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");
}
}

624
vendor/flate2/src/gz/mod.rs vendored Normal file
View File

@@ -0,0 +1,624 @@
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, Default)]
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]),
#[default]
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<R: BufRead>(&mut self, r: &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)
| ((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: BufRead>(r: &mut R, buffer: &mut Vec<u8>) -> Result<()> {
let mut bytes = r.bytes();
loop {
match bytes.next().transpose()? {
Some(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 {
u16::from_le_bytes(*buffer)
}
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, Default)]
pub struct GzBuilder {
extra: Option<Vec<u8>>,
filename: Option<CString>,
comment: Option<CString>,
operating_system: Option<u8>,
mtime: u32,
}
impl GzBuilder {
/// Create a new blank builder with no header by default.
pub fn new() -> GzBuilder {
Self::default()
}
/// 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.extend((v.len() as u16).to_le_bytes());
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 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::{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[..rng().random_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();
}
}

378
vendor/flate2/src/gz/read.rs vendored Normal file
View File

@@ -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 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
///
/// # 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");
}
}
}
}

641
vendor/flate2/src/gz/write.rs vendored Normal file
View File

@@ -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 as u8,
(sum >> 8) as u8,
(sum >> 16) as u8,
(sum >> 24) as u8,
amt 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)
| ((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)
| ((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");
}
}

244
vendor/flate2/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,244 @@
//! 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` to Rust. This feature does not
//! require a C compiler, and only uses safe Rust code.
//!
//! * `zlib-rs` - this implementation utilizes the `zlib-rs` crate, a Rust rewrite of zlib.
//! This backend is the fastest, at the cost of some `unsafe` Rust code.
//!
//! Several backends implemented in C are also available.
//! These are useful in case you are already using a specific C implementation
//! and need the result of compression to be bit-identical.
//! See the crate's README for details on the available C backends.
//!
//! The `zlib-rs` backend typically outperforms all the C implementations.
//!
//! # 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 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".
///
/// ### Backend differences
///
/// The [`miniz_oxide`](https://crates.io/crates/miniz_oxide) backend for flate2
/// does not support level 0 or `Compression::none()`. Instead it interprets them
/// as the default compression level, which is quite slow.
/// `Compression::fast()` should be used instead.
///
/// `miniz_oxide` also supports a non-compliant compression level 10.
/// It is even slower and may result in higher compression, but
/// **only miniz_oxide will be able to read the data** compressed with level 10.
/// Do **not** use level 10 if you need other software to be able to read it!
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. See [`new`](Self::new) for details about compression levels.
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::rng().random())
}

786
vendor/flate2/src/mem.rs vendored Normal file
View File

@@ -0,0 +1,786 @@
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]
#[allow(clippy::unnecessary_cast)]
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, but the output is
/// not aligned to a byte boundary.
///
/// All 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 bytes 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 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 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]
#[allow(clippy::unnecessary_cast)]
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(Clone, 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(Clone, 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(Clone, 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> {
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure. No copies of `inner` can be
// retained for longer than the lifetime of `self.inner.inner.stream_wrapper`.
let stream = self.inner.inner.stream_wrapper.inner;
let rc = unsafe {
(*stream).msg = std::ptr::null_mut();
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()),
#[allow(clippy::unnecessary_cast)]
ffi::MZ_OK => Ok(unsafe { (*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;
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure. No copies of `inner` can be
// retained for longer than the lifetime of `self.inner.inner.stream_wrapper`.
let stream = self.inner.inner.stream_wrapper.inner;
unsafe {
(*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> {
// SAFETY: The field `inner` must always be accessed as a raw pointer,
// since it points to a cyclic structure. No copies of `inner` can be
// retained for longer than the lifetime of `self.inner.inner.stream_wrapper`.
let stream = self.inner.inner.stream_wrapper.inner;
let rc = unsafe {
(*stream).msg = std::ptr::null_mut();
assert!(dictionary.len() < ffi::uInt::MAX as usize);
ffi::inflateSetDictionary(stream, dictionary.as_ptr(), dictionary.len() as ffi::uInt)
};
#[allow(clippy::unnecessary_cast)]
match rc {
ffi::MZ_STREAM_ERROR => decompress_failed(self.inner.inner.msg()),
ffi::MZ_DATA_ERROR => decompress_need_dict(unsafe { (*stream).adler } as u32),
ffi::MZ_OK => Ok(unsafe { (*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"));
}
}

293
vendor/flate2/src/zio.rs vendored Normal file
View File

@@ -0,0 +1,293 @@
use std::io;
use std::io::prelude::*;
use std::mem;
use crate::{
Compress, CompressError, 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 Error: Into<io::Error>;
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, Self::Error>;
fn run_vec(
&mut self,
input: &[u8],
output: &mut Vec<u8>,
flush: Self::Flush,
) -> Result<Status, Self::Error>;
}
impl Ops for Compress {
type Error = CompressError;
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, CompressError> {
self.compress(input, output, flush)
}
fn run_vec(
&mut self,
input: &[u8],
output: &mut Vec<u8>,
flush: FlushCompress,
) -> Result<Status, CompressError> {
self.compress_vec(input, output, flush)
}
}
impl Ops for Decompress {
type Error = DecompressError;
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, Flush::finish())
.map_err(Into::into)?;
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, Flush::sync())
.map_err(Into::into)?;
// 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, Flush::none())
.map_err(Into::into)?;
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();
}
}
}

305
vendor/flate2/src/zlib/bufread.rs vendored Normal file
View File

@@ -0,0 +1,305 @@
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.
///
/// After reading a single member of the ZLIB 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.
///
/// [`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()
}
}
#[cfg(test)]
mod test {
use crate::bufread::ZlibDecoder;
use crate::zlib::write;
use crate::Compression;
use std::io::{Read, Write};
// ZlibDecoder consumes one zlib archive 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::ZlibEncoder::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 = ZlibDecoder::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");
}
}

159
vendor/flate2/src/zlib/mod.rs vendored Normal file
View File

@@ -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::{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[..rng().random_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[..rng().random_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()
}
}
}

281
vendor/flate2/src/zlib/read.rs vendored Normal file
View File

@@ -0,0 +1,281 @@
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.
///
/// After reading a single member of the ZLIB data this reader will return
/// Ok(0) even if there are more bytes available in the underlying reader.
/// `ZlibDecoder` may have read additional bytes past the end of the ZLIB data.
/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader`
/// and use `bufread::ZlibDecoder` instead.
///
/// [`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()
}
}

384
vendor/flate2/src/zlib/write.rs vendored Normal file
View File

@@ -0,0 +1,384 @@
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.
///
/// After decoding a single member of the ZLIB data this writer will return the number of bytes up
/// to the end of the ZLIB member and subsequent writes will return Ok(0) allowing the caller to
/// handle any data following the ZLIB member.
///
/// [`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)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Compression;
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";
// ZlibDecoder consumes one zlib archive 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 = ZlibEncoder::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 = ZlibDecoder::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");
}
}