1 use std::io;
2 use std::io::prelude::*;
3 
4 use super::bufread;
5 use super::{GzBuilder, GzHeader};
6 use crate::bufreader::BufReader;
7 use crate::Compression;
8 
9 /// A gzip streaming encoder
10 ///
11 /// This structure implements a [`Read`] interface. When read from, it reads
12 /// uncompressed data from the underlying [`Read`] and provides the compressed data.
13 ///
14 /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
15 ///
16 /// # Examples
17 ///
18 /// ```
19 /// use std::io::prelude::*;
20 /// use std::io;
21 /// use flate2::Compression;
22 /// use flate2::read::GzEncoder;
23 ///
24 /// // Return a vector containing the GZ compressed version of hello world
25 ///
26 /// fn gzencode_hello_world() -> io::Result<Vec<u8>> {
27 ///     let mut ret_vec = Vec::new();
28 ///     let bytestring = b"hello world";
29 ///     let mut gz = GzEncoder::new(&bytestring[..], Compression::fast());
30 ///     gz.read_to_end(&mut ret_vec)?;
31 ///     Ok(ret_vec)
32 /// }
33 /// ```
34 #[derive(Debug)]
35 pub struct GzEncoder<R> {
36     inner: bufread::GzEncoder<BufReader<R>>,
37 }
38 
gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R>39 pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> {
40     GzEncoder { inner }
41 }
42 
43 impl<R: Read> GzEncoder<R> {
44     /// Creates a new encoder which will use the given compression level.
45     ///
46     /// The encoder is not configured specially for the emitted header. For
47     /// header configuration, see the `GzBuilder` type.
48     ///
49     /// The data read from the stream `r` will be compressed and available
50     /// through the returned reader.
new(r: R, level: Compression) -> GzEncoder<R>51     pub fn new(r: R, level: Compression) -> GzEncoder<R> {
52         GzBuilder::new().read(r, level)
53     }
54 }
55 
56 impl<R> GzEncoder<R> {
57     /// Acquires a reference to the underlying reader.
get_ref(&self) -> &R58     pub fn get_ref(&self) -> &R {
59         self.inner.get_ref().get_ref()
60     }
61 
62     /// Acquires a mutable reference to the underlying reader.
63     ///
64     /// Note that mutation of the reader may result in surprising results if
65     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut R66     pub fn get_mut(&mut self) -> &mut R {
67         self.inner.get_mut().get_mut()
68     }
69 
70     /// Returns the underlying stream, consuming this encoder
into_inner(self) -> R71     pub fn into_inner(self) -> R {
72         self.inner.into_inner().into_inner()
73     }
74 }
75 
76 impl<R: Read> Read for GzEncoder<R> {
read(&mut self, into: &mut [u8]) -> io::Result<usize>77     fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
78         self.inner.read(into)
79     }
80 }
81 
82 impl<R: Read + Write> Write for GzEncoder<R> {
write(&mut self, buf: &[u8]) -> io::Result<usize>83     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
84         self.get_mut().write(buf)
85     }
86 
flush(&mut self) -> io::Result<()>87     fn flush(&mut self) -> io::Result<()> {
88         self.get_mut().flush()
89     }
90 }
91 
92 /// A decoder for a single member of a [gzip file].
93 ///
94 /// This structure implements a [`Read`] interface. When read from, it reads
95 /// compressed data from the underlying [`Read`] and provides the uncompressed data.
96 ///
97 /// After reading a single member of the gzip data this reader will return
98 /// Ok(0) even if there are more bytes available in the underlying reader.
99 /// `GzDecoder` may have read additional bytes past the end of the gzip data.
100 /// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader`
101 /// and use `bufread::GzDecoder` instead.
102 ///
103 /// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
104 /// or read more
105 /// [in the introduction](../index.html#about-multi-member-gzip-files).
106 ///
107 /// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
108 ///
109 /// # Examples
110 ///
111 /// ```
112 /// use std::io::prelude::*;
113 /// use std::io;
114 /// # use flate2::Compression;
115 /// # use flate2::write::GzEncoder;
116 /// use flate2::read::GzDecoder;
117 ///
118 /// # fn main() {
119 /// #    let mut e = GzEncoder::new(Vec::new(), Compression::default());
120 /// #    e.write_all(b"Hello World").unwrap();
121 /// #    let bytes = e.finish().unwrap();
122 /// #    println!("{}", decode_reader(bytes).unwrap());
123 /// # }
124 /// #
125 /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
126 /// // Here &[u8] implements Read
127 ///
128 /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
129 ///    let mut gz = GzDecoder::new(&bytes[..]);
130 ///    let mut s = String::new();
131 ///    gz.read_to_string(&mut s)?;
132 ///    Ok(s)
133 /// }
134 /// ```
135 #[derive(Debug)]
136 pub struct GzDecoder<R> {
137     inner: bufread::GzDecoder<BufReader<R>>,
138 }
139 
140 impl<R: Read> GzDecoder<R> {
141     /// Creates a new decoder from the given reader, immediately parsing the
142     /// gzip header.
new(r: R) -> GzDecoder<R>143     pub fn new(r: R) -> GzDecoder<R> {
144         GzDecoder {
145             inner: bufread::GzDecoder::new(BufReader::new(r)),
146         }
147     }
148 }
149 
150 impl<R> GzDecoder<R> {
151     /// Returns the header associated with this stream, if it was valid.
header(&self) -> Option<&GzHeader>152     pub fn header(&self) -> Option<&GzHeader> {
153         self.inner.header()
154     }
155 
156     /// Acquires a reference to the underlying reader.
157     ///
158     /// Note that the decoder may have read past the end of the gzip data.
159     /// To prevent this use [`bufread::GzDecoder`] instead.
get_ref(&self) -> &R160     pub fn get_ref(&self) -> &R {
161         self.inner.get_ref().get_ref()
162     }
163 
164     /// Acquires a mutable reference to the underlying stream.
165     ///
166     /// Note that mutation of the stream may result in surprising results if
167     /// this decoder continues to be used.
168     ///
169     /// Note that the decoder may have read past the end of the gzip data.
170     /// To prevent this use [`bufread::GzDecoder`] instead.
get_mut(&mut self) -> &mut R171     pub fn get_mut(&mut self) -> &mut R {
172         self.inner.get_mut().get_mut()
173     }
174 
175     /// Consumes this decoder, returning the underlying reader.
176     ///
177     /// Note that the decoder may have read past the end of the gzip data.
178     /// Subsequent reads will skip those bytes. To prevent this use
179     /// [`bufread::GzDecoder`] instead.
into_inner(self) -> R180     pub fn into_inner(self) -> R {
181         self.inner.into_inner().into_inner()
182     }
183 }
184 
185 impl<R: Read> Read for GzDecoder<R> {
read(&mut self, into: &mut [u8]) -> io::Result<usize>186     fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
187         self.inner.read(into)
188     }
189 }
190 
191 impl<R: Read + Write> Write for GzDecoder<R> {
write(&mut self, buf: &[u8]) -> io::Result<usize>192     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
193         self.get_mut().write(buf)
194     }
195 
flush(&mut self) -> io::Result<()>196     fn flush(&mut self) -> io::Result<()> {
197         self.get_mut().flush()
198     }
199 }
200 
201 /// A gzip streaming decoder that decodes a [gzip file] that may have multiple members.
202 ///
203 /// This structure implements a [`Read`] interface. When read from, it reads
204 /// compressed data from the underlying [`Read`] and provides the uncompressed
205 /// data.
206 ///
207 /// A gzip file consists of a series of *members* concatenated one after another.
208 /// MultiGzDecoder decodes all members of a file and returns Ok(0) once the
209 /// underlying reader does.
210 ///
211 /// To handle members seperately, see [GzDecoder] or read more
212 /// [in the introduction](../index.html#about-multi-member-gzip-files).
213 ///
214 /// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
215 ///
216 /// # Examples
217 ///
218 /// ```
219 /// use std::io::prelude::*;
220 /// use std::io;
221 /// # use flate2::Compression;
222 /// # use flate2::write::GzEncoder;
223 /// use flate2::read::MultiGzDecoder;
224 ///
225 /// # fn main() {
226 /// #    let mut e = GzEncoder::new(Vec::new(), Compression::default());
227 /// #    e.write_all(b"Hello World").unwrap();
228 /// #    let bytes = e.finish().unwrap();
229 /// #    println!("{}", decode_reader(bytes).unwrap());
230 /// # }
231 /// #
232 /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
233 /// // Here &[u8] implements Read
234 ///
235 /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
236 ///    let mut gz = MultiGzDecoder::new(&bytes[..]);
237 ///    let mut s = String::new();
238 ///    gz.read_to_string(&mut s)?;
239 ///    Ok(s)
240 /// }
241 /// ```
242 #[derive(Debug)]
243 pub struct MultiGzDecoder<R> {
244     inner: bufread::MultiGzDecoder<BufReader<R>>,
245 }
246 
247 impl<R: Read> MultiGzDecoder<R> {
248     /// Creates a new decoder from the given reader, immediately parsing the
249     /// (first) gzip header. If the gzip stream contains multiple members all will
250     /// be decoded.
new(r: R) -> MultiGzDecoder<R>251     pub fn new(r: R) -> MultiGzDecoder<R> {
252         MultiGzDecoder {
253             inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
254         }
255     }
256 }
257 
258 impl<R> MultiGzDecoder<R> {
259     /// Returns the current header associated with this stream, if it's valid.
header(&self) -> Option<&GzHeader>260     pub fn header(&self) -> Option<&GzHeader> {
261         self.inner.header()
262     }
263 
264     /// Acquires a reference to the underlying reader.
get_ref(&self) -> &R265     pub fn get_ref(&self) -> &R {
266         self.inner.get_ref().get_ref()
267     }
268 
269     /// Acquires a mutable reference to the underlying stream.
270     ///
271     /// Note that mutation of the stream may result in surprising results if
272     /// this decoder is continued to be used.
get_mut(&mut self) -> &mut R273     pub fn get_mut(&mut self) -> &mut R {
274         self.inner.get_mut().get_mut()
275     }
276 
277     /// Consumes this decoder, returning the underlying reader.
into_inner(self) -> R278     pub fn into_inner(self) -> R {
279         self.inner.into_inner().into_inner()
280     }
281 }
282 
283 impl<R: Read> Read for MultiGzDecoder<R> {
read(&mut self, into: &mut [u8]) -> io::Result<usize>284     fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
285         self.inner.read(into)
286     }
287 }
288 
289 impl<R: Read + Write> Write for MultiGzDecoder<R> {
write(&mut self, buf: &[u8]) -> io::Result<usize>290     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
291         self.get_mut().write(buf)
292     }
293 
flush(&mut self) -> io::Result<()>294     fn flush(&mut self) -> io::Result<()> {
295         self.get_mut().flush()
296     }
297 }
298 
299 #[cfg(test)]
300 mod tests {
301     use std::io::{Cursor, ErrorKind, Read, Result, Write};
302 
303     use super::GzDecoder;
304 
305     //a cursor turning EOF into blocking errors
306     #[derive(Debug)]
307     pub struct BlockingCursor {
308         pub cursor: Cursor<Vec<u8>>,
309     }
310 
311     impl BlockingCursor {
new() -> BlockingCursor312         pub fn new() -> BlockingCursor {
313             BlockingCursor {
314                 cursor: Cursor::new(Vec::new()),
315             }
316         }
317 
set_position(&mut self, pos: u64)318         pub fn set_position(&mut self, pos: u64) {
319             return self.cursor.set_position(pos);
320         }
321     }
322 
323     impl Write for BlockingCursor {
write(&mut self, buf: &[u8]) -> Result<usize>324         fn write(&mut self, buf: &[u8]) -> Result<usize> {
325             return self.cursor.write(buf);
326         }
flush(&mut self) -> Result<()>327         fn flush(&mut self) -> Result<()> {
328             return self.cursor.flush();
329         }
330     }
331 
332     impl Read for BlockingCursor {
read(&mut self, buf: &mut [u8]) -> Result<usize>333         fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
334             //use the cursor, except it turns eof into blocking error
335             let r = self.cursor.read(buf);
336             match r {
337                 Err(ref err) => {
338                     if err.kind() == ErrorKind::UnexpectedEof {
339                         return Err(ErrorKind::WouldBlock.into());
340                     }
341                 }
342                 Ok(0) => {
343                     //regular EOF turned into blocking error
344                     return Err(ErrorKind::WouldBlock.into());
345                 }
346                 Ok(_n) => {}
347             }
348             return r;
349         }
350     }
351 
352     #[test]
blocked_partial_header_read()353     fn blocked_partial_header_read() {
354         // this is a reader which receives data afterwards
355         let mut r = BlockingCursor::new();
356         let data = vec![1, 2, 3];
357 
358         match r.write_all(&data) {
359             Ok(()) => {}
360             _ => {
361                 panic!("Unexpected result for write_all");
362             }
363         }
364         r.set_position(0);
365 
366         // this is unused except for the buffering
367         let mut decoder = GzDecoder::new(r);
368         let mut out = Vec::with_capacity(7);
369         match decoder.read(&mut out) {
370             Err(e) => {
371                 assert_eq!(e.kind(), ErrorKind::WouldBlock);
372             }
373             _ => {
374                 panic!("Unexpected result for decoder.read");
375             }
376         }
377     }
378 }
379