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