| use std::io; |
| use std::io::prelude::*; |
| |
| #[cfg(feature = "tokio")] |
| use futures::Poll; |
| #[cfg(feature = "tokio")] |
| use tokio_io::{AsyncRead, AsyncWrite}; |
| |
| 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<Vec<u8>> { |
| /// 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<R> { |
| inner: bufread::GzEncoder<BufReader<R>>, |
| } |
| |
| pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> { |
| GzEncoder { inner: 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 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<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. |
| 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 decoder, returning the underlying reader. |
| 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) |
| } |
| } |
| |
| #[cfg(feature = "tokio")] |
| impl<R: AsyncRead> AsyncRead for GzDecoder<R> {} |
| |
| 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() |
| } |
| } |
| |
| #[cfg(feature = "tokio")] |
| impl<R: AsyncWrite + AsyncRead> AsyncWrite for GzDecoder<R> { |
| fn shutdown(&mut self) -> Poll<(), io::Error> { |
| self.get_mut().shutdown() |
| } |
| } |
| |
| /// 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<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 encoder 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) |
| } |
| } |
| |
| #[cfg(feature = "tokio")] |
| impl<R: AsyncRead> AsyncRead for MultiGzDecoder<R> {} |
| |
| 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(feature = "tokio")] |
| impl<R: AsyncWrite + AsyncRead> AsyncWrite for MultiGzDecoder<R> { |
| fn shutdown(&mut self) -> Poll<(), io::Error> { |
| self.get_mut().shutdown() |
| } |
| } |