flate2/gz/read.rs
1use crate::io;
2use crate::io::{Read, Write};
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 /// The underlying reader may be mutated as long as its unread input and
65 /// current position are preserved for subsequent reads by this encoder.
66 ///
67 /// To process a new stream, wait for this encoder to reach EOF and create a
68 /// new encoder; replacing the reader directly does not reset it.
69 pub fn get_mut(&mut self) -> &mut R {
70 self.inner.get_mut().get_mut()
71 }
72
73 /// Returns the underlying stream, consuming this encoder
74 pub fn into_inner(self) -> R {
75 self.inner.into_inner().into_inner()
76 }
77}
78
79impl<R: Read> Read for GzEncoder<R> {
80 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
81 self.inner.read(into)
82 }
83}
84
85impl<R: Read + Write> Write for GzEncoder<R> {
86 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
87 self.get_mut().write(buf)
88 }
89
90 fn flush(&mut self) -> io::Result<()> {
91 self.get_mut().flush()
92 }
93}
94
95/// A decoder for a single member of a [gzip file].
96///
97/// This structure implements a [`Read`] interface. When read from, it reads
98/// compressed data from the underlying [`Read`] and provides the uncompressed data.
99///
100/// After reading a single member of the gzip data this reader will return
101/// Ok(0) even if there are more bytes available in the underlying reader.
102/// `GzDecoder` may have read additional bytes past the end of the gzip data.
103/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader`
104/// and use `bufread::GzDecoder` instead.
105///
106/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
107/// or read more
108/// [in the introduction](../index.html#about-multi-member-gzip-files).
109///
110/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
111///
112/// # Examples
113///
114/// ```
115/// use std::io::prelude::*;
116/// use std::io;
117/// # use flate2::Compression;
118/// # use flate2::write::GzEncoder;
119/// use flate2::read::GzDecoder;
120///
121/// # fn main() {
122/// # let mut e = GzEncoder::new(Vec::new(), Compression::default());
123/// # e.write_all(b"Hello World").unwrap();
124/// # let bytes = e.finish().unwrap();
125/// # println!("{}", decode_reader(bytes).unwrap());
126/// # }
127/// #
128/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
129/// // Here &[u8] implements Read
130///
131/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
132/// let mut gz = GzDecoder::new(&bytes[..]);
133/// let mut s = String::new();
134/// gz.read_to_string(&mut s)?;
135/// Ok(s)
136/// }
137/// ```
138#[derive(Debug)]
139pub struct GzDecoder<R> {
140 inner: bufread::GzDecoder<BufReader<R>>,
141}
142
143impl<R: Read> GzDecoder<R> {
144 /// Creates a new decoder from the given reader, immediately parsing the
145 /// gzip header.
146 pub fn new(r: R) -> GzDecoder<R> {
147 GzDecoder {
148 inner: bufread::GzDecoder::new(BufReader::new(r)),
149 }
150 }
151}
152
153impl<R> GzDecoder<R> {
154 /// Returns the header associated with this stream, if it was valid.
155 pub fn header(&self) -> Option<&GzHeader> {
156 self.inner.header()
157 }
158
159 /// Acquires a reference to the underlying reader.
160 ///
161 /// Note that the decoder may have read past the end of the gzip data.
162 /// To prevent this use [`bufread::GzDecoder`] instead.
163 pub fn get_ref(&self) -> &R {
164 self.inner.get_ref().get_ref()
165 }
166
167 /// Acquires a mutable reference to the underlying stream.
168 ///
169 /// The underlying reader may be mutated as long as its unread input and
170 /// current position are preserved for subsequent reads by this decoder.
171 ///
172 /// To process a new stream, wait for this decoder to reach EOF and use
173 /// [`reset`](Self::reset); replacing the reader directly does not reset it.
174 ///
175 /// Note that the decoder may have read past the end of the gzip data.
176 /// To prevent this use [`bufread::GzDecoder`] instead.
177 pub fn get_mut(&mut self) -> &mut R {
178 self.inner.get_mut().get_mut()
179 }
180
181 /// Consumes this decoder, returning the underlying reader.
182 ///
183 /// Note that the decoder may have read past the end of the gzip data.
184 /// Subsequent reads will skip those bytes. To prevent this use
185 /// [`bufread::GzDecoder`] instead.
186 pub fn into_inner(self) -> R {
187 self.inner.into_inner().into_inner()
188 }
189
190 /// Resets the state of this decoder entirely, swapping out the input
191 /// stream for another.
192 ///
193 /// This will reset the internal state of this decoder and replace the
194 /// input stream with the one provided, returning the previous input
195 /// stream. Future data read from this decoder will be the decompressed
196 /// version of `r`'s data.
197 ///
198 /// Note that there may be currently buffered data when this function is
199 /// called, and in that case the buffered data is discarded.
200 pub fn reset(&mut self, r: R) -> R {
201 super::bufread::reset_decoder_data(&mut self.inner);
202 self.inner.get_mut().reset(r)
203 }
204}
205
206impl<R: Read> Read for GzDecoder<R> {
207 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
208 self.inner.read(into)
209 }
210}
211
212impl<R: Read + Write> Write for GzDecoder<R> {
213 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
214 self.get_mut().write(buf)
215 }
216
217 fn flush(&mut self) -> io::Result<()> {
218 self.get_mut().flush()
219 }
220}
221
222/// A gzip streaming decoder that decodes a [gzip file] that may have multiple members.
223///
224/// This structure implements a [`Read`] interface. When read from, it reads
225/// compressed data from the underlying [`Read`] and provides the uncompressed
226/// data.
227///
228/// A gzip file consists of a series of *members* concatenated one after another.
229/// MultiGzDecoder decodes all members of a file and returns Ok(0) once the
230/// underlying reader does.
231///
232/// To handle members separately, see [GzDecoder] or read more
233/// [in the introduction](../index.html#about-multi-member-gzip-files).
234///
235/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
236///
237/// # Examples
238///
239/// ```
240/// use std::io::prelude::*;
241/// use std::io;
242/// # use flate2::Compression;
243/// # use flate2::write::GzEncoder;
244/// use flate2::read::MultiGzDecoder;
245///
246/// # fn main() {
247/// # let mut e = GzEncoder::new(Vec::new(), Compression::default());
248/// # e.write_all(b"Hello World").unwrap();
249/// # let bytes = e.finish().unwrap();
250/// # println!("{}", decode_reader(bytes).unwrap());
251/// # }
252/// #
253/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
254/// // Here &[u8] implements Read
255///
256/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
257/// let mut gz = MultiGzDecoder::new(&bytes[..]);
258/// let mut s = String::new();
259/// gz.read_to_string(&mut s)?;
260/// Ok(s)
261/// }
262/// ```
263#[derive(Debug)]
264pub struct MultiGzDecoder<R> {
265 inner: bufread::MultiGzDecoder<BufReader<R>>,
266}
267
268impl<R: Read> MultiGzDecoder<R> {
269 /// Creates a new decoder from the given reader, immediately parsing the
270 /// (first) gzip header. If the gzip stream contains multiple members all will
271 /// be decoded.
272 pub fn new(r: R) -> MultiGzDecoder<R> {
273 MultiGzDecoder {
274 inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
275 }
276 }
277}
278
279impl<R> MultiGzDecoder<R> {
280 /// Returns the current header associated with this stream, if it's valid.
281 pub fn header(&self) -> Option<&GzHeader> {
282 self.inner.header()
283 }
284
285 /// Acquires a reference to the underlying reader.
286 pub fn get_ref(&self) -> &R {
287 self.inner.get_ref().get_ref()
288 }
289
290 /// Acquires a mutable reference to the underlying stream.
291 ///
292 /// The underlying reader may be mutated as long as its unread input and
293 /// current position are preserved for subsequent reads by this decoder.
294 ///
295 /// To process a new stream, wait for this decoder to reach EOF and create a
296 /// new decoder; replacing the reader directly does not reset it.
297 pub fn get_mut(&mut self) -> &mut R {
298 self.inner.get_mut().get_mut()
299 }
300
301 /// Consumes this decoder, returning the underlying reader.
302 pub fn into_inner(self) -> R {
303 self.inner.into_inner().into_inner()
304 }
305}
306
307impl<R: Read> Read for MultiGzDecoder<R> {
308 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
309 self.inner.read(into)
310 }
311}
312
313impl<R: Read + Write> Write for MultiGzDecoder<R> {
314 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
315 self.get_mut().write(buf)
316 }
317
318 fn flush(&mut self) -> io::Result<()> {
319 self.get_mut().flush()
320 }
321}
322
323#[cfg(test)]
324mod tests {
325 use crate::io::{Cursor, ErrorKind, Read, Result, Write};
326 use alloc::vec::Vec;
327
328 use super::GzDecoder;
329
330 //a cursor turning EOF into blocking errors
331 #[derive(Debug)]
332 pub struct BlockingCursor {
333 pub cursor: Cursor<Vec<u8>>,
334 }
335
336 impl BlockingCursor {
337 pub fn new() -> BlockingCursor {
338 BlockingCursor {
339 cursor: Cursor::new(Vec::new()),
340 }
341 }
342
343 pub fn set_position(&mut self, pos: u64) {
344 self.cursor.set_position(pos)
345 }
346 }
347
348 impl Write for BlockingCursor {
349 fn write(&mut self, buf: &[u8]) -> Result<usize> {
350 self.cursor.write(buf)
351 }
352 fn flush(&mut self) -> Result<()> {
353 self.cursor.flush()
354 }
355 }
356
357 impl Read for BlockingCursor {
358 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
359 //use the cursor, except it turns eof into blocking error
360 let r = self.cursor.read(buf);
361 match r {
362 Err(ref err) => {
363 if err.kind() == ErrorKind::UnexpectedEof {
364 return Err(ErrorKind::WouldBlock.into());
365 }
366 }
367 Ok(0) => {
368 //regular EOF turned into blocking error
369 return Err(ErrorKind::WouldBlock.into());
370 }
371 Ok(_n) => {}
372 }
373 r
374 }
375 }
376
377 #[test]
378 fn blocked_partial_header_read() {
379 // this is a reader which receives data afterwards
380 let mut r = BlockingCursor::new();
381 let data = vec![1, 2, 3];
382
383 match r.write_all(&data) {
384 Ok(()) => {}
385 _ => {
386 panic!("Unexpected result for write_all");
387 }
388 }
389 r.set_position(0);
390
391 // this is unused except for the buffering
392 let mut decoder = GzDecoder::new(r);
393 let mut out = Vec::with_capacity(7);
394 match decoder.read(&mut out) {
395 Err(e) => {
396 assert_eq!(e.kind(), ErrorKind::WouldBlock);
397 }
398 _ => {
399 panic!("Unexpected result for decoder.read");
400 }
401 }
402 }
403
404 fn compress_data(data: &[u8]) -> Vec<u8> {
405 use crate::write::GzEncoder;
406 use crate::Compression;
407
408 let mut e = GzEncoder::new(Vec::new(), Compression::default());
409 e.write_all(data).unwrap();
410 e.finish().unwrap()
411 }
412
413 #[test]
414 fn decode_with_reset() {
415 let data1 = b"Hello World";
416 let data2 = b"Goodbye World";
417
418 let compressed1 = compress_data(data1);
419 let compressed2 = compress_data(data2);
420
421 let mut output = Vec::new();
422 let mut decoder = GzDecoder::new(compressed1.as_slice());
423 decoder.read_to_end(&mut output).unwrap();
424 assert_eq!(output, data1);
425
426 output.clear();
427 decoder.reset(compressed2.as_slice());
428 decoder.read_to_end(&mut output).unwrap();
429 assert_eq!(output, data2);
430 }
431
432 #[test]
433 fn decode_with_reset_after_corruption() {
434 let valid_data = b"Hello World";
435 let valid_compressed = compress_data(valid_data);
436
437 // Create a corrupted payload (valid gzip header but corrupted body)
438 let mut corrupted = valid_compressed.clone();
439 assert!(corrupted.len() > 13);
440 corrupted[12] ^= 0xFF;
441 corrupted[13] ^= 0xFF;
442
443 // Try to decode corrupted data
444 let mut decoder = GzDecoder::new(Cursor::new(corrupted));
445 let mut output = Vec::new();
446 let _ = decoder.read_to_end(&mut output).unwrap_err();
447
448 // Reset with valid payload and decode
449 decoder.reset(Cursor::new(valid_compressed));
450 output.clear();
451 decoder.read_to_end(&mut output).unwrap();
452 assert_eq!(output, valid_data);
453 }
454}