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}