]> git.proxmox.com Git - rustc.git/blame - vendor/flate2/src/gz/read.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / vendor / flate2 / src / gz / read.rs
CommitLineData
ea8adc8c 1use std::io;
60c5eb7d
XL
2use std::io::prelude::*;
3
ea8adc8c 4use super::bufread;
60c5eb7d
XL
5use super::{GzBuilder, GzHeader};
6use crate::bufreader::BufReader;
7use crate::Compression;
ea8adc8c
XL
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::Compression;
23/// use flate2::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>> {
781aab86 28/// let mut ret_vec = Vec::new();
ea8adc8c 29/// let bytestring = b"hello world";
ff7c6d11 30/// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast());
781aab86
FG
31/// gz.read_to_end(&mut ret_vec)?;
32/// Ok(ret_vec)
ea8adc8c
XL
33/// }
34/// ```
35#[derive(Debug)]
36pub struct GzEncoder<R> {
37 inner: bufread::GzEncoder<BufReader<R>>,
38}
39
b7449926 40pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> {
04454e1e 41 GzEncoder { inner }
ea8adc8c
XL
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
ff7c6d11 48 /// header configuration, see the `GzBuilder` type.
ea8adc8c
XL
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> {
ff7c6d11 53 GzBuilder::new().read(r, level)
ea8adc8c
XL
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
781aab86 93/// A decoder for a single member of a [gzip file].
ea8adc8c
XL
94///
95/// This structure exposes a [`Read`] interface that will consume compressed
96/// data from the underlying reader and emit uncompressed data.
97///
781aab86
FG
98/// After reading a single member of the gzip data this reader will return
99/// Ok(0) even if there are more bytes available in the underlying reader.
100/// `GzDecoder` may have read additional bytes past the end of the gzip data.
101/// If you need the following bytes, wrap the `Reader` in a `std::io::BufReader`
102/// and use `bufread::GzDecoder` instead.
103///
104/// To handle gzip files that may have multiple members, see [`MultiGzDecoder`]
105/// or read more
106/// [in the introduction](../index.html#about-multi-member-gzip-files).
107///
108/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
ea8adc8c
XL
109///
110/// # Examples
111///
112/// ```
ea8adc8c
XL
113/// use std::io::prelude::*;
114/// use std::io;
115/// # use flate2::Compression;
116/// # use flate2::write::GzEncoder;
117/// use flate2::read::GzDecoder;
118///
119/// # fn main() {
ff7c6d11 120/// # let mut e = GzEncoder::new(Vec::new(), Compression::default());
b7449926 121/// # e.write_all(b"Hello World").unwrap();
ea8adc8c
XL
122/// # let bytes = e.finish().unwrap();
123/// # println!("{}", decode_reader(bytes).unwrap());
124/// # }
125/// #
126/// // Uncompresses a Gz Encoded vector of bytes and returns a string or error
127/// // Here &[u8] implements Read
128///
129/// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> {
ff7c6d11 130/// let mut gz = GzDecoder::new(&bytes[..]);
ea8adc8c
XL
131/// let mut s = String::new();
132/// gz.read_to_string(&mut s)?;
133/// Ok(s)
134/// }
135/// ```
136#[derive(Debug)]
137pub struct GzDecoder<R> {
138 inner: bufread::GzDecoder<BufReader<R>>,
139}
140
141impl<R: Read> GzDecoder<R> {
142 /// Creates a new decoder from the given reader, immediately parsing the
143 /// gzip header.
ff7c6d11
XL
144 pub fn new(r: R) -> GzDecoder<R> {
145 GzDecoder {
146 inner: bufread::GzDecoder::new(BufReader::new(r)),
147 }
ea8adc8c
XL
148 }
149}
150
151impl<R> GzDecoder<R> {
ff7c6d11
XL
152 /// Returns the header associated with this stream, if it was valid.
153 pub fn header(&self) -> Option<&GzHeader> {
ea8adc8c
XL
154 self.inner.header()
155 }
156
157 /// Acquires a reference to the underlying reader.
781aab86
FG
158 ///
159 /// Note that the decoder may have read past the end of the gzip data.
160 /// To prevent this use [`bufread::GzDecoder`] instead.
ea8adc8c
XL
161 pub fn get_ref(&self) -> &R {
162 self.inner.get_ref().get_ref()
163 }
164
165 /// Acquires a mutable reference to the underlying stream.
166 ///
167 /// Note that mutation of the stream may result in surprising results if
781aab86
FG
168 /// this decoder continues to be used.
169 ///
170 /// Note that the decoder may have read past the end of the gzip data.
171 /// To prevent this use [`bufread::GzDecoder`] instead.
ea8adc8c
XL
172 pub fn get_mut(&mut self) -> &mut R {
173 self.inner.get_mut().get_mut()
174 }
175
176 /// Consumes this decoder, returning the underlying reader.
781aab86
FG
177 ///
178 /// Note that the decoder may have read past the end of the gzip data.
179 /// Subsequent reads will skip those bytes. To prevent this use
180 /// [`bufread::GzDecoder`] instead.
ea8adc8c
XL
181 pub fn into_inner(self) -> R {
182 self.inner.into_inner().into_inner()
183 }
184}
185
186impl<R: Read> Read for GzDecoder<R> {
187 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
188 self.inner.read(into)
189 }
190}
191
192impl<R: Read + Write> Write for GzDecoder<R> {
193 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
194 self.get_mut().write(buf)
195 }
196
197 fn flush(&mut self) -> io::Result<()> {
198 self.get_mut().flush()
199 }
200}
201
781aab86
FG
202/// A gzip streaming decoder that decodes a [gzip file] that may have multiple members.
203///
204/// This structure exposes a [`Read`] interface that will consume compressed
205/// data from the underlying reader and emit uncompressed data.
ea8adc8c 206///
781aab86
FG
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.
ea8adc8c 210///
781aab86
FG
211/// To handle members seperately, see [GzDecoder] or read more
212/// [in the introduction](../index.html#about-multi-member-gzip-files).
ea8adc8c 213///
781aab86 214/// [gzip file]: https://www.rfc-editor.org/rfc/rfc1952#page-5
ea8adc8c
XL
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() {
ff7c6d11 226/// # let mut e = GzEncoder::new(Vec::new(), Compression::default());
b7449926 227/// # e.write_all(b"Hello World").unwrap();
ea8adc8c
XL
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> {
ff7c6d11 236/// let mut gz = MultiGzDecoder::new(&bytes[..]);
ea8adc8c
XL
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.
ff7c6d11
XL
251 pub fn new(r: R) -> MultiGzDecoder<R> {
252 MultiGzDecoder {
253 inner: bufread::MultiGzDecoder::new(BufReader::new(r)),
254 }
ea8adc8c
XL
255 }
256}
257
258impl<R> MultiGzDecoder<R> {
ff7c6d11
XL
259 /// Returns the current header associated with this stream, if it's valid.
260 pub fn header(&self) -> Option<&GzHeader> {
ea8adc8c
XL
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
fe692bf9 272 /// this decoder is continued to be used.
ea8adc8c
XL
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(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}
781aab86
FG
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}