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