Skip to main content

flate2_expose/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 exposes a [`Read`] interface that will read uncompressed data
12/// from the underlying reader and expose the compressed version as a [`Read`]
13/// interface.
14///
15/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
16///
17/// # Examples
18///
19/// ```
20/// use std::io::prelude::*;
21/// use std::io;
22/// use flate2_expose::Compression;
23/// use flate2_expose::read::GzEncoder;
24///
25/// // Return a vector containing the GZ compressed version of hello world
26///
27/// fn gzencode_hello_world() -> io::Result<Vec<u8>> {
28///     let mut ret_vec = [0;100];
29///     let bytestring = b"hello world";
30///     let mut gz = GzEncoder::new(&bytestring[..], Compression::fast());
31///     let count = gz.read(&mut ret_vec)?;
32///     Ok(ret_vec[0..count].to_vec())
33/// }
34/// ```
35#[derive(Debug)]
36pub struct GzEncoder<R> {
37    inner: bufread::GzEncoder<BufReader<R>>,
38}
39
40pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> {
41    GzEncoder { inner }
42}
43
44impl<R: Read> GzEncoder<R> {
45    /// Creates a new encoder which will use the given compression level.
46    ///
47    /// The encoder is not configured specially for the emitted header. For
48    /// header configuration, see the `GzBuilder` type.
49    ///
50    /// The data read from the stream `r` will be compressed and available
51    /// through the returned reader.
52    pub fn new(r: R, level: Compression) -> GzEncoder<R> {
53        GzBuilder::new().read(r, level)
54    }
55}
56
57impl<R> GzEncoder<R> {
58    /// Acquires a reference to the underlying reader.
59    pub fn get_ref(&self) -> &R {
60        self.inner.get_ref().get_ref()
61    }
62
63    /// Acquires a mutable reference to the underlying reader.
64    ///
65    /// Note that mutation of the reader may result in surprising results if
66    /// this encoder is continued to be used.
67    pub fn get_mut(&mut self) -> &mut R {
68        self.inner.get_mut().get_mut()
69    }
70
71    /// Returns the underlying stream, consuming this encoder
72    pub fn into_inner(self) -> R {
73        self.inner.into_inner().into_inner()
74    }
75}
76
77impl<R: Read> Read for GzEncoder<R> {
78    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
79        self.inner.read(into)
80    }
81}
82
83impl<R: Read + Write> Write for GzEncoder<R> {
84    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
85        self.get_mut().write(buf)
86    }
87
88    fn flush(&mut self) -> io::Result<()> {
89        self.get_mut().flush()
90    }
91}
92
93/// A gzip streaming decoder
94///
95/// This structure exposes a [`Read`] interface that will consume compressed
96/// data from the underlying reader and emit uncompressed data.
97///
98/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
99///
100/// # Examples
101///
102/// ```
103///
104/// use std::io::prelude::*;
105/// use std::io;
106/// # use flate2_expose::Compression;
107/// # use flate2_expose::write::GzEncoder;
108/// use flate2_expose::read::GzDecoder;
109///
110/// # fn main() {
111/// #    let mut e = GzEncoder::new(Vec::new(), Compression::default());
112/// #    e.write_all(b"Hello World").unwrap();
113/// #    let bytes = e.finish().unwrap();
114/// #    println!("{}", decode_reader(bytes).unwrap());
115/// # }
116/// #
117/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
118/// // Here &[u8] implements Read
119///
120/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
121///    let mut gz = GzDecoder::new(&bytes[..]);
122///    let mut s = String::new();
123///    gz.read_to_string(&mut s)?;
124///    Ok(s)
125/// }
126/// ```
127#[derive(Debug)]
128pub struct GzDecoder<R> {
129    inner: bufread::GzDecoder<BufReader<R>>,
130}
131
132impl<R: Read> GzDecoder<R> {
133    /// Creates a new decoder from the given reader, immediately parsing the
134    /// gzip header.
135    pub fn new(r: R) -> GzDecoder<R> {
136        GzDecoder {
137            inner: bufread::GzDecoder::new(BufReader::new(r)),
138        }
139    }
140}
141
142impl<R> GzDecoder<R> {
143    /// Returns the header associated with this stream, if it was valid.
144    pub fn header(&self) -> Option<&GzHeader> {
145        self.inner.header()
146    }
147
148    /// Acquires a reference to the underlying reader.
149    pub fn get_ref(&self) -> &R {
150        self.inner.get_ref().get_ref()
151    }
152
153    /// Acquires a mutable reference to the underlying stream.
154    ///
155    /// Note that mutation of the stream may result in surprising results if
156    /// this encoder is continued to be used.
157    pub fn get_mut(&mut self) -> &mut R {
158        self.inner.get_mut().get_mut()
159    }
160
161    /// Consumes this decoder, returning the underlying reader.
162    pub fn into_inner(self) -> R {
163        self.inner.into_inner().into_inner()
164    }
165}
166
167impl<R: Read> Read for GzDecoder<R> {
168    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
169        self.inner.read(into)
170    }
171}
172
173impl<R: Read + Write> Write for GzDecoder<R> {
174    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
175        self.get_mut().write(buf)
176    }
177
178    fn flush(&mut self) -> io::Result<()> {
179        self.get_mut().flush()
180    }
181}
182
183/// A gzip streaming decoder that decodes all members of a multistream
184///
185/// A gzip member consists of a header, compressed data and a trailer. The [gzip
186/// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple
187/// gzip members to be joined in a single stream.  `MultiGzDecoder` will
188/// decode all consecutive members while `GzDecoder` will only decompress the
189/// first gzip member. The multistream format is commonly used in bioinformatics,
190/// for example when using the BGZF compressed data.
191///
192/// This structure exposes a [`Read`] interface that will consume all gzip members
193/// from the underlying reader and emit uncompressed data.
194///
195/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
196///
197/// # Examples
198///
199/// ```
200/// use std::io::prelude::*;
201/// use std::io;
202/// # use flate2_expose::Compression;
203/// # use flate2_expose::write::GzEncoder;
204/// use flate2_expose::read::MultiGzDecoder;
205///
206/// # fn main() {
207/// #    let mut e = GzEncoder::new(Vec::new(), Compression::default());
208/// #    e.write_all(b"Hello World").unwrap();
209/// #    let bytes = e.finish().unwrap();
210/// #    println!("{}", decode_reader(bytes).unwrap());
211/// # }
212/// #
213/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
214/// // Here &[u8] implements Read
215///
216/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
217///    let mut gz = MultiGzDecoder::new(&bytes[..]);
218///    let mut s = String::new();
219///    gz.read_to_string(&mut s)?;
220///    Ok(s)
221/// }
222/// ```
223#[derive(Debug)]
224pub struct MultiGzDecoder<R> {
225    inner: bufread::MultiGzDecoder<BufReader<R>>,
226}
227
228impl<R: Read> MultiGzDecoder<R> {
229    /// Creates a new decoder from the given reader, immediately parsing the
230    /// (first) gzip header. If the gzip stream contains multiple members all will
231    /// be decoded.
232    pub fn new(r: R) -> MultiGzDecoder<R> {
233        MultiGzDecoder {
234            inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
235        }
236    }
237}
238
239impl<R> MultiGzDecoder<R> {
240    /// Returns the current header associated with this stream, if it's valid.
241    pub fn header(&self) -> Option<&GzHeader> {
242        self.inner.header()
243    }
244
245    /// Acquires a reference to the underlying reader.
246    pub fn get_ref(&self) -> &R {
247        self.inner.get_ref().get_ref()
248    }
249
250    /// Acquires a mutable reference to the underlying stream.
251    ///
252    /// Note that mutation of the stream may result in surprising results if
253    /// this encoder is continued to be used.
254    pub fn get_mut(&mut self) -> &mut R {
255        self.inner.get_mut().get_mut()
256    }
257
258    /// Consumes this decoder, returning the underlying reader.
259    pub fn into_inner(self) -> R {
260        self.inner.into_inner().into_inner()
261    }
262}
263
264impl<R: Read> Read for MultiGzDecoder<R> {
265    fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
266        self.inner.read(into)
267    }
268}
269
270impl<R: Read + Write> Write for MultiGzDecoder<R> {
271    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
272        self.get_mut().write(buf)
273    }
274
275    fn flush(&mut self) -> io::Result<()> {
276        self.get_mut().flush()
277    }
278}