1use std::io::prelude::*;
4use std::io::{self, BufReader};
5
6use crate::bufread;
7use crate::stream::Stream;
8
9pub struct XzEncoder<R: Read> {
12 inner: bufread::XzEncoder<BufReader<R>>,
13}
14
15pub struct XzDecoder<R: Read> {
18 inner: bufread::XzDecoder<BufReader<R>>,
19}
20
21impl<R: Read> XzEncoder<R> {
22 #[inline]
29 pub fn new(r: R, level: u32) -> XzEncoder<R> {
30 XzEncoder {
31 inner: bufread::XzEncoder::new(BufReader::new(r), level),
32 }
33 }
34
35 #[cfg(feature = "parallel")]
42 pub fn new_parallel(r: R, level: u32) -> XzEncoder<R> {
43 XzEncoder {
44 inner: bufread::XzEncoder::new_parallel(BufReader::new(r), level),
45 }
46 }
47
48 #[inline]
53 pub fn new_stream(r: R, stream: Stream) -> XzEncoder<R> {
54 XzEncoder {
55 inner: bufread::XzEncoder::new_stream(BufReader::new(r), stream),
56 }
57 }
58
59 #[inline]
61 pub fn get_ref(&self) -> &R {
62 self.inner.get_ref().get_ref()
63 }
64
65 #[inline]
70 pub fn get_mut(&mut self) -> &mut R {
71 self.inner.get_mut().get_mut()
72 }
73
74 #[inline]
76 pub fn into_inner(self) -> R {
77 self.inner.into_inner().into_inner()
78 }
79
80 #[inline]
90 pub fn total_out(&self) -> u64 {
91 self.inner.total_out()
92 }
93
94 #[inline]
97 pub fn total_in(&self) -> u64 {
98 self.inner.total_in()
99 }
100}
101
102impl<R: Read> Read for XzEncoder<R> {
103 #[inline]
104 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
105 self.inner.read(buf)
106 }
107}
108
109impl<W: Write + Read> Write for XzEncoder<W> {
110 #[inline]
111 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
112 self.get_mut().write(buf)
113 }
114
115 #[inline]
116 fn flush(&mut self) -> io::Result<()> {
117 self.get_mut().flush()
118 }
119}
120
121impl<R: Read> XzDecoder<R> {
122 #[inline]
128 pub fn new(r: R) -> XzDecoder<R> {
129 XzDecoder {
130 inner: bufread::XzDecoder::new(BufReader::new(r)),
131 }
132 }
133
134 #[cfg(feature = "parallel")]
139 #[inline]
140 pub fn new_parallel(r: R) -> XzDecoder<R> {
141 XzDecoder {
142 inner: bufread::XzDecoder::new_parallel(BufReader::new(r)),
143 }
144 }
145
146 #[inline]
149 pub fn new_multi_decoder(r: R) -> XzDecoder<R> {
150 XzDecoder {
151 inner: bufread::XzDecoder::new_multi_decoder(BufReader::new(r)),
152 }
153 }
154
155 #[inline]
160 pub fn new_stream(r: R, stream: Stream) -> XzDecoder<R> {
161 XzDecoder {
162 inner: bufread::XzDecoder::new_stream(BufReader::new(r), stream),
163 }
164 }
165
166 #[inline]
168 pub fn get_ref(&self) -> &R {
169 self.inner.get_ref().get_ref()
170 }
171
172 #[inline]
177 pub fn get_mut(&mut self) -> &mut R {
178 self.inner.get_mut().get_mut()
179 }
180
181 #[inline]
183 pub fn into_inner(self) -> R {
184 self.inner.into_inner().into_inner()
185 }
186
187 #[inline]
195 pub fn total_out(&self) -> u64 {
196 self.inner.total_out()
197 }
198
199 #[inline]
202 pub fn total_in(&self) -> u64 {
203 self.inner.total_in()
204 }
205}
206
207impl<R: Read> Read for XzDecoder<R> {
208 #[inline]
209 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
210 self.inner.read(buf)
211 }
212}
213
214impl<W: Write + Read> Write for XzDecoder<W> {
215 #[inline]
216 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
217 self.get_mut().write(buf)
218 }
219
220 #[inline]
221 fn flush(&mut self) -> io::Result<()> {
222 self.get_mut().flush()
223 }
224}
225
226#[cfg(test)]
227mod tests {
228 use super::*;
229 use crate::stream::{LzmaOptions, PRESET_EXTREME};
230 use quickcheck::quickcheck;
231 use rand::{thread_rng, Rng};
232 use std::iter;
233 #[cfg(all(target_family = "wasm", target_os = "unknown"))]
234 use wasm_bindgen_test::wasm_bindgen_test as test;
235
236 #[test]
237 fn smoke() {
238 let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
239 let mut c = XzEncoder::new(m, 6);
240 let mut data = vec![];
241 c.read_to_end(&mut data).unwrap();
242 let mut d = XzDecoder::new(&data[..]);
243 let mut data2 = Vec::new();
244 d.read_to_end(&mut data2).unwrap();
245 assert_eq!(data2, m);
246 }
247
248 #[test]
249 fn smoke2() {
250 let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
251 let c = XzEncoder::new(m, 6);
252 let mut d = XzDecoder::new(c);
253 let mut data = vec![];
254 d.read_to_end(&mut data).unwrap();
255 assert_eq!(data, [1, 2, 3, 4, 5, 6, 7, 8]);
256 }
257
258 #[test]
259 fn smoke3() {
260 let m = vec![3u8; 128 * 1024 + 1];
261 let c = XzEncoder::new(&m[..], 6);
262 let mut d = XzDecoder::new(c);
263 let mut data = vec![];
264 d.read_to_end(&mut data).unwrap();
265 assert_eq!(data, &m[..]);
266 }
267
268 #[test]
269 fn self_terminating() {
270 let m = vec![3u8; 128 * 1024 + 1];
271 let mut c = XzEncoder::new(&m[..], 6);
272
273 let mut result = Vec::new();
274 c.read_to_end(&mut result).unwrap();
275
276 let mut rng = thread_rng();
277 let v = iter::repeat_with(|| rng.gen::<u8>())
278 .take(1024)
279 .collect::<Vec<_>>();
280 for _ in 0..200 {
281 result.extend(v.iter().map(|x| *x));
282 }
283
284 let mut d = XzDecoder::new(&result[..]);
285 let mut data = vec![0u8; m.len()];
286 assert_eq!(d.read(&mut data).unwrap(), m.len());
287 assert_eq!(data, &m[..]);
288 }
289
290 #[test]
291 fn zero_length_read_at_eof() {
292 let m = Vec::new();
293 let mut c = XzEncoder::new(&m[..], 6);
294
295 let mut result = Vec::new();
296 c.read_to_end(&mut result).unwrap();
297
298 let mut d = XzDecoder::new(&result[..]);
299 let mut data = Vec::new();
300 assert_eq!(d.read(&mut data).unwrap(), 0);
301 }
302
303 #[test]
304 fn zero_length_read_with_data() {
305 let m = vec![3u8; 128 * 1024 + 1];
306 let mut c = XzEncoder::new(&m[..], 6);
307
308 let mut result = Vec::new();
309 c.read_to_end(&mut result).unwrap();
310
311 let mut d = XzDecoder::new(&result[..]);
312 let mut data = Vec::new();
313 assert_eq!(d.read(&mut data).unwrap(), 0);
314 }
315
316 #[test]
317 fn extreme_preset_round_trip() {
318 let m = vec![7u8; 128 * 1024 + 1];
319 let c = XzEncoder::new(&m[..], 6 | PRESET_EXTREME);
320 let mut d = XzDecoder::new(c);
321 let mut data = Vec::new();
322 d.read_to_end(&mut data).unwrap();
323 assert_eq!(data, m);
324 }
325
326 #[test]
327 fn qc_lzma1() {
328 quickcheck(test as fn(_) -> _);
329 fn test(v: Vec<u8>) -> bool {
330 let options = LzmaOptions::new_preset(6).unwrap();
331 let stream = Stream::new_lzma_encoder(&options).unwrap();
332 let r = XzEncoder::new_stream(&v[..], stream);
333 let stream = Stream::new_lzma_decoder(u64::MAX).unwrap();
334 let mut r = XzDecoder::new_stream(r, stream);
335 let mut v2 = Vec::new();
336 r.read_to_end(&mut v2).unwrap();
337 v == v2
338 }
339 }
340
341 #[test]
342 fn qc() {
343 quickcheck(test as fn(_) -> _);
344
345 fn test(v: Vec<u8>) -> bool {
346 let r = XzEncoder::new(&v[..], 6);
347 let mut r = XzDecoder::new(r);
348 let mut v2 = Vec::new();
349 r.read_to_end(&mut v2).unwrap();
350 v == v2
351 }
352 }
353
354 #[cfg(feature = "parallel")]
355 #[test]
356 fn qc_parallel_encode() {
357 quickcheck(test as fn(_) -> _);
358
359 fn test(v: Vec<u8>) -> bool {
360 let r = XzEncoder::new_parallel(&v[..], 6);
361 let mut r = XzDecoder::new(r);
362 let mut v2 = Vec::new();
363 r.read_to_end(&mut v2).unwrap();
364 v == v2
365 }
366 }
367
368 #[cfg(feature = "parallel")]
369 #[test]
370 fn extreme_preset_round_trip_parallel() {
371 let m = vec![9u8; 128 * 1024 + 1];
372 let c = XzEncoder::new_parallel(&m[..], 6 | PRESET_EXTREME);
373 let mut d = XzDecoder::new(c);
374 let mut data = Vec::new();
375 d.read_to_end(&mut data).unwrap();
376 assert_eq!(data, m);
377 }
378
379 #[cfg(feature = "parallel")]
380 #[test]
381 fn qc_parallel_decode() {
382 quickcheck(test as fn(_) -> _);
383
384 fn test(v: Vec<u8>) -> bool {
385 let r = XzEncoder::new(&v[..], 6);
386 let mut r = XzDecoder::new_parallel(r);
387 let mut v2 = Vec::new();
388 r.read_to_end(&mut v2).unwrap();
389 v == v2
390 }
391 }
392
393 #[test]
394 fn two_streams() {
395 let mut input_stream1: Vec<u8> = Vec::new();
396 let mut input_stream2: Vec<u8> = Vec::new();
397 let mut all_input: Vec<u8> = Vec::new();
398
399 const STREAM1_SIZE: usize = 1024;
401 for num in 0..STREAM1_SIZE {
402 input_stream1.push(num as u8)
403 }
404 const STREAM2_SIZE: usize = 532;
405 for num in 0..STREAM2_SIZE {
406 input_stream2.push((num + 32) as u8)
407 }
408 all_input.extend(&input_stream1);
409 all_input.extend(&input_stream2);
410
411 let mut decoder_input = Vec::new();
413 {
414 let mut encoder = XzEncoder::new(&input_stream1[..], 6);
415 encoder.read_to_end(&mut decoder_input).unwrap();
416 }
417 {
418 let mut encoder = XzEncoder::new(&input_stream2[..], 6);
419 encoder.read_to_end(&mut decoder_input).unwrap();
420 }
421
422 let mut decoder_reader = &decoder_input[..];
424 {
425 let mut decoder = XzDecoder::new_multi_decoder(&mut decoder_reader);
427 let mut decompressed_data = vec![0u8; all_input.len()];
428
429 assert_eq!(
430 decoder.read(&mut decompressed_data).unwrap(),
431 all_input.len()
432 );
433 assert_eq!(decompressed_data, &all_input[..]);
434 }
435 }
436}