Skip to main content

flate2/gz/
write.rs

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