inflate/reader.rs
1use std::io::{self, BufRead, Read, BufReader, Error, ErrorKind, Write};
2use std::{cmp,mem};
3
4use super::InflateStream;
5
6/// Workaround for lack of copy_from_slice on pre-1.9 rust.
7#[inline]
8fn copy_from_slice(mut to: &mut [u8], from: &[u8]) {
9 assert_eq!(to.len(), from.len());
10 to.write_all(from).unwrap();
11}
12
13/// A DEFLATE decoder/decompressor.
14///
15/// This structure implements a `Read` interface and takes a stream
16/// of compressed data that implements the `BufRead` trait as input,
17/// providing the decompressed data when read from.
18///
19/// # Example
20/// ```
21/// use std::io::Read;
22/// use inflate::DeflateDecoderBuf;
23///
24/// const TEST_STRING: &'static str = "Hello, world";
25/// let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0];
26/// let mut decoder = DeflateDecoderBuf::new(&encoded[..]);
27/// let mut output = Vec::new();
28/// let status = decoder.read_to_end(&mut output);
29/// # let _ = status;
30/// assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING);
31/// ```
32pub struct DeflateDecoderBuf<R> {
33 /// The inner reader instance
34 reader: R,
35 /// The raw decompressor
36 decompressor: InflateStream,
37 /// How many bytes of the decompressor's output buffer still need to be output.
38 pending_output_bytes: usize,
39 /// Total number of bytes read from the underlying reader.
40 total_in: u64,
41 /// Total number of bytes written in `read` calls.
42 total_out: u64,
43}
44
45impl<R: BufRead> DeflateDecoderBuf<R> {
46 /// Create a new `Deflatedecoderbuf` to read from a raw deflate stream.
47 pub fn new(reader: R) -> DeflateDecoderBuf<R> {
48 DeflateDecoderBuf {
49 reader: reader,
50 decompressor: InflateStream::new(),
51 pending_output_bytes: 0,
52 total_in: 0,
53 total_out: 0,
54 }
55 }
56
57 /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream.
58 pub fn from_zlib(reader: R) -> DeflateDecoderBuf<R> {
59 DeflateDecoderBuf {
60 reader: reader,
61 decompressor: InflateStream::from_zlib(),
62 pending_output_bytes: 0,
63 total_in: 0,
64 total_out: 0,
65 }
66 }
67
68 /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream.
69 /// without calculating and validating the checksum.
70 pub fn from_zlib_no_checksum(reader: R) -> DeflateDecoderBuf<R> {
71 DeflateDecoderBuf {
72 reader: reader,
73 decompressor: InflateStream::from_zlib_no_checksum(),
74 pending_output_bytes: 0,
75 total_in: 0,
76 total_out: 0,
77 }
78 }
79}
80
81impl<R> DeflateDecoderBuf<R> {
82 /// Resets the decompressor, and replaces the current inner `BufRead` instance by `r`.
83 /// without doing any extra reallocations.
84 ///
85 /// Note that this function doesn't ensure that all data has been output.
86 #[inline]
87 pub fn reset(&mut self, r: R) -> R {
88 self.decompressor.reset();
89 mem::replace(&mut self.reader, r)
90 }
91
92 /// Resets the decoder, but continue to read from the same reader.
93 ///
94 /// Note that this function doesn't ensure that all data has been output.
95 #[inline]
96 pub fn reset_data(&mut self) {
97 self.decompressor.reset()
98 }
99
100 /// Returns a reference to the underlying `BufRead` instance.
101 #[inline]
102 pub fn get_ref(&self) -> &R {
103 &self.reader
104 }
105
106 /// Returns a mutable reference to the underlying `BufRead` instance.
107 ///
108 /// Note that mutation of the reader may cause surprising results if the decoder is going to
109 /// keep being used.
110 #[inline]
111 pub fn get_mut(&mut self) -> &mut R {
112 &mut self.reader
113 }
114
115 /// Drops the decoder and return the inner `BufRead` instance.
116 ///
117 /// Note that this function doesn't ensure that all data has been output.
118 #[inline]
119 pub fn into_inner(self) -> R {
120 self.reader
121 }
122
123 /// Returns the total bytes read from the underlying `BufRead` instance.
124 #[inline]
125 pub fn total_in(&self) -> u64 {
126 self.total_in
127 }
128
129 /// Returns the total number of bytes output from this decoder.
130 #[inline]
131 pub fn total_out(&self) -> u64 {
132 self.total_out
133 }
134
135 /// Returns the calculated checksum value of the currently decoded data.
136 ///
137 /// Will return 0 for cases where the checksum is not validated.
138 #[inline]
139 pub fn current_checksum(&self) -> u32 {
140 self.decompressor.current_checksum()
141 }
142}
143
144impl<R: BufRead> Read for DeflateDecoderBuf<R> {
145 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
146 let mut bytes_out = 0;
147 // If there is still data left to ouput from the last call to `update()`, that needs to be
148 // output first
149 if self.pending_output_bytes != 0 {
150 // Get the part of the buffer that has not been output yet.
151 // The decompressor sets `pos` to 0 when it reaches the end of it's internal buffer,
152 // so we have to check for that.
153 let start = if self.decompressor.pos != 0 {
154 self.decompressor.pos as usize - self.pending_output_bytes
155 } else {
156 self.decompressor.buffer.len() - self.pending_output_bytes
157 };
158
159 // Copy as much decompressed as possible to buf.
160 let bytes_to_copy = cmp::min(buf.len(), self.pending_output_bytes);
161 let pending_data =
162 &self.decompressor.buffer[start..
163 start + bytes_to_copy];
164 copy_from_slice(&mut buf[..bytes_to_copy],pending_data);
165 bytes_out += bytes_to_copy;
166 // This won't underflow since `bytes_to_copy` will be at most
167 // the same value as `pending_output_bytes`.
168 self.pending_output_bytes -= bytes_to_copy;
169 if self.pending_output_bytes != 0 {
170 self.total_out += bytes_out as u64;
171 // If there is still decompressed data left that didn't
172 // fit in `buf`, return what we read.
173 return Ok(bytes_out);
174 }
175 }
176
177 // There is space in `buf` for more data, so try to read more.
178 let (input_bytes_read, remaining_bytes) = {
179 self.pending_output_bytes = 0;
180 let input = try!(self.reader.fill_buf());
181 if input.len() == 0 {
182 self.total_out += bytes_out as u64;
183 //If there is nothing more to read, return.
184 return Ok(bytes_out);
185 }
186 let (input_bytes_read, data) =
187 match self.decompressor.update(&input) {
188 Ok(res) => res,
189 Err(m) => return Err(Error::new(ErrorKind::Other, m))
190 };
191
192 // Space left in `buf`
193 let space_left = buf.len() - bytes_out;
194 let bytes_to_copy = cmp::min(space_left, data.len());
195
196 copy_from_slice(&mut buf[bytes_out..bytes_out + bytes_to_copy], &data[..bytes_to_copy]);
197
198 bytes_out += bytes_to_copy;
199
200 // Can't underflow as bytes_to_copy is bounded by data.len().
201 (input_bytes_read, data.len() - bytes_to_copy)
202
203 };
204
205 self.pending_output_bytes += remaining_bytes;
206 self.total_in += input_bytes_read as u64;
207 self.total_out += bytes_out as u64;
208 self.reader.consume(input_bytes_read);
209
210 Ok(bytes_out)
211 }
212}
213
214
215
216/// A DEFLATE decoder/decompressor.
217///
218/// This structure implements a `Read` interface and takes a stream of compressed data that
219/// implements the `Read` trait as input,
220/// provoding the decompressed data when read from.
221/// # Example
222/// ```
223/// use std::io::Read;
224/// use inflate::DeflateDecoder;
225/// const TEST_STRING: &'static str = "Hello, world";
226/// let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0];
227/// let mut decoder = DeflateDecoder::new(&encoded[..]);
228/// let mut output = Vec::new();
229/// let status = decoder.read_to_end(&mut output);
230/// # let _ = status;
231/// assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING);
232/// ```
233pub struct DeflateDecoder<R> {
234 /// Inner DeflateDecoderBuf, with R wrapped in a `BufReader`.
235 inner: DeflateDecoderBuf<BufReader<R>>
236}
237
238impl<R: Read> DeflateDecoder<R> {
239 /// Create a new `Deflatedecoderbuf` to read from a raw deflate stream.
240 pub fn new(reader: R) -> DeflateDecoder<R> {
241 DeflateDecoder {
242 inner: DeflateDecoderBuf::new(BufReader::new(reader))
243 }
244 }
245
246 /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream.
247 pub fn from_zlib(reader: R) -> DeflateDecoder<R> {
248 DeflateDecoder {
249 inner: DeflateDecoderBuf::from_zlib(BufReader::new(reader))
250 }
251 }
252
253 /// Create a new `DeflateDecoderbuf` that reads from a zlib wrapped deflate stream.
254 /// without calculating and validating the checksum.
255 pub fn from_zlib_no_checksum(reader: R) -> DeflateDecoder<R> {
256 DeflateDecoder {
257 inner: DeflateDecoderBuf::from_zlib_no_checksum(BufReader::new(reader))
258 }
259 }
260
261 /// Resets the decompressor, and replaces the current inner `BufRead` instance by `r`.
262 /// without doing any extra reallocations.
263 ///
264 /// Note that this function doesn't ensure that all data has been output.
265 #[inline]
266 pub fn reset(&mut self, r: R) -> R {
267 self.inner.reset(BufReader::new(r)).into_inner()
268 }
269
270 /// Returns a reference to the underlying reader.
271 #[inline]
272 pub fn get_ref(&self) -> &R {
273 self.inner.get_ref().get_ref()
274 }
275
276 /// Returns a mutable reference to the underlying reader.
277 ///
278 /// Note that mutation of the reader may cause surprising results if the decoder is going to
279 /// keep being used.
280 #[inline]
281 pub fn get_mut(&mut self) -> &mut R {
282 self.inner.get_mut().get_mut()
283 }
284
285 /// Returns the total number of bytes output from this decoder.
286 #[inline]
287 pub fn into_inner(self) -> R {
288 self.inner.into_inner().into_inner()
289 }
290}
291
292impl<R> DeflateDecoder<R> {
293 /// Resets the decoder, but continue to read from the same reader.
294 ///
295 /// Note that this function doesn't ensure that all data has been output.
296 #[inline]
297 pub fn reset_data(&mut self) {
298 self.inner.reset_data()
299 }
300
301 /// Returns the total bytes read from the underlying reader.
302 #[inline]
303 pub fn total_in(&self) -> u64 {
304 self.inner.total_in
305 }
306
307 /// Returns the total number of bytes output from this decoder.
308 #[inline]
309 pub fn total_out(&self) -> u64 {
310 self.inner.total_out
311 }
312
313 /// Returns the calculated checksum value of the currently decoded data.
314 ///
315 /// Will return 0 for cases where the checksum is not validated.
316 #[inline]
317 pub fn current_checksum(&self) -> u32 {
318 self.inner.current_checksum()
319 }
320}
321
322impl<R: Read> Read for DeflateDecoder<R> {
323 #[inline]
324 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
325 self.inner.read(buf)
326 }
327}
328
329#[cfg(test)]
330mod test {
331 use super::{DeflateDecoder};
332 use std::io::Read;
333
334 #[test]
335 fn deflate_reader() {
336 const TEST_STRING: &'static str = "Hello, world";
337 let encoded = vec![243, 72, 205, 201, 201, 215, 81, 40, 207, 47, 202, 73, 1, 0];
338 let mut decoder = DeflateDecoder::new(&encoded[..]);
339 let mut output = Vec::new();
340 decoder.read_to_end(&mut output).unwrap();
341 assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING);
342 assert_eq!(decoder.total_in(), encoded.len() as u64);
343 assert_eq!(decoder.total_out(), TEST_STRING.len() as u64);
344 }
345
346 #[test]
347 fn zlib_reader() {
348 const TEST_STRING: &'static str = "Hello, zlib!";
349 let encoded = vec![120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201,
350 76, 82, 4, 0, 27, 101, 4, 19];
351 let mut decoder = DeflateDecoder::from_zlib(&encoded[..]);
352 let mut output = Vec::new();
353 decoder.read_to_end(&mut output).unwrap();
354 assert_eq!(String::from_utf8(output).unwrap(), TEST_STRING);
355 assert_eq!(decoder.total_in(), encoded.len() as u64);
356 assert_eq!(decoder.total_out(), TEST_STRING.len() as u64);
357 }
358}