flate2/gz/
read.rs

1use std::io;
2use std::io::prelude::*;
3
4use super::bufread;
5use super::{GzBuilder, GzHeader};
6use crate::bufreader::BufReader;
7use 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)]
35pub struct GzEncoder<R> {
36    inner: bufread::GzEncoder<BufReader<R>>,
37}
38
39pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> {
40    GzEncoder { inner }
41}
42
43impl<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.
51    pub fn new(r: R, level: Compression) -> GzEncoder<R> {
52        GzBuilder::new().read(r, level)
53    }
54}
55
56impl<R> GzEncoder<R> {
57    /// Acquires a reference to the underlying reader.
58    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.
66    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
71    pub fn into_inner(self) -> R {
72        self.inner.into_inner().into_inner()
73    }
74}
75
76impl<R: Read> Read for GzEncoder<R> {
77    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
78        self.inner.read(into)
79    }
80}
81
82impl<R: Read + Write> Write for GzEncoder<R> {
83    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
84        self.get_mut().write(buf)
85    }
86
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)]
136pub struct GzDecoder<R> {
137    inner: bufread::GzDecoder<BufReader<R>>,
138}
139
140impl<R: Read> GzDecoder<R> {
141    /// Creates a new decoder from the given reader, immediately parsing the
142    /// gzip header.
143    pub fn new(r: R) -> GzDecoder<R> {
144        GzDecoder {
145            inner: bufread::GzDecoder::new(BufReader::new(r)),
146        }
147    }
148}
149
150impl<R> GzDecoder<R> {
151    /// Returns the header associated with this stream, if it was valid.
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.
160    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.
171    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.
180    pub fn into_inner(self) -> R {
181        self.inner.into_inner().into_inner()
182    }
183}
184
185impl<R: Read> Read for GzDecoder<R> {
186    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
187        self.inner.read(into)
188    }
189}
190
191impl<R: Read + Write> Write for GzDecoder<R> {
192    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
193        self.get_mut().write(buf)
194    }
195
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 separately, 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)]
243pub struct MultiGzDecoder<R> {
244    inner: bufread::MultiGzDecoder<BufReader<R>>,
245}
246
247impl<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.
251    pub fn new(r: R) -> MultiGzDecoder<R> {
252        MultiGzDecoder {
253            inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
254        }
255    }
256}
257
258impl<R> MultiGzDecoder<R> {
259    /// Returns the current header associated with this stream, if it's valid.
260    pub fn header(&self) -> Option<&GzHeader> {
261        self.inner.header()
262    }
263
264    /// Acquires a reference to the underlying reader.
265    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.
273    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.
278    pub fn into_inner(self) -> R {
279        self.inner.into_inner().into_inner()
280    }
281}
282
283impl<R: Read> Read for MultiGzDecoder<R> {
284    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
285        self.inner.read(into)
286    }
287}
288
289impl<R: Read + Write> Write for MultiGzDecoder<R> {
290    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
291        self.get_mut().write(buf)
292    }
293
294    fn flush(&mut self) -> io::Result<()> {
295        self.get_mut().flush()
296    }
297}
298
299#[cfg(test)]
300mod 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 {
312        pub fn new() -> BlockingCursor {
313            BlockingCursor {
314                cursor: Cursor::new(Vec::new()),
315            }
316        }
317
318        pub fn set_position(&mut self, pos: u64) {
319            return self.cursor.set_position(pos);
320        }
321    }
322
323    impl Write for BlockingCursor {
324        fn write(&mut self, buf: &[u8]) -> Result<usize> {
325            return self.cursor.write(buf);
326        }
327        fn flush(&mut self) -> Result<()> {
328            return self.cursor.flush();
329        }
330    }
331
332    impl Read for BlockingCursor {
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]
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}