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