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 exposes a [`Read`] interface that will read uncompressed data /// from the underlying reader and expose the compressed version as a [`Read`] /// interface. /// /// [`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> { /// let mut ret_vec = [0;100]; /// let bytestring = b"hello world"; /// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast()); /// let count = gz.read(&mut ret_vec)?; /// Ok(ret_vec[0..count].to_vec()) /// } /// ``` #[derive(Debug)] pub struct GzEncoder { inner: bufread::GzEncoder>, } pub fn gz_encoder(inner: bufread::GzEncoder>) -> GzEncoder { GzEncoder { inner } } impl GzEncoder { /// 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 { GzBuilder::new().read(r, level) } } impl GzEncoder { /// 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 Read for GzEncoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for GzEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder /// /// This structure exposes a [`Read`] interface that will consume compressed /// data from the underlying reader and emit uncompressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::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) -> io::Result { /// let mut gz = GzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct GzDecoder { inner: bufread::GzDecoder>, } impl GzDecoder { /// Creates a new decoder from the given reader, immediately parsing the /// gzip header. pub fn new(r: R) -> GzDecoder { GzDecoder { inner: bufread::GzDecoder::new(BufReader::new(r)), } } } impl GzDecoder { /// 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. 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 Read for GzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for GzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } } /// A gzip streaming decoder that decodes all members of a multistream /// /// A gzip member consists of a header, compressed data and a trailer. The [gzip /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple /// gzip members to be joined in a single stream. `MultiGzDecoder` will /// decode all consecutive members while `GzDecoder` will only decompress the /// first gzip member. The multistream format is commonly used in bioinformatics, /// for example when using the BGZF compressed data. /// /// This structure exposes a [`Read`] interface that will consume all gzip members /// from the underlying reader and emit uncompressed data. /// /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::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) -> io::Result { /// let mut gz = MultiGzDecoder::new(&bytes[..]); /// let mut s = String::new(); /// gz.read_to_string(&mut s)?; /// Ok(s) /// } /// ``` #[derive(Debug)] pub struct MultiGzDecoder { inner: bufread::MultiGzDecoder>, } impl MultiGzDecoder { /// 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 { MultiGzDecoder { inner: bufread::MultiGzDecoder::new(BufReader::new(r)), } } } impl MultiGzDecoder { /// 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 Read for MultiGzDecoder { fn read(&mut self, into: &mut [u8]) -> io::Result { self.inner.read(into) } } impl Write for MultiGzDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.get_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.get_mut().flush() } }