1 //! Reader-based compression/decompression streams
2 
3 use std::io::prelude::*;
4 use std::io::{self, BufReader};
5 
6 use bufread;
7 
8 use super::CompressParams;
9 
10 /// A compression stream which wraps an uncompressed stream of data. Compressed
11 /// data will be read from the stream.
12 pub struct BrotliEncoder<R: Read> {
13     inner: bufread::BrotliEncoder<BufReader<R>>,
14 }
15 
16 /// A decompression stream which wraps a compressed stream of data. Decompressed
17 /// data will be read from the stream.
18 pub struct BrotliDecoder<R: Read> {
19     inner: bufread::BrotliDecoder<BufReader<R>>,
20 }
21 
22 impl<R: Read> BrotliEncoder<R> {
23     /// Create a new compression stream which will compress at the given level
24     /// to read compress output to the give output stream.
25     ///
26     /// The `level` argument here is typically 0-9 with 6 being a good default.
new(r: R, level: u32) -> BrotliEncoder<R>27     pub fn new(r: R, level: u32) -> BrotliEncoder<R> {
28         BrotliEncoder {
29             inner: bufread::BrotliEncoder::new(BufReader::new(r), level),
30         }
31     }
32 
33     /// Configure the compression parameters of this encoder.
from_params( r: R, params: &CompressParams) -> BrotliEncoder<R>34     pub fn from_params( r: R, params: &CompressParams) -> BrotliEncoder<R> {
35         BrotliEncoder{
36             inner: bufread::BrotliEncoder::from_params(
37                 BufReader::with_capacity(params.get_lgwin_readable(),r), params)
38         }
39     }
40 
41     /// Acquires a reference to the underlying stream
get_ref(&self) -> &R42     pub fn get_ref(&self) -> &R {
43         self.inner.get_ref().get_ref()
44     }
45 
46     /// Acquires a mutable reference to the underlying stream
47     ///
48     /// Note that mutation of the stream may result in surprising results if
49     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut R50     pub fn get_mut(&mut self) -> &mut R {
51         self.inner.get_mut().get_mut()
52     }
53 
54     /// Unwrap the underlying writer, finishing the compression stream.
into_inner(self) -> R55     pub fn into_inner(self) -> R {
56         self.inner.into_inner().into_inner()
57     }
58 }
59 
60 impl<R: Read> Read for BrotliEncoder<R> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>61     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
62         self.inner.read(buf)
63     }
64 }
65 
66 impl<R: Read> BrotliDecoder<R> {
67     /// Create a new decompression stream, which will read compressed
68     /// data from the given input stream and decompress it.
new(r: R) -> BrotliDecoder<R>69     pub fn new(r: R) -> BrotliDecoder<R> {
70         BrotliDecoder {
71             inner: bufread::BrotliDecoder::new(BufReader::new(r)),
72         }
73     }
74 
75     /// Acquires a reference to the underlying stream
get_ref(&self) -> &R76     pub fn get_ref(&self) -> &R {
77         self.inner.get_ref().get_ref()
78     }
79 
80     /// Acquires a mutable reference to the underlying stream
81     ///
82     /// Note that mutation of the stream may result in surprising results if
83     /// this encoder is continued to be used.
get_mut(&mut self) -> &mut R84     pub fn get_mut(&mut self) -> &mut R {
85         self.inner.get_mut().get_mut()
86     }
87 
88     /// Unwrap the underlying writer, finishing the compression stream.
into_inner(self) -> R89     pub fn into_inner(self) -> R {
90         self.inner.into_inner().into_inner()
91     }
92 }
93 
94 impl<R: Read> Read for BrotliDecoder<R> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>95     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
96         self.inner.read(buf)
97     }
98 }
99 
100 #[cfg(test)]
101 mod tests {
102     use std::io::prelude::*;
103     use read::{BrotliEncoder, BrotliDecoder};
104     use rand::{thread_rng, Rng};
105 
106 
107     #[test]
smoke()108     fn smoke() {
109         let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
110         let mut c = BrotliEncoder::new(m, 6);
111         let mut data = vec![];
112         c.read_to_end(&mut data).unwrap();
113         let mut d = BrotliDecoder::new(&data[..]);
114         let mut data2 = Vec::new();
115         d.read_to_end(&mut data2).unwrap();
116         assert_eq!(data2, m);
117     }
118 
119     #[test]
smoke2()120     fn smoke2() {
121         let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
122         let c = BrotliEncoder::new(m, 6);
123         let mut d = BrotliDecoder::new(c);
124         let mut data = vec![];
125         d.read_to_end(&mut data).unwrap();
126         assert_eq!(data, [1, 2, 3, 4, 5, 6, 7, 8]);
127     }
128 
129     #[test]
smoke3()130     fn smoke3() {
131         let m = vec![3u8; 128 * 1024 + 1];
132         let c = BrotliEncoder::new(&m[..], 6);
133         let mut d = BrotliDecoder::new(c);
134         let mut data = vec![];
135         d.read_to_end(&mut data).unwrap();
136         assert!(data == &m[..]);
137     }
138 
139     #[test]
self_terminating()140     fn self_terminating() {
141         let m = vec![3u8; 128 * 1024 + 1];
142         let mut c = BrotliEncoder::new(&m[..], 6);
143 
144         let mut result = Vec::new();
145         c.read_to_end(&mut result).unwrap();
146 
147         let v = thread_rng().gen_iter::<u8>().take(1024).collect::<Vec<_>>();
148         for _ in 0..200 {
149             result.extend(v.iter().map(|x| *x));
150         }
151 
152         let mut d = BrotliDecoder::new(&result[..]);
153         let mut data = Vec::with_capacity(m.len());
154         unsafe { data.set_len(m.len()); }
155         assert!(d.read(&mut data).unwrap() == m.len());
156         assert!(data == &m[..]);
157     }
158 
159     #[test]
zero_length_read_at_eof()160     fn zero_length_read_at_eof() {
161         let m = Vec::new();
162         let mut c = BrotliEncoder::new(&m[..], 6);
163 
164         let mut result = Vec::new();
165         c.read_to_end(&mut result).unwrap();
166 
167         let mut d = BrotliDecoder::new(&result[..]);
168         let mut data = Vec::new();
169         assert!(d.read(&mut data).unwrap() == 0);
170     }
171 
172     #[test]
zero_length_read_with_data()173     fn zero_length_read_with_data() {
174         let m = vec![3u8; 128 * 1024 + 1];
175         let mut c = BrotliEncoder::new(&m[..], 6);
176 
177         let mut result = Vec::new();
178         c.read_to_end(&mut result).unwrap();
179 
180         let mut d = BrotliDecoder::new(&result[..]);
181         let mut data = Vec::new();
182         assert!(d.read(&mut data).unwrap() == 0);
183     }
184 
185     #[test]
qc()186     fn qc() {
187         ::quickcheck::quickcheck(test as fn(_) -> _);
188 
189         fn test(v: Vec<u8>) -> bool {
190             let r = BrotliEncoder::new(&v[..], 6);
191             let mut r = BrotliDecoder::new(r);
192             let mut v2 = Vec::new();
193             r.read_to_end(&mut v2).unwrap();
194             v == v2
195         }
196     }
197 }
198