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 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>> { |
28 | /// let mut ret_vec = [0;100]; |
29 | /// let bytestring = b"hello world" ; |
30 | /// let mut gz = GzEncoder::new(&bytestring[..], Compression::fast()); |
31 | /// let count = gz.read(&mut ret_vec)?; |
32 | /// Ok(ret_vec[0..count].to_vec()) |
33 | /// } |
34 | /// ``` |
35 | #[derive (Debug)] |
36 | pub struct GzEncoder<R> { |
37 | inner: bufread::GzEncoder<BufReader<R>>, |
38 | } |
39 | |
40 | pub fn gz_encoder<R: Read>(inner: bufread::GzEncoder<BufReader<R>>) -> GzEncoder<R> { |
41 | GzEncoder { inner } |
42 | } |
43 | |
44 | impl<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 |
48 | /// header configuration, see the `GzBuilder` type. |
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> { |
53 | GzBuilder::new().read(r, lvl:level) |
54 | } |
55 | } |
56 | |
57 | impl<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 | |
77 | impl<R: Read> Read for GzEncoder<R> { |
78 | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { |
79 | self.inner.read(buf:into) |
80 | } |
81 | } |
82 | |
83 | impl<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 | |
93 | /// A gzip streaming decoder |
94 | /// |
95 | /// This structure exposes a [`Read`] interface that will consume compressed |
96 | /// data from the underlying reader and emit uncompressed data. |
97 | /// |
98 | /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html |
99 | /// |
100 | /// # Examples |
101 | /// |
102 | /// ``` |
103 | /// |
104 | /// use std::io::prelude::*; |
105 | /// use std::io; |
106 | /// # use flate2::Compression; |
107 | /// # use flate2::write::GzEncoder; |
108 | /// use flate2::read::GzDecoder; |
109 | /// |
110 | /// # fn main() { |
111 | /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); |
112 | /// # e.write_all(b"Hello World" ).unwrap(); |
113 | /// # let bytes = e.finish().unwrap(); |
114 | /// # println!("{}" , decode_reader(bytes).unwrap()); |
115 | /// # } |
116 | /// # |
117 | /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error |
118 | /// // Here &[u8] implements Read |
119 | /// |
120 | /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { |
121 | /// let mut gz = GzDecoder::new(&bytes[..]); |
122 | /// let mut s = String::new(); |
123 | /// gz.read_to_string(&mut s)?; |
124 | /// Ok(s) |
125 | /// } |
126 | /// ``` |
127 | #[derive (Debug)] |
128 | pub struct GzDecoder<R> { |
129 | inner: bufread::GzDecoder<BufReader<R>>, |
130 | } |
131 | |
132 | impl<R: Read> GzDecoder<R> { |
133 | /// Creates a new decoder from the given reader, immediately parsing the |
134 | /// gzip header. |
135 | pub fn new(r: R) -> GzDecoder<R> { |
136 | GzDecoder { |
137 | inner: bufread::GzDecoder::new(BufReader::new(inner:r)), |
138 | } |
139 | } |
140 | } |
141 | |
142 | impl<R> GzDecoder<R> { |
143 | /// Returns the header associated with this stream, if it was valid. |
144 | pub fn header(&self) -> Option<&GzHeader> { |
145 | self.inner.header() |
146 | } |
147 | |
148 | /// Acquires a reference to the underlying reader. |
149 | pub fn get_ref(&self) -> &R { |
150 | self.inner.get_ref().get_ref() |
151 | } |
152 | |
153 | /// Acquires a mutable reference to the underlying stream. |
154 | /// |
155 | /// Note that mutation of the stream may result in surprising results if |
156 | /// this decoder is continued to be used. |
157 | pub fn get_mut(&mut self) -> &mut R { |
158 | self.inner.get_mut().get_mut() |
159 | } |
160 | |
161 | /// Consumes this decoder, returning the underlying reader. |
162 | pub fn into_inner(self) -> R { |
163 | self.inner.into_inner().into_inner() |
164 | } |
165 | } |
166 | |
167 | impl<R: Read> Read for GzDecoder<R> { |
168 | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { |
169 | self.inner.read(buf:into) |
170 | } |
171 | } |
172 | |
173 | impl<R: Read + Write> Write for GzDecoder<R> { |
174 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
175 | self.get_mut().write(buf) |
176 | } |
177 | |
178 | fn flush(&mut self) -> io::Result<()> { |
179 | self.get_mut().flush() |
180 | } |
181 | } |
182 | |
183 | /// A gzip streaming decoder that decodes all members of a multistream |
184 | /// |
185 | /// A gzip member consists of a header, compressed data and a trailer. The [gzip |
186 | /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple |
187 | /// gzip members to be joined in a single stream. `MultiGzDecoder` will |
188 | /// decode all consecutive members while `GzDecoder` will only decompress the |
189 | /// first gzip member. The multistream format is commonly used in bioinformatics, |
190 | /// for example when using the BGZF compressed data. |
191 | /// |
192 | /// This structure exposes a [`Read`] interface that will consume all gzip members |
193 | /// from the underlying reader and emit uncompressed data. |
194 | /// |
195 | /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html |
196 | /// |
197 | /// # Examples |
198 | /// |
199 | /// ``` |
200 | /// use std::io::prelude::*; |
201 | /// use std::io; |
202 | /// # use flate2::Compression; |
203 | /// # use flate2::write::GzEncoder; |
204 | /// use flate2::read::MultiGzDecoder; |
205 | /// |
206 | /// # fn main() { |
207 | /// # let mut e = GzEncoder::new(Vec::new(), Compression::default()); |
208 | /// # e.write_all(b"Hello World" ).unwrap(); |
209 | /// # let bytes = e.finish().unwrap(); |
210 | /// # println!("{}" , decode_reader(bytes).unwrap()); |
211 | /// # } |
212 | /// # |
213 | /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error |
214 | /// // Here &[u8] implements Read |
215 | /// |
216 | /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { |
217 | /// let mut gz = MultiGzDecoder::new(&bytes[..]); |
218 | /// let mut s = String::new(); |
219 | /// gz.read_to_string(&mut s)?; |
220 | /// Ok(s) |
221 | /// } |
222 | /// ``` |
223 | #[derive (Debug)] |
224 | pub struct MultiGzDecoder<R> { |
225 | inner: bufread::MultiGzDecoder<BufReader<R>>, |
226 | } |
227 | |
228 | impl<R: Read> MultiGzDecoder<R> { |
229 | /// Creates a new decoder from the given reader, immediately parsing the |
230 | /// (first) gzip header. If the gzip stream contains multiple members all will |
231 | /// be decoded. |
232 | pub fn new(r: R) -> MultiGzDecoder<R> { |
233 | MultiGzDecoder { |
234 | inner: bufread::MultiGzDecoder::new(BufReader::new(inner:r)), |
235 | } |
236 | } |
237 | } |
238 | |
239 | impl<R> MultiGzDecoder<R> { |
240 | /// Returns the current header associated with this stream, if it's valid. |
241 | pub fn header(&self) -> Option<&GzHeader> { |
242 | self.inner.header() |
243 | } |
244 | |
245 | /// Acquires a reference to the underlying reader. |
246 | pub fn get_ref(&self) -> &R { |
247 | self.inner.get_ref().get_ref() |
248 | } |
249 | |
250 | /// Acquires a mutable reference to the underlying stream. |
251 | /// |
252 | /// Note that mutation of the stream may result in surprising results if |
253 | /// this decoder is continued to be used. |
254 | pub fn get_mut(&mut self) -> &mut R { |
255 | self.inner.get_mut().get_mut() |
256 | } |
257 | |
258 | /// Consumes this decoder, returning the underlying reader. |
259 | pub fn into_inner(self) -> R { |
260 | self.inner.into_inner().into_inner() |
261 | } |
262 | } |
263 | |
264 | impl<R: Read> Read for MultiGzDecoder<R> { |
265 | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { |
266 | self.inner.read(buf:into) |
267 | } |
268 | } |
269 | |
270 | impl<R: Read + Write> Write for MultiGzDecoder<R> { |
271 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { |
272 | self.get_mut().write(buf) |
273 | } |
274 | |
275 | fn flush(&mut self) -> io::Result<()> { |
276 | self.get_mut().flush() |
277 | } |
278 | } |
279 | |