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