1 //! The encoder and decoder of the GZIP format.
2 //!
3 //! The GZIP format is defined in [RFC-1952](https://tools.ietf.org/html/rfc1952).
4 //!
5 //! # Examples
6 //! ```
7 //! use std::io::{self, Read};
8 //! use libflate::gzip::Encoder;
9 //! use libflate::non_blocking::gzip::Decoder;
10 //!
11 //! // Encoding
12 //! let mut encoder = Encoder::new(Vec::new()).unwrap();
13 //! io::copy(&mut &b"Hello World!"[..], &mut encoder).unwrap();
14 //! let encoded_data = encoder.finish().into_result().unwrap();
15 //!
16 //! // Decoding
17 //! let mut decoder = Decoder::new(&encoded_data[..]);
18 //! let mut decoded_data = Vec::new();
19 //! decoder.read_to_end(&mut decoded_data).unwrap();
20 //!
21 //! assert_eq!(decoded_data, b"Hello World!");
22 //! ```
23 use crate::checksum;
24 use crate::gzip::{Header, Trailer};
25 use crate::non_blocking::deflate;
26 use std::io::{self, Read};
27 
28 /// GZIP decoder which supports non-blocking I/O.
29 #[derive(Debug)]
30 pub struct Decoder<R> {
31     header: Option<Header>,
32     reader: deflate::Decoder<R>,
33     crc32: checksum::Crc32,
34     eos: bool,
35 }
36 impl<R: Read> Decoder<R> {
37     /// Makes a new decoder instance.
38     ///
39     /// `inner` is to be decoded GZIP stream.
40     ///
41     /// # Examples
42     /// ```
43     /// use std::io::Read;
44     /// use libflate::non_blocking::gzip::Decoder;
45     ///
46     /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
47     ///                     72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
48     ///                     163, 28, 41, 28, 12, 0, 0, 0];
49     ///
50     /// let mut decoder = Decoder::new(&encoded_data[..]);
51     /// let mut buf = Vec::new();
52     /// decoder.read_to_end(&mut buf).unwrap();
53     ///
54     /// assert_eq!(buf, b"Hello World!");
55     /// ```
new(inner: R) -> Self56     pub fn new(inner: R) -> Self {
57         Decoder {
58             header: None,
59             reader: deflate::Decoder::new(inner),
60             crc32: checksum::Crc32::new(),
61             eos: false,
62         }
63     }
64 
65     /// Returns the header of the GZIP stream.
66     ///
67     /// # Examples
68     /// ```
69     /// use libflate::gzip::Os;
70     /// use libflate::non_blocking::gzip::Decoder;
71     ///
72     /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
73     ///                     72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
74     ///                     163, 28, 41, 28, 12, 0, 0, 0];
75     ///
76     /// let mut decoder = Decoder::new(&encoded_data[..]);
77     /// assert_eq!(decoder.header().unwrap().os(), Os::Unix);
78     /// ```
header(&mut self) -> io::Result<&Header>79     pub fn header(&mut self) -> io::Result<&Header> {
80         if let Some(ref header) = self.header {
81             Ok(header)
82         } else {
83             let header = self
84                 .reader
85                 .bit_reader_mut()
86                 .transaction(|r| Header::read_from(r.as_inner_mut()))?;
87             self.header = Some(header);
88             self.header()
89         }
90     }
91 
92     /// Returns the immutable reference to the inner stream.
as_inner_ref(&self) -> &R93     pub fn as_inner_ref(&self) -> &R {
94         self.reader.as_inner_ref()
95     }
96 
97     /// Returns the mutable reference to the inner stream.
as_inner_mut(&mut self) -> &mut R98     pub fn as_inner_mut(&mut self) -> &mut R {
99         self.reader.as_inner_mut()
100     }
101 
102     /// Unwraps this `Decoder`, returning the underlying reader.
103     ///
104     /// # Examples
105     /// ```
106     /// use std::io::Cursor;
107     /// use libflate::non_blocking::gzip::Decoder;
108     ///
109     /// let encoded_data = [31, 139, 8, 0, 123, 0, 0, 0, 0, 3, 1, 12, 0, 243, 255,
110     ///                     72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33,
111     ///                     163, 28, 41, 28, 12, 0, 0, 0];
112     ///
113     /// let decoder = Decoder::new(Cursor::new(&encoded_data[..]));
114     /// assert_eq!(decoder.into_inner().into_inner(), &encoded_data[..]);
115     /// ```
into_inner(self) -> R116     pub fn into_inner(self) -> R {
117         self.reader.into_inner()
118     }
119 }
120 impl<R: Read> Read for Decoder<R> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>121     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
122         if self.header.is_none() {
123             self.header()?;
124         }
125         if self.eos {
126             Ok(0)
127         } else {
128             let read_size = self.reader.read(buf)?;
129             if read_size == 0 {
130                 let trailer = self
131                     .reader
132                     .bit_reader_mut()
133                     .transaction(|r| Trailer::read_from(r.as_inner_mut()))?;
134                 self.eos = true;
135                 // checksum verification is skipped during fuzzing
136                 // so that random data from fuzzer can reach actually interesting code
137                 // Compilation flag 'fuzzing' is automatically set by all 3 Rust fuzzers.
138                 if cfg!(not(fuzzing)) && trailer.crc32() != self.crc32.value() {
139                     Err(invalid_data_error!(
140                         "CRC32 mismatched: value={}, expected={}",
141                         self.crc32.value(),
142                         trailer.crc32()
143                     ))
144                 } else {
145                     Ok(0)
146                 }
147             } else {
148                 self.crc32.update(&buf[..read_size]);
149                 Ok(read_size)
150             }
151         }
152     }
153 }
154 
155 #[cfg(test)]
156 mod tests {
157     use super::*;
158     use crate::gzip::Encoder;
159     use crate::util::{nb_read_to_end, WouldBlockReader};
160     use std::io;
161 
decode_all(buf: &[u8]) -> io::Result<Vec<u8>>162     fn decode_all(buf: &[u8]) -> io::Result<Vec<u8>> {
163         let decoder = Decoder::new(WouldBlockReader::new(buf));
164         nb_read_to_end(decoder)
165     }
166 
167     #[test]
encode_works()168     fn encode_works() {
169         let plain = b"Hello World! Hello GZIP!!";
170         let mut encoder = Encoder::new(Vec::new()).unwrap();
171         io::copy(&mut &plain[..], &mut encoder).unwrap();
172         let encoded = encoder.finish().into_result().unwrap();
173         assert_eq!(decode_all(&encoded).unwrap(), plain);
174     }
175 
176     #[test]
decode_works_noncompressed_block_offset_sync()177     fn decode_works_noncompressed_block_offset_sync() {
178         let encoded = include_bytes!("../../data/noncompressed_block_offset_sync/offset.gz");
179         let decoded = include_bytes!("../../data/noncompressed_block_offset_sync/offset");
180         // decode_all(encoded).unwrap();
181         assert_eq!(decode_all(encoded).unwrap(), decoded.to_vec());
182     }
183 }
184