1 use std::cmp;
2 use std::io;
3 use std::io::prelude::*;
4 
5 use super::{corrupt, GzBuilder, GzHeader, GzHeaderParser};
6 use crate::crc::{Crc, CrcWriter};
7 use crate::zio;
8 use crate::{Compress, Compression, Decompress, Status};
9 
10 /// A gzip streaming encoder
11 ///
12 /// This structure exposes a [`Write`] interface that will emit compressed data
13 /// to the underlying writer `W`.
14 ///
15 /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
16 ///
17 /// # Examples
18 ///
19 /// ```
20 /// use std::io::prelude::*;
21 /// use flate2::Compression;
22 /// use flate2::write::GzEncoder;
23 ///
24 /// // Vec<u8> implements Write to print the compressed bytes of sample string
25 /// # fn main() {
26 ///
27 /// let mut e = GzEncoder::new(Vec::new(), Compression::default());
28 /// e.write_all(b"Hello World").unwrap();
29 /// println!("{:?}", e.finish().unwrap());
30 /// # }
31 /// ```
32 #[derive(Debug)]
33 pub struct GzEncoder<W: Write> {
34     inner: zio::Writer<W, Compress>,
35     crc: Crc,
36     crc_bytes_written: usize,
37     header: Vec<u8>,
38 }
39 
gz_encoder<W: Write>(header: Vec<u8>, w: W, lvl: Compression) -> GzEncoder<W>40 pub fn gz_encoder<W: Write>(header: Vec<u8>, w: W, lvl: Compression) -> GzEncoder<W> {
41     GzEncoder {
42         inner: zio::Writer::new(w, Compress::new(lvl, false)),
43         crc: Crc::new(),
44         header,
45         crc_bytes_written: 0,
46     }
47 }
48 
49 impl<W: Write> GzEncoder<W> {
50     /// Creates a new encoder which will use the given compression level.
51     ///
52     /// The encoder is not configured specially for the emitted header. For
53     /// header configuration, see the `GzBuilder` type.
54     ///
55     /// The data written to the returned encoder will be compressed and then
56     /// written to the stream `w`.
new(w: W, level: Compression) -> GzEncoder<W>57     pub fn new(w: W, level: Compression) -> GzEncoder<W> {
58         GzBuilder::new().write(w, level)
59     }
60 
61     /// Acquires a reference to the underlying writer.
get_ref(&self) -> &W62     pub fn get_ref(&self) -> &W {
63         self.inner.get_ref()
64     }
65 
66     /// Acquires a mutable reference to the underlying writer.
67     ///
68     /// Note that mutation of the writer may result in surprising results if
69     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut W70     pub fn get_mut(&mut self) -> &mut W {
71         self.inner.get_mut()
72     }
73 
74     /// Attempt to finish this output stream, writing out final chunks of data.
75     ///
76     /// Note that this function can only be used once data has finished being
77     /// written to the output stream. After this function is called then further
78     /// calls to `write` may result in a panic.
79     ///
80     /// # Panics
81     ///
82     /// Attempts to write data to this stream may result in a panic after this
83     /// function is called.
84     ///
85     /// # Errors
86     ///
87     /// This function will perform I/O to complete this stream, and any I/O
88     /// errors which occur will be returned from this function.
try_finish(&mut self) -> io::Result<()>89     pub fn try_finish(&mut self) -> io::Result<()> {
90         self.write_header()?;
91         self.inner.finish()?;
92 
93         while self.crc_bytes_written < 8 {
94             let (sum, amt) = (self.crc.sum(), self.crc.amount());
95             let buf = [
96                 (sum >> 0) as u8,
97                 (sum >> 8) as u8,
98                 (sum >> 16) as u8,
99                 (sum >> 24) as u8,
100                 (amt >> 0) as u8,
101                 (amt >> 8) as u8,
102                 (amt >> 16) as u8,
103                 (amt >> 24) as u8,
104             ];
105             let inner = self.inner.get_mut();
106             let n = inner.write(&buf[self.crc_bytes_written..])?;
107             self.crc_bytes_written += n;
108         }
109         Ok(())
110     }
111 
112     /// Finish encoding this stream, returning the underlying writer once the
113     /// encoding is done.
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.
finish(mut self) -> io::Result<W>125     pub fn finish(mut self) -> io::Result<W> {
126         self.try_finish()?;
127         Ok(self.inner.take_inner())
128     }
129 
write_header(&mut self) -> io::Result<()>130     fn write_header(&mut self) -> io::Result<()> {
131         while !self.header.is_empty() {
132             let n = self.inner.get_mut().write(&self.header)?;
133             self.header.drain(..n);
134         }
135         Ok(())
136     }
137 }
138 
139 impl<W: Write> Write for GzEncoder<W> {
write(&mut self, buf: &[u8]) -> io::Result<usize>140     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
141         assert_eq!(self.crc_bytes_written, 0);
142         self.write_header()?;
143         let n = self.inner.write(buf)?;
144         self.crc.update(&buf[..n]);
145         Ok(n)
146     }
147 
flush(&mut self) -> io::Result<()>148     fn flush(&mut self) -> io::Result<()> {
149         assert_eq!(self.crc_bytes_written, 0);
150         self.write_header()?;
151         self.inner.flush()
152     }
153 }
154 
155 impl<R: Read + Write> Read for GzEncoder<R> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>156     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
157         self.get_mut().read(buf)
158     }
159 }
160 
161 impl<W: Write> Drop for GzEncoder<W> {
drop(&mut self)162     fn drop(&mut self) {
163         if self.inner.is_present() {
164             let _ = self.try_finish();
165         }
166     }
167 }
168 
169 /// A decoder for a single member of a [gzip file].
170 ///
171 /// This structure exposes a [`Write`] interface, receiving compressed data and
172 /// writing uncompressed data to the underlying writer.
173 ///
174 /// After decoding a single member of the gzip data this writer will return the number of bytes up to
175 /// to the end of the gzip member and subsequent writes will return Ok(0) allowing the caller to
176 /// handle any data following the gzip member.
177 ///
178 /// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
179 /// or read more
180 /// [in the introduction](../index.html#about-multi-member-gzip-files).
181 ///
182 /// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
183 /// [`Write`]: https://doc.rust-lang.org/std/io/trait.Write.html
184 ///
185 /// # Examples
186 ///
187 /// ```
188 /// use std::io::prelude::*;
189 /// use std::io;
190 /// use flate2::Compression;
191 /// use flate2::write::{GzEncoder, GzDecoder};
192 ///
193 /// # fn main() {
194 /// #    let mut e = GzEncoder::new(Vec::new(), Compression::default());
195 /// #    e.write(b"Hello World").unwrap();
196 /// #    let bytes = e.finish().unwrap();
197 /// #    assert_eq!("Hello World", decode_writer(bytes).unwrap());
198 /// # }
199 /// // Uncompresses a gzip encoded vector of bytes and returns a string or error
200 /// // Here Vec<u8> implements Write
201 /// fn decode_writer(bytes: Vec<u8>) -> io::Result<String> {
202 ///    let mut writer = Vec::new();
203 ///    let mut decoder = GzDecoder::new(writer);
204 ///    decoder.write_all(&bytes[..])?;
205 ///    writer = decoder.finish()?;
206 ///    let return_string = String::from_utf8(writer).expect("String parsing error");
207 ///    Ok(return_string)
208 /// }
209 /// ```
210 #[derive(Debug)]
211 pub struct GzDecoder<W: Write> {
212     inner: zio::Writer<CrcWriter<W>, Decompress>,
213     crc_bytes: Vec<u8>,
214     header_parser: GzHeaderParser,
215 }
216 
217 const CRC_BYTES_LEN: usize = 8;
218 
219 impl<W: Write> GzDecoder<W> {
220     /// Creates a new decoder which will write uncompressed data to the stream.
221     ///
222     /// When this encoder is dropped or unwrapped the final pieces of data will
223     /// be flushed.
new(w: W) -> GzDecoder<W>224     pub fn new(w: W) -> GzDecoder<W> {
225         GzDecoder {
226             inner: zio::Writer::new(CrcWriter::new(w), Decompress::new(false)),
227             crc_bytes: Vec::with_capacity(CRC_BYTES_LEN),
228             header_parser: GzHeaderParser::new(),
229         }
230     }
231 
232     /// Returns the header associated with this stream.
header(&self) -> Option<&GzHeader>233     pub fn header(&self) -> Option<&GzHeader> {
234         self.header_parser.header()
235     }
236 
237     /// Acquires a reference to the underlying writer.
get_ref(&self) -> &W238     pub fn get_ref(&self) -> &W {
239         self.inner.get_ref().get_ref()
240     }
241 
242     /// Acquires a mutable reference to the underlying writer.
243     ///
244     /// Note that mutating the output/input state of the stream may corrupt this
245     /// object, so care must be taken when using this method.
get_mut(&mut self) -> &mut W246     pub fn get_mut(&mut self) -> &mut W {
247         self.inner.get_mut().get_mut()
248     }
249 
250     /// Attempt to finish this output stream, writing out final chunks of data.
251     ///
252     /// Note that this function can only be used once data has finished being
253     /// written to the output stream. After this function is called then further
254     /// calls to `write` may result in a panic.
255     ///
256     /// # Panics
257     ///
258     /// Attempts to write data to this stream may result in a panic after this
259     /// function is called.
260     ///
261     /// # Errors
262     ///
263     /// This function will perform I/O to finish the stream, returning any
264     /// errors which happen.
try_finish(&mut self) -> io::Result<()>265     pub fn try_finish(&mut self) -> io::Result<()> {
266         self.finish_and_check_crc()?;
267         Ok(())
268     }
269 
270     /// Consumes this decoder, flushing the output stream.
271     ///
272     /// This will flush the underlying data stream and then return the contained
273     /// writer if the flush succeeded.
274     ///
275     /// Note that this function may not be suitable to call in a situation where
276     /// the underlying stream is an asynchronous I/O stream. To finish a stream
277     /// the `try_finish` (or `shutdown`) method should be used instead. To
278     /// re-acquire ownership of a stream it is safe to call this method after
279     /// `try_finish` or `shutdown` has returned `Ok`.
280     ///
281     /// # Errors
282     ///
283     /// This function will perform I/O to complete this stream, and any I/O
284     /// errors which occur will be returned from this function.
finish(mut self) -> io::Result<W>285     pub fn finish(mut self) -> io::Result<W> {
286         self.finish_and_check_crc()?;
287         Ok(self.inner.take_inner().into_inner())
288     }
289 
finish_and_check_crc(&mut self) -> io::Result<()>290     fn finish_and_check_crc(&mut self) -> io::Result<()> {
291         self.inner.finish()?;
292 
293         if self.crc_bytes.len() != 8 {
294             return Err(corrupt());
295         }
296 
297         let crc = ((self.crc_bytes[0] as u32) << 0)
298             | ((self.crc_bytes[1] as u32) << 8)
299             | ((self.crc_bytes[2] as u32) << 16)
300             | ((self.crc_bytes[3] as u32) << 24);
301         let amt = ((self.crc_bytes[4] as u32) << 0)
302             | ((self.crc_bytes[5] as u32) << 8)
303             | ((self.crc_bytes[6] as u32) << 16)
304             | ((self.crc_bytes[7] as u32) << 24);
305         if crc != self.inner.get_ref().crc().sum() {
306             return Err(corrupt());
307         }
308         if amt != self.inner.get_ref().crc().amount() {
309             return Err(corrupt());
310         }
311         Ok(())
312     }
313 }
314 
315 impl<W: Write> Write for GzDecoder<W> {
write(&mut self, mut buf: &[u8]) -> io::Result<usize>316     fn write(&mut self, mut buf: &[u8]) -> io::Result<usize> {
317         let buflen = buf.len();
318         if self.header().is_none() {
319             match self.header_parser.parse(&mut buf) {
320                 Err(err) => {
321                     if err.kind() == io::ErrorKind::UnexpectedEof {
322                         // all data read but header still not complete
323                         Ok(buflen)
324                     } else {
325                         Err(err)
326                     }
327                 }
328                 Ok(_) => {
329                     debug_assert!(self.header().is_some());
330                     // buf now contains the unread part of the original buf
331                     let n = buflen - buf.len();
332                     Ok(n)
333                 }
334             }
335         } else {
336             let (n, status) = self.inner.write_with_status(buf)?;
337 
338             if status == Status::StreamEnd && n < buf.len() && self.crc_bytes.len() < 8 {
339                 let remaining = buf.len() - n;
340                 let crc_bytes = cmp::min(remaining, CRC_BYTES_LEN - self.crc_bytes.len());
341                 self.crc_bytes.extend(&buf[n..n + crc_bytes]);
342                 return Ok(n + crc_bytes);
343             }
344             Ok(n)
345         }
346     }
347 
flush(&mut self) -> io::Result<()>348     fn flush(&mut self) -> io::Result<()> {
349         self.inner.flush()
350     }
351 }
352 
353 impl<W: Read + Write> Read for GzDecoder<W> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>354     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
355         self.inner.get_mut().get_mut().read(buf)
356     }
357 }
358 
359 /// A gzip streaming decoder that decodes a [gzip file] with multiple members.
360 ///
361 /// This structure exposes a [`Write`] interface that will consume compressed data and
362 /// write uncompressed data to the underlying writer.
363 ///
364 /// A gzip file consists of a series of *members* concatenated one after another.
365 /// `MultiGzDecoder` decodes all members of a file and writes them to the
366 /// underlying writer one after another.
367 ///
368 /// To handle members separately, see [GzDecoder] or read more
369 /// [in the introduction](../index.html#about-multi-member-gzip-files).
370 ///
371 /// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
372 #[derive(Debug)]
373 pub struct MultiGzDecoder<W: Write> {
374     inner: GzDecoder<W>,
375 }
376 
377 impl<W: Write> MultiGzDecoder<W> {
378     /// Creates a new decoder which will write uncompressed data to the stream.
379     /// If the gzip stream contains multiple members all will be decoded.
new(w: W) -> MultiGzDecoder<W>380     pub fn new(w: W) -> MultiGzDecoder<W> {
381         MultiGzDecoder {
382             inner: GzDecoder::new(w),
383         }
384     }
385 
386     /// Returns the header associated with the current member.
header(&self) -> Option<&GzHeader>387     pub fn header(&self) -> Option<&GzHeader> {
388         self.inner.header()
389     }
390 
391     /// Acquires a reference to the underlying writer.
get_ref(&self) -> &W392     pub fn get_ref(&self) -> &W {
393         self.inner.get_ref()
394     }
395 
396     /// Acquires a mutable reference to the underlying writer.
397     ///
398     /// Note that mutating the output/input state of the stream may corrupt this
399     /// object, so care must be taken when using this method.
get_mut(&mut self) -> &mut W400     pub fn get_mut(&mut self) -> &mut W {
401         self.inner.get_mut()
402     }
403 
404     /// Attempt to finish this output stream, writing out final chunks of data.
405     ///
406     /// Note that this function can only be used once data has finished being
407     /// written to the output stream. After this function is called then further
408     /// calls to `write` may result in a panic.
409     ///
410     /// # Panics
411     ///
412     /// Attempts to write data to this stream may result in a panic after this
413     /// function is called.
414     ///
415     /// # Errors
416     ///
417     /// This function will perform I/O to finish the stream, returning any
418     /// errors which happen.
try_finish(&mut self) -> io::Result<()>419     pub fn try_finish(&mut self) -> io::Result<()> {
420         self.inner.try_finish()
421     }
422 
423     /// Consumes this decoder, flushing the output stream.
424     ///
425     /// This will flush the underlying data stream and then return the contained
426     /// writer if the flush succeeded.
427     ///
428     /// Note that this function may not be suitable to call in a situation where
429     /// the underlying stream is an asynchronous I/O stream. To finish a stream
430     /// the `try_finish` (or `shutdown`) method should be used instead. To
431     /// re-acquire ownership of a stream it is safe to call this method after
432     /// `try_finish` or `shutdown` has returned `Ok`.
433     ///
434     /// # Errors
435     ///
436     /// This function will perform I/O to complete this stream, and any I/O
437     /// errors which occur will be returned from this function.
finish(self) -> io::Result<W>438     pub fn finish(self) -> io::Result<W> {
439         self.inner.finish()
440     }
441 }
442 
443 impl<W: Write> Write for MultiGzDecoder<W> {
write(&mut self, buf: &[u8]) -> io::Result<usize>444     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
445         if buf.is_empty() {
446             Ok(0)
447         } else {
448             match self.inner.write(buf) {
449                 Ok(0) => {
450                     // When the GzDecoder indicates that it has finished
451                     // create a new GzDecoder to handle additional data.
452                     self.inner.try_finish()?;
453                     let w = self.inner.inner.take_inner().into_inner();
454                     self.inner = GzDecoder::new(w);
455                     self.inner.write(buf)
456                 }
457                 res => res,
458             }
459         }
460     }
461 
flush(&mut self) -> io::Result<()>462     fn flush(&mut self) -> io::Result<()> {
463         self.inner.flush()
464     }
465 }
466 
467 #[cfg(test)]
468 mod tests {
469     use super::*;
470 
471     const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
472                                Hello World Hello World Hello World Hello World Hello World \
473                                Hello World Hello World Hello World Hello World Hello World \
474                                Hello World Hello World Hello World Hello World Hello World \
475                                Hello World Hello World Hello World Hello World Hello World";
476 
477     #[test]
decode_writer_one_chunk()478     fn decode_writer_one_chunk() {
479         let mut e = GzEncoder::new(Vec::new(), Compression::default());
480         e.write(STR.as_ref()).unwrap();
481         let bytes = e.finish().unwrap();
482 
483         let mut writer = Vec::new();
484         let mut decoder = GzDecoder::new(writer);
485         let n = decoder.write(&bytes[..]).unwrap();
486         decoder.write(&bytes[n..]).unwrap();
487         decoder.try_finish().unwrap();
488         writer = decoder.finish().unwrap();
489         let return_string = String::from_utf8(writer).expect("String parsing error");
490         assert_eq!(return_string, STR);
491     }
492 
493     #[test]
decode_writer_partial_header()494     fn decode_writer_partial_header() {
495         let mut e = GzEncoder::new(Vec::new(), Compression::default());
496         e.write(STR.as_ref()).unwrap();
497         let bytes = e.finish().unwrap();
498 
499         let mut writer = Vec::new();
500         let mut decoder = GzDecoder::new(writer);
501         assert_eq!(decoder.write(&bytes[..5]).unwrap(), 5);
502         let n = decoder.write(&bytes[5..]).unwrap();
503         if n < bytes.len() - 5 {
504             decoder.write(&bytes[n + 5..]).unwrap();
505         }
506         writer = decoder.finish().unwrap();
507         let return_string = String::from_utf8(writer).expect("String parsing error");
508         assert_eq!(return_string, STR);
509     }
510 
511     #[test]
decode_writer_partial_header_filename()512     fn decode_writer_partial_header_filename() {
513         let filename = "test.txt";
514         let mut e = GzBuilder::new()
515             .filename(filename)
516             .read(STR.as_bytes(), Compression::default());
517         let mut bytes = Vec::new();
518         e.read_to_end(&mut bytes).unwrap();
519 
520         let mut writer = Vec::new();
521         let mut decoder = GzDecoder::new(writer);
522         assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12);
523         let n = decoder.write(&bytes[12..]).unwrap();
524         if n < bytes.len() - 12 {
525             decoder.write(&bytes[n + 12..]).unwrap();
526         }
527         assert_eq!(
528             decoder.header().unwrap().filename().unwrap(),
529             filename.as_bytes()
530         );
531         writer = decoder.finish().unwrap();
532         let return_string = String::from_utf8(writer).expect("String parsing error");
533         assert_eq!(return_string, STR);
534     }
535 
536     #[test]
decode_writer_partial_header_comment()537     fn decode_writer_partial_header_comment() {
538         let comment = "test comment";
539         let mut e = GzBuilder::new()
540             .comment(comment)
541             .read(STR.as_bytes(), Compression::default());
542         let mut bytes = Vec::new();
543         e.read_to_end(&mut bytes).unwrap();
544 
545         let mut writer = Vec::new();
546         let mut decoder = GzDecoder::new(writer);
547         assert_eq!(decoder.write(&bytes[..12]).unwrap(), 12);
548         let n = decoder.write(&bytes[12..]).unwrap();
549         if n < bytes.len() - 12 {
550             decoder.write(&bytes[n + 12..]).unwrap();
551         }
552         assert_eq!(
553             decoder.header().unwrap().comment().unwrap(),
554             comment.as_bytes()
555         );
556         writer = decoder.finish().unwrap();
557         let return_string = String::from_utf8(writer).expect("String parsing error");
558         assert_eq!(return_string, STR);
559     }
560 
561     #[test]
decode_writer_exact_header()562     fn decode_writer_exact_header() {
563         let mut e = GzEncoder::new(Vec::new(), Compression::default());
564         e.write(STR.as_ref()).unwrap();
565         let bytes = e.finish().unwrap();
566 
567         let mut writer = Vec::new();
568         let mut decoder = GzDecoder::new(writer);
569         assert_eq!(decoder.write(&bytes[..10]).unwrap(), 10);
570         decoder.write(&bytes[10..]).unwrap();
571         writer = decoder.finish().unwrap();
572         let return_string = String::from_utf8(writer).expect("String parsing error");
573         assert_eq!(return_string, STR);
574     }
575 
576     #[test]
decode_writer_partial_crc()577     fn decode_writer_partial_crc() {
578         let mut e = GzEncoder::new(Vec::new(), Compression::default());
579         e.write(STR.as_ref()).unwrap();
580         let bytes = e.finish().unwrap();
581 
582         let mut writer = Vec::new();
583         let mut decoder = GzDecoder::new(writer);
584         let l = bytes.len() - 5;
585         let n = decoder.write(&bytes[..l]).unwrap();
586         decoder.write(&bytes[n..]).unwrap();
587         writer = decoder.finish().unwrap();
588         let return_string = String::from_utf8(writer).expect("String parsing error");
589         assert_eq!(return_string, STR);
590     }
591 
592     // Two or more gzip files concatenated form a multi-member gzip file. MultiGzDecoder will
593     // concatenate the decoded contents of all members.
594     #[test]
decode_multi_writer()595     fn decode_multi_writer() {
596         let mut e = GzEncoder::new(Vec::new(), Compression::default());
597         e.write(STR.as_ref()).unwrap();
598         let bytes = e.finish().unwrap().repeat(2);
599 
600         let mut writer = Vec::new();
601         let mut decoder = MultiGzDecoder::new(writer);
602         let mut count = 0;
603         while count < bytes.len() {
604             let n = decoder.write(&bytes[count..]).unwrap();
605             assert!(n != 0);
606             count += n;
607         }
608         writer = decoder.finish().unwrap();
609         let return_string = String::from_utf8(writer).expect("String parsing error");
610         let expected = STR.repeat(2);
611         assert_eq!(return_string, expected);
612     }
613 
614     // GzDecoder consumes one gzip member and then returns 0 for subsequent writes, allowing any
615     // additional data to be consumed by the caller.
616     #[test]
decode_extra_data()617     fn decode_extra_data() {
618         let compressed = {
619             let mut e = GzEncoder::new(Vec::new(), Compression::default());
620             e.write(STR.as_ref()).unwrap();
621             let mut b = e.finish().unwrap();
622             b.push(b'x');
623             b
624         };
625 
626         let mut writer = Vec::new();
627         let mut decoder = GzDecoder::new(writer);
628         let mut consumed_bytes = 0;
629         loop {
630             let n = decoder.write(&compressed[consumed_bytes..]).unwrap();
631             if n == 0 {
632                 break;
633             }
634             consumed_bytes += n;
635         }
636         writer = decoder.finish().unwrap();
637         let actual = String::from_utf8(writer).expect("String parsing error");
638         assert_eq!(actual, STR);
639         assert_eq!(&compressed[consumed_bytes..], b"x");
640     }
641 }
642