1 use std::cmp;
2 use std::io;
3 use std::io::prelude::*;
4 use std::mem;
5 
6 #[cfg(feature = "tokio")]
7 use futures::Poll;
8 #[cfg(feature = "tokio")]
9 use tokio_io::{AsyncRead, AsyncWrite};
10 
11 use super::{GzBuilder, GzHeader};
12 use super::{FCOMMENT, FEXTRA, FHCRC, FNAME};
13 use crate::crc::{Crc, CrcReader};
14 use crate::deflate;
15 use crate::Compression;
16 
copy(into: &mut [u8], from: &[u8], pos: &mut usize) -> usize17 fn copy(into: &mut [u8], from: &[u8], pos: &mut usize) -> usize {
18     let min = cmp::min(into.len(), from.len() - *pos);
19     for (slot, val) in into.iter_mut().zip(from[*pos..*pos + min].iter()) {
20         *slot = *val;
21     }
22     *pos += min;
23     return min;
24 }
25 
corrupt() -> io::Error26 pub(crate) fn corrupt() -> io::Error {
27     io::Error::new(
28         io::ErrorKind::InvalidInput,
29         "corrupt gzip stream does not have a matching checksum",
30     )
31 }
32 
bad_header() -> io::Error33 fn bad_header() -> io::Error {
34     io::Error::new(io::ErrorKind::InvalidInput, "invalid gzip header")
35 }
36 
read_le_u16<R: Read>(r: &mut Buffer<R>) -> io::Result<u16>37 fn read_le_u16<R: Read>(r: &mut Buffer<R>) -> io::Result<u16> {
38     let mut b = [0; 2];
39     r.read_and_forget(&mut b)?;
40     Ok((b[0] as u16) | ((b[1] as u16) << 8))
41 }
42 
read_gz_header_part<'a, R: Read>(r: &'a mut Buffer<'a, R>) -> io::Result<()>43 fn read_gz_header_part<'a, R: Read>(r: &'a mut Buffer<'a, R>) -> io::Result<()> {
44     loop {
45         match r.part.state {
46             GzHeaderParsingState::Start => {
47                 let mut header = [0; 10];
48                 r.read_and_forget(&mut header)?;
49 
50                 if header[0] != 0x1f || header[1] != 0x8b {
51                     return Err(bad_header());
52                 }
53                 if header[2] != 8 {
54                     return Err(bad_header());
55                 }
56 
57                 r.part.flg = header[3];
58                 r.part.header.mtime = ((header[4] as u32) << 0)
59                     | ((header[5] as u32) << 8)
60                     | ((header[6] as u32) << 16)
61                     | ((header[7] as u32) << 24);
62                 let _xfl = header[8];
63                 r.part.header.operating_system = header[9];
64                 r.part.state = GzHeaderParsingState::Xlen;
65             }
66             GzHeaderParsingState::Xlen => {
67                 if r.part.flg & FEXTRA != 0 {
68                     r.part.xlen = read_le_u16(r)?;
69                 }
70                 r.part.state = GzHeaderParsingState::Extra;
71             }
72             GzHeaderParsingState::Extra => {
73                 if r.part.flg & FEXTRA != 0 {
74                     let mut extra = vec![0; r.part.xlen as usize];
75                     r.read_and_forget(&mut extra)?;
76                     r.part.header.extra = Some(extra);
77                 }
78                 r.part.state = GzHeaderParsingState::Filename;
79             }
80             GzHeaderParsingState::Filename => {
81                 if r.part.flg & FNAME != 0 {
82                     if None == r.part.header.filename {
83                         r.part.header.filename = Some(Vec::new());
84                     };
85                     for byte in r.bytes() {
86                         let byte = byte?;
87                         if byte == 0 {
88                             break;
89                         }
90                     }
91                 }
92                 r.part.state = GzHeaderParsingState::Comment;
93             }
94             GzHeaderParsingState::Comment => {
95                 if r.part.flg & FCOMMENT != 0 {
96                     if None == r.part.header.comment {
97                         r.part.header.comment = Some(Vec::new());
98                     };
99                     for byte in r.bytes() {
100                         let byte = byte?;
101                         if byte == 0 {
102                             break;
103                         }
104                     }
105                 }
106                 r.part.state = GzHeaderParsingState::Crc;
107             }
108             GzHeaderParsingState::Crc => {
109                 if r.part.flg & FHCRC != 0 {
110                     let stored_crc = read_le_u16(r)?;
111                     let calced_crc = r.part.crc.sum() as u16;
112                     if stored_crc != calced_crc {
113                         return Err(corrupt());
114                     }
115                 }
116                 return Ok(());
117             }
118         }
119     }
120 }
121 
read_gz_header<R: Read>(r: &mut R) -> io::Result<GzHeader>122 pub(crate) fn read_gz_header<R: Read>(r: &mut R) -> io::Result<GzHeader> {
123     let mut part = GzHeaderPartial::new();
124 
125     let result = {
126         let mut reader = Buffer::new(&mut part, r);
127         read_gz_header_part(&mut reader)
128     };
129 
130     match result {
131         Ok(()) => {
132             return Ok(part.take_header());
133         }
134         Err(err) => {
135             return Err(err);
136         }
137     };
138 }
139 
140 /// A gzip streaming encoder
141 ///
142 /// This structure exposes a [`BufRead`] interface that will read uncompressed data
143 /// from the underlying reader and expose the compressed version as a [`BufRead`]
144 /// interface.
145 ///
146 /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// use std::io::prelude::*;
152 /// use std::io;
153 /// use flate2::Compression;
154 /// use flate2::bufread::GzEncoder;
155 /// use std::fs::File;
156 /// use std::io::BufReader;
157 ///
158 /// // Opens sample file, compresses the contents and returns a Vector or error
159 /// // File wrapped in a BufReader implements BufRead
160 ///
161 /// fn open_hello_world() -> io::Result<Vec<u8>> {
162 ///     let f = File::open("examples/hello_world.txt")?;
163 ///     let b = BufReader::new(f);
164 ///     let mut gz = GzEncoder::new(b, Compression::fast());
165 ///     let mut buffer = Vec::new();
166 ///     gz.read_to_end(&mut buffer)?;
167 ///     Ok(buffer)
168 /// }
169 /// ```
170 #[derive(Debug)]
171 pub struct GzEncoder<R> {
172     inner: deflate::bufread::DeflateEncoder<CrcReader<R>>,
173     header: Vec<u8>,
174     pos: usize,
175     eof: bool,
176 }
177 
gz_encoder<R: BufRead>(header: Vec<u8>, r: R, lvl: Compression) -> GzEncoder<R>178 pub fn gz_encoder<R: BufRead>(header: Vec<u8>, r: R, lvl: Compression) -> GzEncoder<R> {
179     let crc = CrcReader::new(r);
180     GzEncoder {
181         inner: deflate::bufread::DeflateEncoder::new(crc, lvl),
182         header: header,
183         pos: 0,
184         eof: false,
185     }
186 }
187 
188 impl<R: BufRead> GzEncoder<R> {
189     /// Creates a new encoder which will use the given compression level.
190     ///
191     /// The encoder is not configured specially for the emitted header. For
192     /// header configuration, see the `GzBuilder` type.
193     ///
194     /// The data read from the stream `r` will be compressed and available
195     /// through the returned reader.
new(r: R, level: Compression) -> GzEncoder<R>196     pub fn new(r: R, level: Compression) -> GzEncoder<R> {
197         GzBuilder::new().buf_read(r, level)
198     }
199 
read_footer(&mut self, into: &mut [u8]) -> io::Result<usize>200     fn read_footer(&mut self, into: &mut [u8]) -> io::Result<usize> {
201         if self.pos == 8 {
202             return Ok(0);
203         }
204         let crc = self.inner.get_ref().crc();
205         let ref arr = [
206             (crc.sum() >> 0) as u8,
207             (crc.sum() >> 8) as u8,
208             (crc.sum() >> 16) as u8,
209             (crc.sum() >> 24) as u8,
210             (crc.amount() >> 0) as u8,
211             (crc.amount() >> 8) as u8,
212             (crc.amount() >> 16) as u8,
213             (crc.amount() >> 24) as u8,
214         ];
215         Ok(copy(into, arr, &mut self.pos))
216     }
217 }
218 
219 impl<R> GzEncoder<R> {
220     /// Acquires a reference to the underlying reader.
get_ref(&self) -> &R221     pub fn get_ref(&self) -> &R {
222         self.inner.get_ref().get_ref()
223     }
224 
225     /// Acquires a mutable reference to the underlying reader.
226     ///
227     /// Note that mutation of the reader may result in surprising results if
228     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut R229     pub fn get_mut(&mut self) -> &mut R {
230         self.inner.get_mut().get_mut()
231     }
232 
233     /// Returns the underlying stream, consuming this encoder
into_inner(self) -> R234     pub fn into_inner(self) -> R {
235         self.inner.into_inner().into_inner()
236     }
237 }
238 
239 #[inline]
finish(buf: &[u8; 8]) -> (u32, u32)240 fn finish(buf: &[u8; 8]) -> (u32, u32) {
241     let crc = ((buf[0] as u32) << 0)
242         | ((buf[1] as u32) << 8)
243         | ((buf[2] as u32) << 16)
244         | ((buf[3] as u32) << 24);
245     let amt = ((buf[4] as u32) << 0)
246         | ((buf[5] as u32) << 8)
247         | ((buf[6] as u32) << 16)
248         | ((buf[7] as u32) << 24);
249     (crc, amt)
250 }
251 
252 impl<R: BufRead> Read for GzEncoder<R> {
read(&mut self, mut into: &mut [u8]) -> io::Result<usize>253     fn read(&mut self, mut into: &mut [u8]) -> io::Result<usize> {
254         let mut amt = 0;
255         if self.eof {
256             return self.read_footer(into);
257         } else if self.pos < self.header.len() {
258             amt += copy(into, &self.header, &mut self.pos);
259             if amt == into.len() {
260                 return Ok(amt);
261             }
262             let tmp = into;
263             into = &mut tmp[amt..];
264         }
265         match self.inner.read(into)? {
266             0 => {
267                 self.eof = true;
268                 self.pos = 0;
269                 self.read_footer(into)
270             }
271             n => Ok(amt + n),
272         }
273     }
274 }
275 
276 impl<R: BufRead + Write> Write for GzEncoder<R> {
write(&mut self, buf: &[u8]) -> io::Result<usize>277     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
278         self.get_mut().write(buf)
279     }
280 
flush(&mut self) -> io::Result<()>281     fn flush(&mut self) -> io::Result<()> {
282         self.get_mut().flush()
283     }
284 }
285 
286 /// A gzip streaming decoder
287 ///
288 /// This structure consumes a [`BufRead`] interface, reading compressed data
289 /// from the underlying reader, and emitting uncompressed data.
290 ///
291 /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
292 ///
293 /// # Examples
294 ///
295 /// ```
296 /// use std::io::prelude::*;
297 /// use std::io;
298 /// # use flate2::Compression;
299 /// # use flate2::write::GzEncoder;
300 /// use flate2::bufread::GzDecoder;
301 ///
302 /// # fn main() {
303 /// #   let mut e = GzEncoder::new(Vec::new(), Compression::default());
304 /// #   e.write_all(b"Hello World").unwrap();
305 /// #   let bytes = e.finish().unwrap();
306 /// #   println!("{}", decode_reader(bytes).unwrap());
307 /// # }
308 /// #
309 /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
310 /// // Here &[u8] implements BufRead
311 ///
312 /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
313 ///    let mut gz = GzDecoder::new(&bytes[..]);
314 ///    let mut s = String::new();
315 ///    gz.read_to_string(&mut s)?;
316 ///    Ok(s)
317 /// }
318 /// ```
319 #[derive(Debug)]
320 pub struct GzDecoder<R> {
321     inner: GzState,
322     header: Option<GzHeader>,
323     reader: CrcReader<deflate::bufread::DeflateDecoder<R>>,
324     multi: bool,
325 }
326 
327 #[derive(Debug)]
328 pub enum GzHeaderParsingState {
329     Start,
330     Xlen,
331     Extra,
332     Filename,
333     Comment,
334     Crc,
335 }
336 
337 #[derive(Debug)]
338 pub struct GzHeaderPartial {
339     buf: Vec<u8>,
340     state: GzHeaderParsingState,
341     flg: u8,
342     xlen: u16,
343     crc: Crc,
344     header: GzHeader,
345 }
346 
347 impl GzHeaderPartial {
new() -> GzHeaderPartial348     fn new() -> GzHeaderPartial {
349         GzHeaderPartial {
350             buf: Vec::with_capacity(10), // minimum header length
351             state: GzHeaderParsingState::Start,
352             flg: 0,
353             xlen: 0,
354             crc: Crc::new(),
355             header: GzHeader {
356                 extra: None,
357                 filename: None,
358                 comment: None,
359                 operating_system: 0,
360                 mtime: 0,
361             },
362         }
363     }
364 
take_header(self) -> GzHeader365     pub fn take_header(self) -> GzHeader {
366         return self.header;
367     }
368 }
369 
370 #[derive(Debug)]
371 enum GzState {
372     Header(GzHeaderPartial),
373     Body,
374     Finished(usize, [u8; 8]),
375     Err(io::Error),
376     End,
377 }
378 
379 /// A small adapter which reads data originally from `buf` and then reads all
380 /// further data from `reader`. This will also buffer all data read from
381 /// `reader` into `buf` for reuse on a further call.
382 struct Buffer<'a, T: 'a> {
383     part: &'a mut GzHeaderPartial,
384     buf_cur: usize,
385     buf_max: usize,
386     reader: &'a mut T,
387 }
388 
389 impl<'a, T> Buffer<'a, T> {
new(part: &'a mut GzHeaderPartial, reader: &'a mut T) -> Buffer<'a, T>390     fn new(part: &'a mut GzHeaderPartial, reader: &'a mut T) -> Buffer<'a, T> {
391         Buffer {
392             reader,
393             buf_cur: 0,
394             buf_max: part.buf.len(),
395             part,
396         }
397     }
398 }
399 
400 impl<'a, T: Read> Read for Buffer<'a, T> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>401     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
402         let mut bufref = match self.part.state {
403             GzHeaderParsingState::Filename => self.part.header.filename.as_mut(),
404             GzHeaderParsingState::Comment => self.part.header.comment.as_mut(),
405             _ => None,
406         };
407         if let Some(ref mut b) = bufref {
408             // we have a direct reference to a buffer where to write
409             let len = self.reader.read(buf)?;
410             if len > 0 && buf[len - 1] == 0 {
411                 // we do not append the final 0
412                 b.extend_from_slice(&buf[..len - 1]);
413             } else {
414                 b.extend_from_slice(&buf[..len]);
415             }
416             self.part.crc.update(&buf[..len]);
417             Ok(len)
418         } else if self.buf_cur == self.buf_max {
419             // we read new bytes and also save them in self.part.buf
420             let len = self.reader.read(buf)?;
421             self.part.buf.extend_from_slice(&buf[..len]);
422             self.part.crc.update(&buf[..len]);
423             Ok(len)
424         } else {
425             // we first read the previously saved bytes
426             let len = (&self.part.buf[self.buf_cur..self.buf_max]).read(buf)?;
427             self.buf_cur += len;
428             Ok(len)
429         }
430     }
431 }
432 
433 impl<'a, T> Buffer<'a, T>
434 where
435     T: std::io::Read,
436 {
437     // If we manage to read all the bytes, we reset the buffer
read_and_forget(&mut self, buf: &mut [u8]) -> io::Result<usize>438     fn read_and_forget(&mut self, buf: &mut [u8]) -> io::Result<usize> {
439         self.read_exact(buf)?;
440         // we managed to read the whole buf
441         // we will no longer need the previously saved bytes in self.part.buf
442         let rlen = buf.len();
443         self.part.buf.truncate(0);
444         self.buf_cur = 0;
445         self.buf_max = 0;
446         return Ok(rlen);
447     }
448 }
449 
450 impl<R: BufRead> GzDecoder<R> {
451     /// Creates a new decoder from the given reader, immediately parsing the
452     /// gzip header.
new(mut r: R) -> GzDecoder<R>453     pub fn new(mut r: R) -> GzDecoder<R> {
454         let mut part = GzHeaderPartial::new();
455         let mut header = None;
456 
457         let result = {
458             let mut reader = Buffer::new(&mut part, &mut r);
459             read_gz_header_part(&mut reader)
460         };
461 
462         let state = match result {
463             Ok(()) => {
464                 header = Some(part.take_header());
465                 GzState::Body
466             }
467             Err(ref err) if io::ErrorKind::WouldBlock == err.kind() => GzState::Header(part),
468             Err(err) => GzState::Err(err),
469         };
470 
471         GzDecoder {
472             inner: state,
473             reader: CrcReader::new(deflate::bufread::DeflateDecoder::new(r)),
474             multi: false,
475             header,
476         }
477     }
478 
multi(mut self, flag: bool) -> GzDecoder<R>479     fn multi(mut self, flag: bool) -> GzDecoder<R> {
480         self.multi = flag;
481         self
482     }
483 }
484 
485 impl<R> GzDecoder<R> {
486     /// Returns the header associated with this stream, if it was valid
header(&self) -> Option<&GzHeader>487     pub fn header(&self) -> Option<&GzHeader> {
488         self.header.as_ref()
489     }
490 
491     /// Acquires a reference to the underlying reader.
get_ref(&self) -> &R492     pub fn get_ref(&self) -> &R {
493         self.reader.get_ref().get_ref()
494     }
495 
496     /// Acquires a mutable reference to the underlying stream.
497     ///
498     /// Note that mutation of the stream may result in surprising results if
499     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut R500     pub fn get_mut(&mut self) -> &mut R {
501         self.reader.get_mut().get_mut()
502     }
503 
504     /// Consumes this decoder, returning the underlying reader.
into_inner(self) -> R505     pub fn into_inner(self) -> R {
506         self.reader.into_inner().into_inner()
507     }
508 }
509 
510 impl<R: BufRead> Read for GzDecoder<R> {
read(&mut self, into: &mut [u8]) -> io::Result<usize>511     fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
512         let GzDecoder {
513             inner,
514             header,
515             reader,
516             multi,
517         } = self;
518 
519         loop {
520             *inner = match mem::replace(inner, GzState::End) {
521                 GzState::Header(mut part) => {
522                     let result = {
523                         let mut reader = Buffer::new(&mut part, reader.get_mut().get_mut());
524                         read_gz_header_part(&mut reader)
525                     };
526                     let state = match result {
527                         Ok(()) => {
528                             *header = Some(part.take_header());
529                             GzState::Body
530                         }
531                         Err(err) if io::ErrorKind::WouldBlock == err.kind() => {
532                             *inner = GzState::Header(part);
533                             return Err(err);
534                         }
535                         Err(err) => return Err(err),
536                     };
537                     state
538                 }
539                 GzState::Body => {
540                     if into.is_empty() {
541                         *inner = GzState::Body;
542                         return Ok(0);
543                     }
544 
545                     let n = reader.read(into).map_err(|err| {
546                         if io::ErrorKind::WouldBlock == err.kind() {
547                             *inner = GzState::Body;
548                         }
549 
550                         err
551                     })?;
552 
553                     match n {
554                         0 => GzState::Finished(0, [0; 8]),
555                         n => {
556                             *inner = GzState::Body;
557                             return Ok(n);
558                         }
559                     }
560                 }
561                 GzState::Finished(pos, mut buf) => {
562                     if pos < buf.len() {
563                         let n = reader
564                             .get_mut()
565                             .get_mut()
566                             .read(&mut buf[pos..])
567                             .and_then(|n| {
568                                 if n == 0 {
569                                     Err(io::ErrorKind::UnexpectedEof.into())
570                                 } else {
571                                     Ok(n)
572                                 }
573                             })
574                             .map_err(|err| {
575                                 if io::ErrorKind::WouldBlock == err.kind() {
576                                     *inner = GzState::Finished(pos, buf);
577                                 }
578 
579                                 err
580                             })?;
581 
582                         GzState::Finished(pos + n, buf)
583                     } else {
584                         let (crc, amt) = finish(&buf);
585 
586                         if crc != reader.crc().sum() || amt != reader.crc().amount() {
587                             return Err(corrupt());
588                         } else if *multi {
589                             let is_eof = reader
590                                 .get_mut()
591                                 .get_mut()
592                                 .fill_buf()
593                                 .map(|buf| buf.is_empty())
594                                 .map_err(|err| {
595                                     if io::ErrorKind::WouldBlock == err.kind() {
596                                         *inner = GzState::Finished(pos, buf);
597                                     }
598 
599                                     err
600                                 })?;
601 
602                             if is_eof {
603                                 GzState::End
604                             } else {
605                                 reader.reset();
606                                 reader.get_mut().reset_data();
607                                 header.take();
608                                 GzState::Header(GzHeaderPartial::new())
609                             }
610                         } else {
611                             GzState::End
612                         }
613                     }
614                 }
615                 GzState::Err(err) => return Err(err),
616                 GzState::End => return Ok(0),
617             };
618         }
619     }
620 }
621 
622 #[cfg(feature = "tokio")]
623 impl<R: AsyncRead + BufRead> AsyncRead for GzDecoder<R> {}
624 
625 impl<R: BufRead + Write> Write for GzDecoder<R> {
write(&mut self, buf: &[u8]) -> io::Result<usize>626     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
627         self.get_mut().write(buf)
628     }
629 
flush(&mut self) -> io::Result<()>630     fn flush(&mut self) -> io::Result<()> {
631         self.get_mut().flush()
632     }
633 }
634 
635 #[cfg(feature = "tokio")]
636 impl<R: AsyncWrite + BufRead> AsyncWrite for GzDecoder<R> {
shutdown(&mut self) -> Poll<(), io::Error>637     fn shutdown(&mut self) -> Poll<(), io::Error> {
638         self.get_mut().shutdown()
639     }
640 }
641 
642 /// A gzip streaming decoder that decodes all members of a multistream
643 ///
644 /// A gzip member consists of a header, compressed data and a trailer. The [gzip
645 /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple
646 /// gzip members to be joined in a single stream. `MultiGzDecoder` will
647 /// decode all consecutive members while `GzDecoder` will only decompress
648 /// the first gzip member. The multistream format is commonly used in
649 /// bioinformatics, for example when using the BGZF compressed data.
650 ///
651 /// This structure exposes a [`BufRead`] interface that will consume all gzip members
652 /// from the underlying reader and emit uncompressed data.
653 ///
654 /// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
655 ///
656 /// # Examples
657 ///
658 /// ```
659 /// use std::io::prelude::*;
660 /// use std::io;
661 /// # use flate2::Compression;
662 /// # use flate2::write::GzEncoder;
663 /// use flate2::bufread::MultiGzDecoder;
664 ///
665 /// # fn main() {
666 /// #   let mut e = GzEncoder::new(Vec::new(), Compression::default());
667 /// #   e.write_all(b"Hello World").unwrap();
668 /// #   let bytes = e.finish().unwrap();
669 /// #   println!("{}", decode_reader(bytes).unwrap());
670 /// # }
671 /// #
672 /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
673 /// // Here &[u8] implements BufRead
674 ///
675 /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
676 ///    let mut gz = MultiGzDecoder::new(&bytes[..]);
677 ///    let mut s = String::new();
678 ///    gz.read_to_string(&mut s)?;
679 ///    Ok(s)
680 /// }
681 /// ```
682 #[derive(Debug)]
683 pub struct MultiGzDecoder<R>(GzDecoder<R>);
684 
685 impl<R: BufRead> MultiGzDecoder<R> {
686     /// Creates a new decoder from the given reader, immediately parsing the
687     /// (first) gzip header. If the gzip stream contains multiple members all will
688     /// be decoded.
new(r: R) -> MultiGzDecoder<R>689     pub fn new(r: R) -> MultiGzDecoder<R> {
690         MultiGzDecoder(GzDecoder::new(r).multi(true))
691     }
692 }
693 
694 impl<R> MultiGzDecoder<R> {
695     /// Returns the current header associated with this stream, if it's valid
header(&self) -> Option<&GzHeader>696     pub fn header(&self) -> Option<&GzHeader> {
697         self.0.header()
698     }
699 
700     /// Acquires a reference to the underlying reader.
get_ref(&self) -> &R701     pub fn get_ref(&self) -> &R {
702         self.0.get_ref()
703     }
704 
705     /// Acquires a mutable reference to the underlying stream.
706     ///
707     /// Note that mutation of the stream may result in surprising results if
708     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut R709     pub fn get_mut(&mut self) -> &mut R {
710         self.0.get_mut()
711     }
712 
713     /// Consumes this decoder, returning the underlying reader.
into_inner(self) -> R714     pub fn into_inner(self) -> R {
715         self.0.into_inner()
716     }
717 }
718 
719 impl<R: BufRead> Read for MultiGzDecoder<R> {
read(&mut self, into: &mut [u8]) -> io::Result<usize>720     fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
721         self.0.read(into)
722     }
723 }
724 
725 #[cfg(feature = "tokio")]
726 impl<R: AsyncRead + BufRead> AsyncRead for MultiGzDecoder<R> {}
727 
728 impl<R: BufRead + Write> Write for MultiGzDecoder<R> {
write(&mut self, buf: &[u8]) -> io::Result<usize>729     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
730         self.get_mut().write(buf)
731     }
732 
flush(&mut self) -> io::Result<()>733     fn flush(&mut self) -> io::Result<()> {
734         self.get_mut().flush()
735     }
736 }
737 
738 #[cfg(feature = "tokio")]
739 impl<R: AsyncWrite + BufRead> AsyncWrite for MultiGzDecoder<R> {
shutdown(&mut self) -> Poll<(), io::Error>740     fn shutdown(&mut self) -> Poll<(), io::Error> {
741         self.get_mut().shutdown()
742     }
743 }
744 
745 #[cfg(test)]
746 pub mod tests {
747     use crate::gz::bufread::*;
748     use std::io;
749     use std::io::{Cursor, Read, Write};
750 
751     //a cursor turning EOF into blocking errors
752     #[derive(Debug)]
753     pub struct BlockingCursor {
754         pub cursor: Cursor<Vec<u8>>,
755     }
756 
757     impl BlockingCursor {
new() -> BlockingCursor758         pub fn new() -> BlockingCursor {
759             BlockingCursor {
760                 cursor: Cursor::new(Vec::new()),
761             }
762         }
763 
set_position(&mut self, pos: u64)764         pub fn set_position(&mut self, pos: u64) {
765             return self.cursor.set_position(pos);
766         }
767 
position(&mut self) -> u64768         pub fn position(&mut self) -> u64 {
769             return self.cursor.position();
770         }
771     }
772 
773     impl Write for BlockingCursor {
write(&mut self, buf: &[u8]) -> io::Result<usize>774         fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
775             return self.cursor.write(buf);
776         }
flush(&mut self) -> io::Result<()>777         fn flush(&mut self) -> io::Result<()> {
778             return self.cursor.flush();
779         }
780     }
781 
782     impl Read for BlockingCursor {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>783         fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
784             //use the cursor, except it turns eof into blocking error
785             let r = self.cursor.read(buf);
786             match r {
787                 Err(ref err) => {
788                     if err.kind() == io::ErrorKind::UnexpectedEof {
789                         return Err(io::ErrorKind::WouldBlock.into());
790                     }
791                 }
792                 Ok(0) => {
793                     //regular EOF turned into blocking error
794                     return Err(io::ErrorKind::WouldBlock.into());
795                 }
796                 Ok(_n) => {}
797             }
798             return r;
799         }
800     }
801     #[test]
802     // test function read_and_forget of Buffer
buffer_read_and_forget()803     fn buffer_read_and_forget() {
804         // this is unused except for the buffering
805         let mut part = GzHeaderPartial::new();
806         // this is a reader which receives data afterwards
807         let mut r = BlockingCursor::new();
808         let data = vec![1, 2, 3];
809         let mut out = Vec::with_capacity(7);
810 
811         match r.write_all(&data) {
812             Ok(()) => {}
813             _ => {
814                 panic!("Unexpected result for write_all");
815             }
816         }
817         r.set_position(0);
818 
819         // First read : successful for one byte
820         let mut reader = Buffer::new(&mut part, &mut r);
821         out.resize(1, 0);
822         match reader.read_and_forget(&mut out) {
823             Ok(1) => {}
824             _ => {
825                 panic!("Unexpected result for read_and_forget with data");
826             }
827         }
828 
829         // Second read : incomplete for 7 bytes (we have only 2)
830         out.resize(7, 0);
831         match reader.read_and_forget(&mut out) {
832             Err(ref err) => {
833                 assert_eq!(io::ErrorKind::WouldBlock, err.kind());
834             }
835             _ => {
836                 panic!("Unexpected result for read_and_forget with incomplete");
837             }
838         }
839 
840         // 3 more data bytes have arrived
841         let pos = r.position();
842         let data2 = vec![4, 5, 6];
843         match r.write_all(&data2) {
844             Ok(()) => {}
845             _ => {
846                 panic!("Unexpected result for write_all");
847             }
848         }
849         r.set_position(pos);
850 
851         // Third read : still incomplete for 7 bytes (we have 5)
852         let mut reader2 = Buffer::new(&mut part, &mut r);
853         match reader2.read_and_forget(&mut out) {
854             Err(ref err) => {
855                 assert_eq!(io::ErrorKind::WouldBlock, err.kind());
856             }
857             _ => {
858                 panic!("Unexpected result for read_and_forget with more incomplete");
859             }
860         }
861 
862         // 3 more data bytes have arrived again
863         let pos2 = r.position();
864         let data3 = vec![7, 8, 9];
865         match r.write_all(&data3) {
866             Ok(()) => {}
867             _ => {
868                 panic!("Unexpected result for write_all");
869             }
870         }
871         r.set_position(pos2);
872 
873         // Fourth read : now succesful for 7 bytes
874         let mut reader3 = Buffer::new(&mut part, &mut r);
875         match reader3.read_and_forget(&mut out) {
876             Ok(7) => {
877                 assert_eq!(out[0], 2);
878                 assert_eq!(out[6], 8);
879             }
880             _ => {
881                 panic!("Unexpected result for read_and_forget with data");
882             }
883         }
884 
885         // Fifth read : succesful for one more byte
886         out.resize(1, 0);
887         match reader3.read_and_forget(&mut out) {
888             Ok(1) => {
889                 assert_eq!(out[0], 9);
890             }
891             _ => {
892                 panic!("Unexpected result for read_and_forget with data");
893             }
894         }
895     }
896 }
897