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