Skip to main content

flate2/deflate/
write.rs

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