use std::io::prelude::*;
use std::io::{self, BufReader};
#[cfg(feature = "tokio")]
use futures::Poll;
#[cfg(feature = "tokio")]
use tokio_io::{AsyncRead, AsyncWrite};
use crate::bufread;
use crate::stream::Stream;
pub struct XzEncoder<R: Read> {
inner: bufread::XzEncoder<BufReader<R>>,
}
pub struct XzDecoder<R: Read> {
inner: bufread::XzDecoder<BufReader<R>>,
}
impl<R: Read> XzEncoder<R> {
#[inline]
pub fn new(r: R, level: u32) -> XzEncoder<R> {
XzEncoder {
inner: bufread::XzEncoder::new(BufReader::new(r), level),
}
}
#[cfg(feature = "parallel")]
pub fn new_parallel(r: R, level: u32) -> XzEncoder<R> {
XzEncoder {
inner: bufread::XzEncoder::new_parallel(BufReader::new(r), level),
}
}
#[inline]
pub fn new_stream(r: R, stream: Stream) -> XzEncoder<R> {
XzEncoder {
inner: bufread::XzEncoder::new_stream(BufReader::new(r), stream),
}
}
#[inline]
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
#[inline]
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
#[inline]
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
#[inline]
pub fn total_out(&self) -> u64 {
self.inner.total_out()
}
#[inline]
pub fn total_in(&self) -> u64 {
self.inner.total_in()
}
}
impl<R: Read> Read for XzEncoder<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncRead> AsyncRead for XzEncoder<R> {}
impl<W: Write + Read> Write for XzEncoder<W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncWrite + Read> AsyncWrite for XzEncoder<R> {
#[inline]
fn shutdown(&mut self) -> Poll<(), io::Error> {
self.get_mut().shutdown()
}
}
impl<R: Read> XzDecoder<R> {
#[inline]
pub fn new(r: R) -> XzDecoder<R> {
XzDecoder {
inner: bufread::XzDecoder::new(BufReader::new(r)),
}
}
#[cfg(feature = "parallel")]
#[inline]
pub fn new_parallel(r: R) -> XzDecoder<R> {
XzDecoder {
inner: bufread::XzDecoder::new_parallel(BufReader::new(r)),
}
}
#[inline]
pub fn new_multi_decoder(r: R) -> XzDecoder<R> {
XzDecoder {
inner: bufread::XzDecoder::new_multi_decoder(BufReader::new(r)),
}
}
#[inline]
pub fn new_stream(r: R, stream: Stream) -> XzDecoder<R> {
XzDecoder {
inner: bufread::XzDecoder::new_stream(BufReader::new(r), stream),
}
}
#[inline]
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
#[inline]
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
#[inline]
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
#[inline]
pub fn total_out(&self) -> u64 {
self.inner.total_out()
}
#[inline]
pub fn total_in(&self) -> u64 {
self.inner.total_in()
}
}
impl<R: Read> Read for XzDecoder<R> {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncRead + Read> AsyncRead for XzDecoder<R> {}
impl<W: Write + Read> Write for XzDecoder<W> {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncWrite + Read> AsyncWrite for XzDecoder<R> {
#[inline]
fn shutdown(&mut self) -> Poll<(), io::Error> {
self.get_mut().shutdown()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::stream::LzmaOptions;
use quickcheck::quickcheck;
use rand::{thread_rng, Rng};
use std::iter;
#[test]
fn smoke() {
let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
let mut c = XzEncoder::new(m, 6);
let mut data = vec![];
c.read_to_end(&mut data).unwrap();
let mut d = XzDecoder::new(&data[..]);
let mut data2 = Vec::new();
d.read_to_end(&mut data2).unwrap();
assert_eq!(data2, m);
}
#[test]
fn smoke2() {
let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
let c = XzEncoder::new(m, 6);
let mut d = XzDecoder::new(c);
let mut data = vec![];
d.read_to_end(&mut data).unwrap();
assert_eq!(data, [1, 2, 3, 4, 5, 6, 7, 8]);
}
#[test]
fn smoke3() {
let m = vec![3u8; 128 * 1024 + 1];
let c = XzEncoder::new(&m[..], 6);
let mut d = XzDecoder::new(c);
let mut data = vec![];
d.read_to_end(&mut data).unwrap();
assert_eq!(data, &m[..]);
}
#[test]
fn self_terminating() {
let m = vec![3u8; 128 * 1024 + 1];
let mut c = XzEncoder::new(&m[..], 6);
let mut result = Vec::new();
c.read_to_end(&mut result).unwrap();
let mut rng = thread_rng();
let v = iter::repeat_with(|| rng.gen::<u8>())
.take(1024)
.collect::<Vec<_>>();
for _ in 0..200 {
result.extend(v.iter().map(|x| *x));
}
let mut d = XzDecoder::new(&result[..]);
let mut data = Vec::with_capacity(m.len());
unsafe {
data.set_len(m.len());
}
assert_eq!(d.read(&mut data).unwrap(), m.len());
assert_eq!(data, &m[..]);
}
#[test]
fn zero_length_read_at_eof() {
let m = Vec::new();
let mut c = XzEncoder::new(&m[..], 6);
let mut result = Vec::new();
c.read_to_end(&mut result).unwrap();
let mut d = XzDecoder::new(&result[..]);
let mut data = Vec::new();
assert_eq!(d.read(&mut data).unwrap(), 0);
}
#[test]
fn zero_length_read_with_data() {
let m = vec![3u8; 128 * 1024 + 1];
let mut c = XzEncoder::new(&m[..], 6);
let mut result = Vec::new();
c.read_to_end(&mut result).unwrap();
let mut d = XzDecoder::new(&result[..]);
let mut data = Vec::new();
assert_eq!(d.read(&mut data).unwrap(), 0);
}
#[test]
fn qc_lzma1() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let options = LzmaOptions::new_preset(6).unwrap();
let stream = Stream::new_lzma_encoder(&options).unwrap();
let r = XzEncoder::new_stream(&v[..], stream);
let stream = Stream::new_lzma_decoder(u64::MAX).unwrap();
let mut r = XzDecoder::new_stream(r, stream);
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
v == v2
}
}
#[test]
fn qc() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let r = XzEncoder::new(&v[..], 6);
let mut r = XzDecoder::new(r);
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
v == v2
}
}
#[cfg(feature = "parallel")]
#[test]
fn qc_parallel_encode() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let r = XzEncoder::new_parallel(&v[..], 6);
let mut r = XzDecoder::new(r);
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
v == v2
}
}
#[cfg(feature = "parallel")]
#[test]
fn qc_parallel_decode() {
quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let r = XzEncoder::new(&v[..], 6);
let mut r = XzDecoder::new_parallel(r);
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
v == v2
}
}
#[test]
fn two_streams() {
let mut input_stream1: Vec<u8> = Vec::new();
let mut input_stream2: Vec<u8> = Vec::new();
let mut all_input: Vec<u8> = Vec::new();
const STREAM1_SIZE: usize = 1024;
for num in 0..STREAM1_SIZE {
input_stream1.push(num as u8)
}
const STREAM2_SIZE: usize = 532;
for num in 0..STREAM2_SIZE {
input_stream2.push((num + 32) as u8)
}
all_input.extend(&input_stream1);
all_input.extend(&input_stream2);
let mut decoder_input = Vec::new();
{
let mut encoder = XzEncoder::new(&input_stream1[..], 6);
encoder.read_to_end(&mut decoder_input).unwrap();
}
{
let mut encoder = XzEncoder::new(&input_stream2[..], 6);
encoder.read_to_end(&mut decoder_input).unwrap();
}
let mut decoder_reader = &decoder_input[..];
{
let mut decoder = XzDecoder::new_multi_decoder(&mut decoder_reader);
let mut decompressed_data = vec![0u8; all_input.len()];
assert_eq!(
decoder.read(&mut decompressed_data).unwrap(),
all_input.len()
);
assert_eq!(decompressed_data, &all_input[..]);
}
}
}