Skip to main content

flate2/zlib/
write.rs

1use crate::io;
2use crate::io::{Read, Write};
3
4use crate::zio;
5use crate::{Compress, Decompress};
6
7/// A ZLIB encoder, or compressor.
8///
9/// This structure implements a [`Write`] interface and takes a stream of
10/// uncompressed data, writing the compressed data to the wrapped writer.
11///
12/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
13///
14/// # Examples
15///
16/// ```
17/// use std::io::prelude::*;
18/// use flate2::Compression;
19/// use flate2::write::ZlibEncoder;
20///
21/// // Vec<u8> implements Write, assigning the compressed bytes of sample string
22///
23/// # fn zlib_encoding() -> std::io::Result<()> {
24/// let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
25/// e.write_all(b"Hello World")?;
26/// let compressed = e.finish()?;
27/// # Ok(())
28/// # }
29/// ```
30#[derive(Debug)]
31pub struct ZlibEncoder<W: Write> {
32    inner: zio::Writer<W, Compress>,
33}
34
35impl<W: Write> ZlibEncoder<W> {
36    /// Creates a new encoder which will write compressed data to the stream
37    /// given at the given compression level.
38    ///
39    /// When this encoder is dropped or unwrapped the final pieces of data will
40    /// be flushed.
41    pub fn new(w: W, level: crate::Compression) -> ZlibEncoder<W> {
42        ZlibEncoder {
43            inner: zio::Writer::new(w, Compress::new(level, true)),
44        }
45    }
46
47    /// Creates a new encoder which will write compressed data to the stream
48    /// `w` with the given `compression` settings.
49    pub fn new_with_compress(w: W, compression: Compress) -> ZlibEncoder<W> {
50        ZlibEncoder {
51            inner: zio::Writer::new(w, compression),
52        }
53    }
54
55    /// Acquires a reference to the underlying writer.
56    pub fn get_ref(&self) -> &W {
57        self.inner.get_ref()
58    }
59
60    /// Acquires a mutable reference to the underlying writer.
61    ///
62    /// The underlying writer may be mutated or replaced as long as this
63    /// preserves the bytes and ordering of the logical output stream.
64    /// Concatenate output from each writer to reconstruct the complete stream.
65    ///
66    /// Replacing the writer does not require [`flush`](Write::flush). Call it
67    /// first when all input accepted so far must be decodable without output
68    /// from later writes. This inserts a sync-flush point and changes the output
69    /// bitstream. This is useful before applying [`std::mem::take`] to
70    /// [`get_mut`](Self::get_mut) when forwarding the stream incrementally.
71    ///
72    /// To start a new stream, use [`reset`](Self::reset); replacing the writer
73    /// does not reset this encoder.
74    pub fn get_mut(&mut self) -> &mut W {
75        self.inner.get_mut()
76    }
77
78    /// Resets the state of this encoder entirely, swapping out the output
79    /// stream for another.
80    ///
81    /// This function will finish encoding the current stream into the current
82    /// output stream before swapping out the two output streams.
83    ///
84    /// After the current stream has been finished, this will reset the internal
85    /// state of this encoder and replace the output stream with the one
86    /// provided, returning the previous output stream. Future data written to
87    /// this encoder will be the compressed into the stream `w` provided.
88    ///
89    /// # Errors
90    ///
91    /// This function will perform I/O to complete this stream, and any I/O
92    /// errors which occur will be returned from this function.
93    pub fn reset(&mut self, w: W) -> io::Result<W> {
94        self.inner.finish()?;
95        self.inner.data.reset();
96        Ok(self.inner.replace(w))
97    }
98
99    /// Attempt to finish this output stream, writing out final chunks of data.
100    ///
101    /// Note that this function can only be used once data has finished being
102    /// written to the output stream. After this function is called then further
103    /// calls to `write` may result in a panic.
104    ///
105    /// # Panics
106    ///
107    /// Attempts to write data to this stream may result in a panic after this
108    /// function is called.
109    ///
110    /// # Errors
111    ///
112    /// This function will perform I/O to complete this stream, and any I/O
113    /// errors which occur will be returned from this function.
114    pub fn try_finish(&mut self) -> io::Result<()> {
115        self.inner.finish()
116    }
117
118    /// Consumes this encoder, flushing the output stream.
119    ///
120    /// This will flush the underlying data stream, close off the compressed
121    /// stream and, if successful, return the contained writer.
122    ///
123    /// Note that this function may not be suitable to call in a situation where
124    /// the underlying stream is an asynchronous I/O stream. To finish a stream
125    /// the `try_finish` (or `shutdown`) method should be used instead. To
126    /// re-acquire ownership of a stream it is safe to call this method after
127    /// `try_finish` or `shutdown` has returned `Ok`.
128    ///
129    /// # Errors
130    ///
131    /// This function will perform I/O to complete this stream, and any I/O
132    /// errors which occur will be returned from this function.
133    pub fn finish(mut self) -> io::Result<W> {
134        self.inner.finish()?;
135        Ok(self.inner.take_inner())
136    }
137
138    /// Consumes this encoder, flushing the output stream.
139    ///
140    /// This will flush the underlying data stream and then return the contained
141    /// writer if the flush succeeded.
142    /// The compressed stream will not be closed but only flushed. This
143    /// means that obtained byte array can by extended by another deflated
144    /// stream. To close the stream add the two bytes 0x3 and 0x0.
145    ///
146    /// # Errors
147    ///
148    /// This function will perform I/O to complete this stream, and any I/O
149    /// errors which occur will be returned from this function.
150    pub fn flush_finish(mut self) -> io::Result<W> {
151        self.inner.flush()?;
152        Ok(self.inner.take_inner())
153    }
154
155    /// Returns the number of bytes that have been written to this compressor.
156    ///
157    /// Note that not all bytes written to this object may be accounted for,
158    /// there may still be some active buffering.
159    pub fn total_in(&self) -> u64 {
160        self.inner.data.total_in()
161    }
162
163    /// Returns the number of bytes that the compressor has produced.
164    ///
165    /// Note that not all bytes may have been written yet, some may still be
166    /// buffered.
167    pub fn total_out(&self) -> u64 {
168        self.inner.data.total_out()
169    }
170}
171
172impl<W: Write> Write for ZlibEncoder<W> {
173    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
174        self.inner.write(buf)
175    }
176
177    fn flush(&mut self) -> io::Result<()> {
178        self.inner.flush()
179    }
180}
181
182impl<W: Read + Write> Read for ZlibEncoder<W> {
183    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
184        self.get_mut().read(buf)
185    }
186}
187
188/// A ZLIB decoder, or decompressor.
189///
190/// This structure implements a [`Write`] and will emit a stream of decompressed
191/// data when fed a stream of compressed data.
192///
193/// After decoding a single member of the ZLIB data this writer will return the number of bytes up
194/// to the end of the ZLIB member and subsequent writes will return Ok(0) allowing the caller to
195/// handle any data following the ZLIB member.
196///
197/// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
198///
199/// # Examples
200///
201/// ```
202/// use std::io::prelude::*;
203/// use std::io;
204/// # use flate2::Compression;
205/// # use flate2::write::ZlibEncoder;
206/// use flate2::write::ZlibDecoder;
207///
208/// # fn main() {
209/// #    let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
210/// #    e.write_all(b"Hello World").unwrap();
211/// #    let bytes = e.finish().unwrap();
212/// #    println!("{}", decode_reader(bytes).unwrap());
213/// # }
214/// #
215/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error
216/// // Here Vec<u8> implements Write
217///
218/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
219///    let mut writer = Vec::new();
220///    let mut z = ZlibDecoder::new(writer);
221///    z.write_all(&bytes[..])?;
222///    writer = z.finish()?;
223///    let return_string = String::from_utf8(writer).expect("String parsing error");
224///    Ok(return_string)
225/// }
226/// ```
227#[derive(Debug)]
228pub struct ZlibDecoder<W: Write> {
229    inner: zio::Writer<W, Decompress>,
230}
231
232impl<W: Write> ZlibDecoder<W> {
233    /// Creates a new decoder which will write uncompressed data to the stream.
234    ///
235    /// When this decoder is dropped or unwrapped the final pieces of data will
236    /// be flushed.
237    pub fn new(w: W) -> ZlibDecoder<W> {
238        ZlibDecoder {
239            inner: zio::Writer::new(w, Decompress::new(true)),
240        }
241    }
242
243    /// Creates a new decoder which will write uncompressed data to the stream `w`
244    /// using the given `decompression` settings.
245    ///
246    /// When this decoder is dropped or unwrapped the final pieces of data will
247    /// be flushed.
248    pub fn new_with_decompress(w: W, decompression: Decompress) -> ZlibDecoder<W> {
249        ZlibDecoder {
250            inner: zio::Writer::new(w, decompression),
251        }
252    }
253
254    /// Acquires a reference to the underlying writer.
255    pub fn get_ref(&self) -> &W {
256        self.inner.get_ref()
257    }
258
259    /// Acquires a mutable reference to the underlying writer.
260    ///
261    /// The underlying writer may be mutated or replaced as long as this
262    /// preserves the bytes and ordering of the logical output stream.
263    /// Concatenate output from each writer to reconstruct the complete stream.
264    ///
265    /// Replacing the writer does not require [`flush`](Write::flush). Call it
266    /// first to write all decompressed output currently available to the
267    /// current writer. This is useful before applying [`std::mem::take`] to
268    /// [`get_mut`](Self::get_mut) when forwarding output incrementally.
269    ///
270    /// To start a new stream, use [`reset`](Self::reset); replacing the writer
271    /// does not reset this decoder.
272    pub fn get_mut(&mut self) -> &mut W {
273        self.inner.get_mut()
274    }
275
276    /// Resets the state of this decoder entirely, swapping out the output
277    /// stream for another.
278    ///
279    /// This will reset the internal state of this decoder and replace the
280    /// output stream with the one provided, returning the previous output
281    /// stream. Future data written to this decoder will be decompressed into
282    /// the output stream `w`.
283    ///
284    /// # Errors
285    ///
286    /// This function will perform I/O to complete this stream, and any I/O
287    /// errors which occur will be returned from this function.
288    pub fn reset(&mut self, w: W) -> io::Result<W> {
289        self.inner.finish()?;
290        self.inner.data = Decompress::new(true);
291        Ok(self.inner.replace(w))
292    }
293
294    /// Attempt to finish this output stream, writing out final chunks of data.
295    ///
296    /// Note that this function can only be used once data has finished being
297    /// written to the output stream. After this function is called then further
298    /// calls to `write` may result in a panic.
299    ///
300    /// # Panics
301    ///
302    /// Attempts to write data to this stream may result in a panic after this
303    /// function is called.
304    ///
305    /// # Errors
306    ///
307    /// This function will perform I/O to complete this stream, and any I/O
308    /// errors which occur will be returned from this function.
309    pub fn try_finish(&mut self) -> io::Result<()> {
310        self.inner.finish()
311    }
312
313    /// Consumes this encoder, flushing the output stream.
314    ///
315    /// This will flush the underlying data stream and then return the contained
316    /// writer if the flush succeeded.
317    ///
318    /// Note that this function may not be suitable to call in a situation where
319    /// the underlying stream is an asynchronous I/O stream. To finish a stream
320    /// the `try_finish` (or `shutdown`) method should be used instead. To
321    /// re-acquire ownership of a stream it is safe to call this method after
322    /// `try_finish` or `shutdown` has returned `Ok`.
323    ///
324    /// # Errors
325    ///
326    /// This function will perform I/O to complete this stream, and any I/O
327    /// errors which occur will be returned from this function.
328    pub fn finish(mut self) -> io::Result<W> {
329        self.inner.finish()?;
330        Ok(self.inner.take_inner())
331    }
332
333    /// Returns the number of bytes that the decompressor has consumed for
334    /// decompression.
335    ///
336    /// Note that this will likely be smaller than the number of bytes
337    /// successfully written to this stream due to internal buffering.
338    pub fn total_in(&self) -> u64 {
339        self.inner.data.total_in()
340    }
341
342    /// Returns the number of bytes that the decompressor has written to its
343    /// output stream.
344    pub fn total_out(&self) -> u64 {
345        self.inner.data.total_out()
346    }
347}
348
349impl<W: Write> Write for ZlibDecoder<W> {
350    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
351        self.inner.write(buf)
352    }
353
354    fn flush(&mut self) -> io::Result<()> {
355        self.inner.flush()
356    }
357}
358
359impl<W: Read + Write> Read for ZlibDecoder<W> {
360    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
361        self.inner.get_mut().read(buf)
362    }
363}
364
365#[cfg(test)]
366mod tests {
367    use alloc::string::String;
368    use alloc::vec::Vec;
369
370    use super::*;
371    use crate::Compression;
372
373    const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
374        Hello World Hello World Hello World Hello World Hello World \
375        Hello World Hello World Hello World Hello World Hello World \
376        Hello World Hello World Hello World Hello World Hello World \
377        Hello World Hello World Hello World Hello World Hello World";
378
379    // ZlibDecoder consumes one zlib archive and then returns 0 for subsequent writes, allowing any
380    // additional data to be consumed by the caller.
381    #[test]
382    fn decode_extra_data() {
383        let compressed = {
384            let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
385            e.write_all(STR.as_ref()).unwrap();
386            let mut b = e.finish().unwrap();
387            b.push(b'x');
388            b
389        };
390
391        let mut writer = Vec::new();
392        let mut decoder = ZlibDecoder::new(writer);
393        let mut consumed_bytes = 0;
394        loop {
395            let n = decoder.write(&compressed[consumed_bytes..]).unwrap();
396            if n == 0 {
397                break;
398            }
399            consumed_bytes += n;
400        }
401        writer = decoder.finish().unwrap();
402        let actual = String::from_utf8(writer).expect("String parsing error");
403        assert_eq!(actual, STR);
404        assert_eq!(&compressed[consumed_bytes..], b"x");
405    }
406}