]>
Commit | Line | Data |
---|---|---|
ea8adc8c XL |
1 | use std::io::prelude::*; |
2 | use std::io; | |
3 | ||
4 | use super::{Builder, Header}; | |
5 | use Compression; | |
6 | use bufreader::BufReader; | |
7 | use super::bufread; | |
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>>) | |
41 | -> GzEncoder<R> | |
42 | { | |
43 | GzEncoder { inner: inner } | |
44 | } | |
45 | ||
46 | impl<R: Read> GzEncoder<R> { | |
47 | /// Creates a new encoder which will use the given compression level. | |
48 | /// | |
49 | /// The encoder is not configured specially for the emitted header. For | |
50 | /// header configuration, see the `Builder` type. | |
51 | /// | |
52 | /// The data read from the stream `r` will be compressed and available | |
53 | /// through the returned reader. | |
54 | pub fn new(r: R, level: Compression) -> GzEncoder<R> { | |
55 | Builder::new().read(r, level) | |
56 | } | |
57 | } | |
58 | ||
59 | impl<R> GzEncoder<R> { | |
60 | /// Acquires a reference to the underlying reader. | |
61 | pub fn get_ref(&self) -> &R { | |
62 | self.inner.get_ref().get_ref() | |
63 | } | |
64 | ||
65 | /// Acquires a mutable reference to the underlying reader. | |
66 | /// | |
67 | /// Note that mutation of the reader may result in surprising results if | |
68 | /// this encoder is continued to be used. | |
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 | ||
79 | impl<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 | ||
85 | impl<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 gzip streaming decoder | |
96 | /// | |
97 | /// This structure exposes a [`Read`] interface that will consume compressed | |
98 | /// data from the underlying reader and emit uncompressed data. | |
99 | /// | |
100 | /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html | |
101 | /// | |
102 | /// # Examples | |
103 | /// | |
104 | /// ``` | |
105 | /// | |
106 | /// use std::io::prelude::*; | |
107 | /// use std::io; | |
108 | /// # use flate2::Compression; | |
109 | /// # use flate2::write::GzEncoder; | |
110 | /// use flate2::read::GzDecoder; | |
111 | /// | |
112 | /// # fn main() { | |
113 | /// # let mut e = GzEncoder::new(Vec::new(), Compression::Default); | |
114 | /// # e.write(b"Hello World").unwrap(); | |
115 | /// # let bytes = e.finish().unwrap(); | |
116 | /// # println!("{}", decode_reader(bytes).unwrap()); | |
117 | /// # } | |
118 | /// # | |
119 | /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error | |
120 | /// // Here &[u8] implements Read | |
121 | /// | |
122 | /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { | |
123 | /// let mut gz = GzDecoder::new(&bytes[..])?; | |
124 | /// let mut s = String::new(); | |
125 | /// gz.read_to_string(&mut s)?; | |
126 | /// Ok(s) | |
127 | /// } | |
128 | /// ``` | |
129 | #[derive(Debug)] | |
130 | pub struct GzDecoder<R> { | |
131 | inner: bufread::GzDecoder<BufReader<R>>, | |
132 | } | |
133 | ||
134 | impl<R: Read> GzDecoder<R> { | |
135 | /// Creates a new decoder from the given reader, immediately parsing the | |
136 | /// gzip header. | |
137 | /// | |
138 | /// # Errors | |
139 | /// | |
140 | /// If an error is encountered when parsing the gzip header, an error is | |
141 | /// returned. | |
142 | pub fn new(r: R) -> io::Result<GzDecoder<R>> { | |
143 | bufread::GzDecoder::new(BufReader::new(r)).map(|r| GzDecoder { inner: r }) | |
144 | } | |
145 | } | |
146 | ||
147 | impl<R> GzDecoder<R> { | |
148 | /// Returns the header associated with this stream. | |
149 | pub fn header(&self) -> &Header { | |
150 | self.inner.header() | |
151 | } | |
152 | ||
153 | /// Acquires a reference to the underlying reader. | |
154 | pub fn get_ref(&self) -> &R { | |
155 | self.inner.get_ref().get_ref() | |
156 | } | |
157 | ||
158 | /// Acquires a mutable reference to the underlying stream. | |
159 | /// | |
160 | /// Note that mutation of the stream may result in surprising results if | |
161 | /// this encoder is continued to be used. | |
162 | pub fn get_mut(&mut self) -> &mut R { | |
163 | self.inner.get_mut().get_mut() | |
164 | } | |
165 | ||
166 | /// Consumes this decoder, returning the underlying reader. | |
167 | pub fn into_inner(self) -> R { | |
168 | self.inner.into_inner().into_inner() | |
169 | } | |
170 | } | |
171 | ||
172 | impl<R: Read> Read for GzDecoder<R> { | |
173 | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { | |
174 | self.inner.read(into) | |
175 | } | |
176 | } | |
177 | ||
178 | impl<R: Read + Write> Write for GzDecoder<R> { | |
179 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
180 | self.get_mut().write(buf) | |
181 | } | |
182 | ||
183 | fn flush(&mut self) -> io::Result<()> { | |
184 | self.get_mut().flush() | |
185 | } | |
186 | } | |
187 | ||
188 | /// A gzip streaming decoder that decodes all members of a multistream | |
189 | /// | |
190 | /// A gzip member consists of a header, compressed data and a trailer. The [gzip | |
191 | /// specification](https://tools.ietf.org/html/rfc1952), however, allows multiple | |
192 | /// gzip members to be joined in a single stream. `MultiGzDecoder` will | |
193 | /// decode all consecutive members while `GzDecoder` will only decompress the | |
194 | /// first gzip member. The multistream format is commonly used in bioinformatics, | |
195 | /// for example when using the BGZF compressed data. | |
196 | /// | |
197 | /// This structure exposes a [`Read`] interface that will consume all gzip members | |
198 | /// from the underlying reader and emit uncompressed data. | |
199 | /// | |
200 | /// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html | |
201 | /// | |
202 | /// # Examples | |
203 | /// | |
204 | /// ``` | |
205 | /// use std::io::prelude::*; | |
206 | /// use std::io; | |
207 | /// # use flate2::Compression; | |
208 | /// # use flate2::write::GzEncoder; | |
209 | /// use flate2::read::MultiGzDecoder; | |
210 | /// | |
211 | /// # fn main() { | |
212 | /// # let mut e = GzEncoder::new(Vec::new(), Compression::Default); | |
213 | /// # e.write(b"Hello World").unwrap(); | |
214 | /// # let bytes = e.finish().unwrap(); | |
215 | /// # println!("{}", decode_reader(bytes).unwrap()); | |
216 | /// # } | |
217 | /// # | |
218 | /// // Uncompresses a Gz Encoded vector of bytes and returns a string or error | |
219 | /// // Here &[u8] implements Read | |
220 | /// | |
221 | /// fn decode_reader(bytes: Vec<u8>) -> io::Result<String> { | |
222 | /// let mut gz = MultiGzDecoder::new(&bytes[..])?; | |
223 | /// let mut s = String::new(); | |
224 | /// gz.read_to_string(&mut s)?; | |
225 | /// Ok(s) | |
226 | /// } | |
227 | /// ``` | |
228 | #[derive(Debug)] | |
229 | pub struct MultiGzDecoder<R> { | |
230 | inner: bufread::MultiGzDecoder<BufReader<R>>, | |
231 | } | |
232 | ||
233 | impl<R: Read> MultiGzDecoder<R> { | |
234 | /// Creates a new decoder from the given reader, immediately parsing the | |
235 | /// (first) gzip header. If the gzip stream contains multiple members all will | |
236 | /// be decoded. | |
237 | /// | |
238 | /// # Errors | |
239 | /// | |
240 | /// If an error is encountered when parsing the gzip header, an error is | |
241 | /// returned. | |
242 | pub fn new(r: R) -> io::Result<MultiGzDecoder<R>> { | |
243 | bufread::MultiGzDecoder::new(BufReader::new(r)).map(|r| MultiGzDecoder { inner: r }) | |
244 | } | |
245 | } | |
246 | ||
247 | impl<R> MultiGzDecoder<R> { | |
248 | /// Returns the current header associated with this stream. | |
249 | pub fn header(&self) -> &Header { | |
250 | self.inner.header() | |
251 | } | |
252 | ||
253 | /// Acquires a reference to the underlying reader. | |
254 | pub fn get_ref(&self) -> &R { | |
255 | self.inner.get_ref().get_ref() | |
256 | } | |
257 | ||
258 | /// Acquires a mutable reference to the underlying stream. | |
259 | /// | |
260 | /// Note that mutation of the stream may result in surprising results if | |
261 | /// this encoder is continued to be used. | |
262 | pub fn get_mut(&mut self) -> &mut R { | |
263 | self.inner.get_mut().get_mut() | |
264 | } | |
265 | ||
266 | /// Consumes this decoder, returning the underlying reader. | |
267 | pub fn into_inner(self) -> R { | |
268 | self.inner.into_inner().into_inner() | |
269 | } | |
270 | } | |
271 | ||
272 | impl<R: Read> Read for MultiGzDecoder<R> { | |
273 | fn read(&mut self, into: &mut [u8]) -> io::Result<usize> { | |
274 | self.inner.read(into) | |
275 | } | |
276 | } | |
277 | ||
278 | impl<R: Read + Write> Write for MultiGzDecoder<R> { | |
279 | fn write(&mut self, buf: &[u8]) -> io::Result<usize> { | |
280 | self.get_mut().write(buf) | |
281 | } | |
282 | ||
283 | fn flush(&mut self) -> io::Result<()> { | |
284 | self.get_mut().flush() | |
285 | } | |
286 | } |