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, lvl: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(buf: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(inner: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(buf: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 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)]
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(inner: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(buf: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}
379