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