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 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 { inner: zio::Writer, } impl ZlibEncoder { /// 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 { 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 { 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 { 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 { 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 { 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 Write for ZlibEncoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } impl Read for ZlibEncoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.get_mut().read(buf) } } /// A ZLIB decoder, or decompressor. /// /// This structure implements a [`Write`] and will emit a stream of decompressed /// data when fed a stream of compressed data. /// /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html /// /// # Examples /// /// ``` /// use std::io::prelude::*; /// use std::io; /// # use flate2::Compression; /// # use flate2::write::ZlibEncoder; /// use flate2::write::ZlibDecoder; /// /// # fn main() { /// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default()); /// # e.write_all(b"Hello World").unwrap(); /// # let bytes = e.finish().unwrap(); /// # println!("{}", decode_reader(bytes).unwrap()); /// # } /// # /// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error /// // Here Vec implements Write /// /// fn decode_reader(bytes: Vec) -> io::Result { /// 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 { inner: zio::Writer, } impl ZlibDecoder { /// 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 { 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 { 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 { 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 { 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 Write for ZlibDecoder { fn write(&mut self, buf: &[u8]) -> io::Result { self.inner.write(buf) } fn flush(&mut self) -> io::Result<()> { self.inner.flush() } } impl Read for ZlibDecoder { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.inner.get_mut().read(buf) } }