Skip to main content

flate2/zlib/
bufread.rs

1use crate::io;
2use crate::io::{BufRead, Read, Write};
3use core::mem;
4
5use crate::zio;
6use crate::{Compress, Decompress};
7
8/// A ZLIB encoder, or compressor.
9///
10/// This structure implements a [`Read`] interface. When read from, it reads
11/// uncompressed data from the underlying [`BufRead`] and provides the compressed data.
12///
13/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
14/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
15///
16/// # Examples
17///
18/// ```
19/// use std::io::prelude::*;
20/// use flate2::Compression;
21/// use flate2::bufread::ZlibEncoder;
22/// use std::fs::File;
23/// use std::io::BufReader;
24///
25/// // Use a buffered file to compress contents into a Vec<u8>
26///
27/// # fn open_hello_world() -> std::io::Result<Vec<u8>> {
28/// let f = File::open("examples/hello_world.txt")?;
29/// let b = BufReader::new(f);
30/// let mut z = ZlibEncoder::new(b, Compression::fast());
31/// let mut buffer = Vec::new();
32/// z.read_to_end(&mut buffer)?;
33/// # Ok(buffer)
34/// # }
35/// ```
36#[derive(Debug)]
37pub struct ZlibEncoder<R> {
38    obj: R,
39    data: Compress,
40}
41
42impl<R: BufRead> ZlibEncoder<R> {
43    /// Creates a new encoder which will read uncompressed data from the given
44    /// stream and emit the compressed stream.
45    pub fn new(r: R, level: crate::Compression) -> ZlibEncoder<R> {
46        ZlibEncoder {
47            obj: r,
48            data: Compress::new(level, true),
49        }
50    }
51
52    /// Creates a new encoder with the given `compression` settings which will
53    /// read uncompressed data from the given stream `r` and emit the compressed stream.
54    pub fn new_with_compress(r: R, compression: Compress) -> ZlibEncoder<R> {
55        ZlibEncoder {
56            obj: r,
57            data: compression,
58        }
59    }
60}
61
62pub fn reset_encoder_data<R>(zlib: &mut ZlibEncoder<R>) {
63    zlib.data.reset()
64}
65
66impl<R> ZlibEncoder<R> {
67    /// Resets the state of this encoder entirely, swapping out the input
68    /// stream for another.
69    ///
70    /// This function will reset the internal state of this encoder and replace
71    /// the input stream with the one provided, returning the previous input
72    /// stream. Future data read from this encoder will be the compressed
73    /// version of `r`'s data.
74    pub fn reset(&mut self, r: R) -> R {
75        reset_encoder_data(self);
76        mem::replace(&mut self.obj, r)
77    }
78
79    /// Acquires a reference to the underlying reader
80    pub fn get_ref(&self) -> &R {
81        &self.obj
82    }
83
84    /// Acquires a mutable reference to the underlying stream
85    ///
86    /// The underlying reader may be mutated as long as its unread input and
87    /// current position are preserved for subsequent reads by this encoder.
88    ///
89    /// To process a new stream, wait for this encoder to reach EOF and use
90    /// [`reset`](Self::reset); replacing the reader directly does not reset it.
91    pub fn get_mut(&mut self) -> &mut R {
92        &mut self.obj
93    }
94
95    /// Consumes this encoder, returning the underlying reader.
96    pub fn into_inner(self) -> R {
97        self.obj
98    }
99
100    /// Returns the number of bytes that have been read into this compressor.
101    ///
102    /// Note that not all bytes read from the underlying object may be accounted
103    /// for, there may still be some active buffering.
104    pub fn total_in(&self) -> u64 {
105        self.data.total_in()
106    }
107
108    /// Returns the number of bytes that the compressor has produced.
109    ///
110    /// Note that not all bytes may have been read yet, some may still be
111    /// buffered.
112    pub fn total_out(&self) -> u64 {
113        self.data.total_out()
114    }
115}
116
117impl<R: BufRead> Read for ZlibEncoder<R> {
118    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
119        zio::read(&mut self.obj, &mut self.data, buf)
120    }
121}
122
123impl<R: BufRead + Write> Write for ZlibEncoder<R> {
124    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
125        self.get_mut().write(buf)
126    }
127
128    fn flush(&mut self) -> io::Result<()> {
129        self.get_mut().flush()
130    }
131}
132
133/// A ZLIB decoder, or decompressor.
134///
135/// This structure implements a [`Read`] interface. When read from, it reads
136/// compressed data from the underlying [`BufRead`] and provides the uncompressed data.
137///
138/// After reading a single member of the ZLIB data this reader will return
139/// Ok(0) even if there are more bytes available in the underlying reader.
140/// If you need the following bytes, call `into_inner()` after Ok(0) to
141/// recover the underlying reader.
142///
143/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
144/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
145///
146/// # Examples
147///
148/// ```
149/// use std::io::prelude::*;
150/// use std::io;
151/// # use flate2::Compression;
152/// # use flate2::write::ZlibEncoder;
153/// use flate2::bufread::ZlibDecoder;
154///
155/// # fn main() {
156/// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
157/// # e.write_all(b"Hello World").unwrap();
158/// # let bytes = e.finish().unwrap();
159/// # println!("{}", decode_bufreader(bytes).unwrap());
160/// # }
161/// #
162/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error
163/// // Here &[u8] implements BufRead
164///
165/// fn decode_bufreader(bytes: Vec<u8>) -> io::Result<String> {
166///     let mut z = ZlibDecoder::new(&bytes[..]);
167///     let mut s = String::new();
168///     z.read_to_string(&mut s)?;
169///     Ok(s)
170/// }
171/// ```
172#[derive(Debug)]
173pub struct ZlibDecoder<R> {
174    obj: R,
175    data: Decompress,
176}
177
178impl<R: BufRead> ZlibDecoder<R> {
179    /// Creates a new decoder which will decompress data read from the given
180    /// stream.
181    pub fn new(r: R) -> ZlibDecoder<R> {
182        ZlibDecoder {
183            obj: r,
184            data: Decompress::new(true),
185        }
186    }
187
188    /// Creates a new decoder which will decompress data read from the given
189    /// stream, using the given `decompression` settings.
190    pub fn new_with_decompress(r: R, decompression: Decompress) -> ZlibDecoder<R> {
191        ZlibDecoder {
192            obj: r,
193            data: decompression,
194        }
195    }
196}
197
198pub fn reset_decoder_data<R>(zlib: &mut ZlibDecoder<R>) {
199    zlib.data.reset(true);
200}
201
202impl<R> ZlibDecoder<R> {
203    /// Resets the state of this decoder entirely, swapping out the input
204    /// stream for another.
205    ///
206    /// This will reset the internal state of this decoder and replace the
207    /// input stream with the one provided, returning the previous input
208    /// stream. Future data read from this decoder will be the decompressed
209    /// version of `r`'s data.
210    pub fn reset(&mut self, r: R) -> R {
211        reset_decoder_data(self);
212        mem::replace(&mut self.obj, r)
213    }
214
215    /// Acquires a reference to the underlying stream
216    pub fn get_ref(&self) -> &R {
217        &self.obj
218    }
219
220    /// Acquires a mutable reference to the underlying stream
221    ///
222    /// The underlying reader may be mutated as long as its unread input and
223    /// current position are preserved for subsequent reads by this decoder.
224    ///
225    /// To process a new stream, wait for this decoder to reach EOF and use
226    /// [`reset`](Self::reset); replacing the reader directly does not reset it.
227    pub fn get_mut(&mut self) -> &mut R {
228        &mut self.obj
229    }
230
231    /// Consumes this decoder, returning the underlying reader.
232    pub fn into_inner(self) -> R {
233        self.obj
234    }
235
236    /// Returns the number of bytes that the decompressor has consumed.
237    ///
238    /// Note that this will likely be smaller than what the decompressor
239    /// actually read from the underlying stream due to buffering.
240    pub fn total_in(&self) -> u64 {
241        self.data.total_in()
242    }
243
244    /// Returns the number of bytes that the decompressor has produced.
245    pub fn total_out(&self) -> u64 {
246        self.data.total_out()
247    }
248}
249
250impl<R: BufRead> Read for ZlibDecoder<R> {
251    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
252        zio::read(&mut self.obj, &mut self.data, into)
253    }
254}
255
256impl<R: BufRead + Write> Write for ZlibDecoder<R> {
257    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
258        self.get_mut().write(buf)
259    }
260
261    fn flush(&mut self) -> io::Result<()> {
262        self.get_mut().flush()
263    }
264}
265
266#[cfg(test)]
267mod test {
268    use crate::bufread::ZlibDecoder;
269    use crate::io::{Read, Write};
270    use crate::zlib::write;
271    use crate::Compression;
272    use alloc::vec::Vec;
273
274    // ZlibDecoder consumes one zlib archive and then returns 0 for subsequent reads, allowing any
275    // additional data to be consumed by the caller.
276    #[test]
277    fn decode_extra_data() {
278        let expected = "Hello World";
279
280        let compressed = {
281            let mut e = write::ZlibEncoder::new(Vec::new(), Compression::default());
282            e.write_all(expected.as_ref()).unwrap();
283            let mut b = e.finish().unwrap();
284            b.push(b'x');
285            b
286        };
287
288        let mut output = Vec::new();
289        let mut decoder = ZlibDecoder::new(compressed.as_slice());
290        let decoded_bytes = decoder.read_to_end(&mut output).unwrap();
291        assert_eq!(decoded_bytes, output.len());
292        let actual = core::str::from_utf8(&output).expect("String parsing error");
293        assert_eq!(
294            actual, expected,
295            "after decompression we obtain the original input"
296        );
297
298        output.clear();
299        assert_eq!(
300            decoder.read(&mut output).unwrap(),
301            0,
302            "subsequent read of decoder returns 0, but inner reader can return additional data"
303        );
304        let mut reader = decoder.into_inner();
305        assert_eq!(
306            reader.read_to_end(&mut output).unwrap(),
307            1,
308            "extra data is accessible in underlying buf-read"
309        );
310        assert_eq!(output, b"x");
311    }
312}