1use std::io;
2use std::io::prelude::*;
3use std::mem;
4
5use crate::zio;
6use crate::{Compress, Decompress};
7
8/// A ZLIB encoder, or compressor.
9///
10/// This structure implements a [`Read`] interface. When read from, it reads
11/// uncompressed data from the underlying [`BufRead`] and provides the compressed data.
12///
13/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
14/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
15///
16/// # Examples
17///
18/// ```
19/// use std::io::prelude::*;
20/// use flate2::Compression;
21/// use flate2::bufread::ZlibEncoder;
22/// use std::fs::File;
23/// use std::io::BufReader;
24///
25/// // Use a buffered file to compress contents into a Vec<u8>
26///
27/// # fn open_hello_world() -> std::io::Result<Vec<u8>> {
28/// let f = File::open("examples/hello_world.txt")?;
29/// let b = BufReader::new(f);
30/// let mut z = ZlibEncoder::new(b, Compression::fast());
31/// let mut buffer = Vec::new();
32/// z.read_to_end(&mut buffer)?;
33/// # Ok(buffer)
34/// # }
35/// ```
36#[derive(Debug)]
37pub struct ZlibEncoder<R> {
38 obj: R,
39 data: Compress,
40}
41
42impl<R: BufRead> ZlibEncoder<R> {
43 /// Creates a new encoder which will read uncompressed data from the given
44 /// stream and emit the compressed stream.
45 pub fn new(r: R, level: crate::Compression) -> ZlibEncoder<R> {
46 ZlibEncoder {
47 obj: r,
48 data: Compress::new(level, zlib_header:true),
49 }
50 }
51
52 /// Creates a new encoder with the given `compression` settings which will
53 /// read uncompressed data from the given stream `r` and emit the compressed stream.
54 pub fn new_with_compress(r: R, compression: Compress) -> ZlibEncoder<R> {
55 ZlibEncoder {
56 obj: r,
57 data: compression,
58 }
59 }
60}
61
62pub fn reset_encoder_data<R>(zlib: &mut ZlibEncoder<R>) {
63 zlib.data.reset()
64}
65
66impl<R> ZlibEncoder<R> {
67 /// Resets the state of this encoder entirely, swapping out the input
68 /// stream for another.
69 ///
70 /// This function will reset the internal state of this encoder and replace
71 /// the input stream with the one provided, returning the previous input
72 /// stream. Future data read from this encoder will be the compressed
73 /// version of `r`'s data.
74 pub fn reset(&mut self, r: R) -> R {
75 reset_encoder_data(self);
76 mem::replace(&mut self.obj, r)
77 }
78
79 /// Acquires a reference to the underlying reader
80 pub fn get_ref(&self) -> &R {
81 &self.obj
82 }
83
84 /// Acquires a mutable reference to the underlying stream
85 ///
86 /// Note that mutation of the stream may result in surprising results if
87 /// this encoder is continued to be used.
88 pub fn get_mut(&mut self) -> &mut R {
89 &mut self.obj
90 }
91
92 /// Consumes this encoder, returning the underlying reader.
93 pub fn into_inner(self) -> R {
94 self.obj
95 }
96
97 /// Returns the number of bytes that have been read into this compressor.
98 ///
99 /// Note that not all bytes read from the underlying object may be accounted
100 /// for, there may still be some active buffering.
101 pub fn total_in(&self) -> u64 {
102 self.data.total_in()
103 }
104
105 /// Returns the number of bytes that the compressor has produced.
106 ///
107 /// Note that not all bytes may have been read yet, some may still be
108 /// buffered.
109 pub fn total_out(&self) -> u64 {
110 self.data.total_out()
111 }
112}
113
114impl<R: BufRead> Read for ZlibEncoder<R> {
115 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
116 zio::read(&mut self.obj, &mut self.data, dst:buf)
117 }
118}
119
120impl<R: BufRead + Write> Write for ZlibEncoder<R> {
121 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
122 self.get_mut().write(buf)
123 }
124
125 fn flush(&mut self) -> io::Result<()> {
126 self.get_mut().flush()
127 }
128}
129
130/// A ZLIB decoder, or decompressor.
131///
132/// This structure implements a [`Read`] interface. When read from, it reads
133/// compressed data from the underlying [`BufRead`] and provides the uncompressed data.
134///
135/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
136/// [`BufRead`]: https://doc.rust-lang.org/std/io/trait.BufRead.html
137///
138/// # Examples
139///
140/// ```
141/// use std::io::prelude::*;
142/// use std::io;
143/// # use flate2::Compression;
144/// # use flate2::write::ZlibEncoder;
145/// use flate2::bufread::ZlibDecoder;
146///
147/// # fn main() {
148/// # let mut e = ZlibEncoder::new(Vec::new(), Compression::default());
149/// # e.write_all(b"Hello World").unwrap();
150/// # let bytes = e.finish().unwrap();
151/// # println!("{}", decode_bufreader(bytes).unwrap());
152/// # }
153/// #
154/// // Uncompresses a Zlib Encoded vector of bytes and returns a string or error
155/// // Here &[u8] implements BufRead
156///
157/// fn decode_bufreader(bytes: Vec<u8>) -> io::Result<String> {
158/// let mut z = ZlibDecoder::new(&bytes[..]);
159/// let mut s = String::new();
160/// z.read_to_string(&mut s)?;
161/// Ok(s)
162/// }
163/// ```
164#[derive(Debug)]
165pub struct ZlibDecoder<R> {
166 obj: R,
167 data: Decompress,
168}
169
170impl<R: BufRead> ZlibDecoder<R> {
171 /// Creates a new decoder which will decompress data read from the given
172 /// stream.
173 pub fn new(r: R) -> ZlibDecoder<R> {
174 ZlibDecoder {
175 obj: r,
176 data: Decompress::new(zlib_header:true),
177 }
178 }
179
180 /// Creates a new decoder which will decompress data read from the given
181 /// stream, using the given `decompression` settings.
182 pub fn new_with_decompress(r: R, decompression: Decompress) -> ZlibDecoder<R> {
183 ZlibDecoder {
184 obj: r,
185 data: decompression,
186 }
187 }
188}
189
190pub fn reset_decoder_data<R>(zlib: &mut ZlibDecoder<R>) {
191 zlib.data = Decompress::new(zlib_header:true);
192}
193
194impl<R> ZlibDecoder<R> {
195 /// Resets the state of this decoder entirely, swapping out the input
196 /// stream for another.
197 ///
198 /// This will reset the internal state of this decoder and replace the
199 /// input stream with the one provided, returning the previous input
200 /// stream. Future data read from this decoder will be the decompressed
201 /// version of `r`'s data.
202 pub fn reset(&mut self, r: R) -> R {
203 reset_decoder_data(self);
204 mem::replace(&mut self.obj, r)
205 }
206
207 /// Acquires a reference to the underlying stream
208 pub fn get_ref(&self) -> &R {
209 &self.obj
210 }
211
212 /// Acquires a mutable reference to the underlying stream
213 ///
214 /// Note that mutation of the stream may result in surprising results if
215 /// this decoder is continued to be used.
216 pub fn get_mut(&mut self) -> &mut R {
217 &mut self.obj
218 }
219
220 /// Consumes this decoder, returning the underlying reader.
221 pub fn into_inner(self) -> R {
222 self.obj
223 }
224
225 /// Returns the number of bytes that the decompressor has consumed.
226 ///
227 /// Note that this will likely be smaller than what the decompressor
228 /// actually read from the underlying stream due to buffering.
229 pub fn total_in(&self) -> u64 {
230 self.data.total_in()
231 }
232
233 /// Returns the number of bytes that the decompressor has produced.
234 pub fn total_out(&self) -> u64 {
235 self.data.total_out()
236 }
237}
238
239impl<R: BufRead> Read for ZlibDecoder<R> {
240 fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
241 zio::read(&mut self.obj, &mut self.data, dst:into)
242 }
243}
244
245impl<R: BufRead + Write> Write for ZlibDecoder<R> {
246 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
247 self.get_mut().write(buf)
248 }
249
250 fn flush(&mut self) -> io::Result<()> {
251 self.get_mut().flush()
252 }
253}
254