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::with_capacity(m.len());
286 unsafe {
287 data.set_len(m.len());
288 }
289 assert_eq!(d.read(&mut data).unwrap(), m.len());
290 assert_eq!(data, &m[..]);
291 }
292
293 #[test]
294 fn zero_length_read_at_eof() {
295 let m = Vec::new();
296 let mut c = XzEncoder::new(&m[..], 6);
297
298 let mut result = Vec::new();
299 c.read_to_end(&mut result).unwrap();
300
301 let mut d = XzDecoder::new(&result[..]);
302 let mut data = Vec::new();
303 assert_eq!(d.read(&mut data).unwrap(), 0);
304 }
305
306 #[test]
307 fn zero_length_read_with_data() {
308 let m = vec![3u8; 128 * 1024 + 1];
309 let mut c = XzEncoder::new(&m[..], 6);
310
311 let mut result = Vec::new();
312 c.read_to_end(&mut result).unwrap();
313
314 let mut d = XzDecoder::new(&result[..]);
315 let mut data = Vec::new();
316 assert_eq!(d.read(&mut data).unwrap(), 0);
317 }
318
319 #[test]
320 fn extreme_preset_round_trip() {
321 let m = vec![7u8; 128 * 1024 + 1];
322 let c = XzEncoder::new(&m[..], 6 | PRESET_EXTREME);
323 let mut d = XzDecoder::new(c);
324 let mut data = Vec::new();
325 d.read_to_end(&mut data).unwrap();
326 assert_eq!(data, m);
327 }
328
329 #[test]
330 fn qc_lzma1() {
331 quickcheck(test as fn(_) -> _);
332 fn test(v: Vec<u8>) -> bool {
333 let options = LzmaOptions::new_preset(6).unwrap();
334 let stream = Stream::new_lzma_encoder(&options).unwrap();
335 let r = XzEncoder::new_stream(&v[..], stream);
336 let stream = Stream::new_lzma_decoder(u64::MAX).unwrap();
337 let mut r = XzDecoder::new_stream(r, stream);
338 let mut v2 = Vec::new();
339 r.read_to_end(&mut v2).unwrap();
340 v == v2
341 }
342 }
343
344 #[test]
345 fn qc() {
346 quickcheck(test as fn(_) -> _);
347
348 fn test(v: Vec<u8>) -> bool {
349 let r = XzEncoder::new(&v[..], 6);
350 let mut r = XzDecoder::new(r);
351 let mut v2 = Vec::new();
352 r.read_to_end(&mut v2).unwrap();
353 v == v2
354 }
355 }
356
357 #[cfg(feature = "parallel")]
358 #[test]
359 fn qc_parallel_encode() {
360 quickcheck(test as fn(_) -> _);
361
362 fn test(v: Vec<u8>) -> bool {
363 let r = XzEncoder::new_parallel(&v[..], 6);
364 let mut r = XzDecoder::new(r);
365 let mut v2 = Vec::new();
366 r.read_to_end(&mut v2).unwrap();
367 v == v2
368 }
369 }
370
371 #[cfg(feature = "parallel")]
372 #[test]
373 fn extreme_preset_round_trip_parallel() {
374 let m = vec![9u8; 128 * 1024 + 1];
375 let c = XzEncoder::new_parallel(&m[..], 6 | PRESET_EXTREME);
376 let mut d = XzDecoder::new(c);
377 let mut data = Vec::new();
378 d.read_to_end(&mut data).unwrap();
379 assert_eq!(data, m);
380 }
381
382 #[cfg(feature = "parallel")]
383 #[test]
384 fn qc_parallel_decode() {
385 quickcheck(test as fn(_) -> _);
386
387 fn test(v: Vec<u8>) -> bool {
388 let r = XzEncoder::new(&v[..], 6);
389 let mut r = XzDecoder::new_parallel(r);
390 let mut v2 = Vec::new();
391 r.read_to_end(&mut v2).unwrap();
392 v == v2
393 }
394 }
395
396 #[test]
397 fn two_streams() {
398 let mut input_stream1: Vec<u8> = Vec::new();
399 let mut input_stream2: Vec<u8> = Vec::new();
400 let mut all_input: Vec<u8> = Vec::new();
401
402 const STREAM1_SIZE: usize = 1024;
404 for num in 0..STREAM1_SIZE {
405 input_stream1.push(num as u8)
406 }
407 const STREAM2_SIZE: usize = 532;
408 for num in 0..STREAM2_SIZE {
409 input_stream2.push((num + 32) as u8)
410 }
411 all_input.extend(&input_stream1);
412 all_input.extend(&input_stream2);
413
414 let mut decoder_input = Vec::new();
416 {
417 let mut encoder = XzEncoder::new(&input_stream1[..], 6);
418 encoder.read_to_end(&mut decoder_input).unwrap();
419 }
420 {
421 let mut encoder = XzEncoder::new(&input_stream2[..], 6);
422 encoder.read_to_end(&mut decoder_input).unwrap();
423 }
424
425 let mut decoder_reader = &decoder_input[..];
427 {
428 let mut decoder = XzDecoder::new_multi_decoder(&mut decoder_reader);
430 let mut decompressed_data = vec![0u8; all_input.len()];
431
432 assert_eq!(
433 decoder.read(&mut decompressed_data).unwrap(),
434 all_input.len()
435 );
436 assert_eq!(decompressed_data, &all_input[..]);
437 }
438 }
439}