use std::io::prelude::*;
use std::io::{self, BufReader};
#[cfg(feature = "tokio")]
use futures::Poll;
#[cfg(feature = "tokio")]
use tokio_io::{AsyncRead, AsyncWrite};
use bufread;
use Compression;
pub struct BzEncoder<R> {
inner: bufread::BzEncoder<BufReader<R>>,
}
pub struct BzDecoder<R> {
inner: bufread::BzDecoder<BufReader<R>>,
}
impl<R: Read> BzEncoder<R> {
pub fn new(r: R, level: Compression) -> BzEncoder<R> {
BzEncoder {
inner: bufread::BzEncoder::new(BufReader::new(r), level),
}
}
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
pub fn total_out(&self) -> u64 {
self.inner.total_out()
}
pub fn total_in(&self) -> u64 {
self.inner.total_in()
}
}
impl<R: Read> Read for BzEncoder<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncRead> AsyncRead for BzEncoder<R> {}
impl<W: Write + Read> Write for BzEncoder<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncWrite + Read> AsyncWrite for BzEncoder<R> {
fn shutdown(&mut self) -> Poll<(), io::Error> {
self.get_mut().shutdown()
}
}
impl<R: Read> BzDecoder<R> {
pub fn new(r: R) -> BzDecoder<R> {
BzDecoder {
inner: bufread::BzDecoder::new(BufReader::new(r)),
}
}
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
pub fn total_out(&self) -> u64 {
self.inner.total_out()
}
pub fn total_in(&self) -> u64 {
self.inner.total_in()
}
}
impl<R: Read> Read for BzDecoder<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.inner.read(into)
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncRead + Read> AsyncRead for BzDecoder<R> {}
impl<W: Write + Read> Write for BzDecoder<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncWrite + Read> AsyncWrite for BzDecoder<R> {
fn shutdown(&mut self) -> Poll<(), io::Error> {
self.get_mut().shutdown()
}
}
pub struct MultiBzDecoder<R> {
inner: bufread::MultiBzDecoder<BufReader<R>>,
}
impl<R: Read> MultiBzDecoder<R> {
pub fn new(r: R) -> MultiBzDecoder<R> {
MultiBzDecoder {
inner: bufread::MultiBzDecoder::new(BufReader::new(r)),
}
}
}
impl<R> MultiBzDecoder<R> {
pub fn get_ref(&self) -> &R {
self.inner.get_ref().get_ref()
}
pub fn get_mut(&mut self) -> &mut R {
self.inner.get_mut().get_mut()
}
pub fn into_inner(self) -> R {
self.inner.into_inner().into_inner()
}
}
impl<R: Read> Read for MultiBzDecoder<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
self.inner.read(into)
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncRead> AsyncRead for MultiBzDecoder<R> {}
impl<R: Read + Write> Write for MultiBzDecoder<R> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.get_mut().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.get_mut().flush()
}
}
#[cfg(feature = "tokio")]
impl<R: AsyncWrite + AsyncRead> AsyncWrite for MultiBzDecoder<R> {
fn shutdown(&mut self) -> Poll<(), io::Error> {
self.get_mut().shutdown()
}
}
#[cfg(test)]
mod tests {
use partial_io::{GenInterrupted, PartialRead, PartialWithErrors};
use rand::distributions::Standard;
use rand::{thread_rng, Rng};
use read::{BzDecoder, BzEncoder, MultiBzDecoder};
use std::io::prelude::*;
use Compression;
#[test]
fn smoke() {
let m: &[u8] = &[1, 2, 3, 4, 5, 6, 7, 8];
let mut c = BzEncoder::new(m, Compression::default());
let mut data = vec![];
c.read_to_end(&mut data).unwrap();
let mut d = BzDecoder::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 = BzEncoder::new(m, Compression::default());
let mut d = BzDecoder::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 = BzEncoder::new(&m[..], Compression::default());
let mut d = BzDecoder::new(c);
let mut data = vec![];
d.read_to_end(&mut data).unwrap();
assert!(data == &m[..]);
}
#[test]
fn self_terminating() {
let m = vec![3u8; 128 * 1024 + 1];
let mut c = BzEncoder::new(&m[..], Compression::default());
let mut result = Vec::new();
c.read_to_end(&mut result).unwrap();
let v = thread_rng()
.sample_iter(&Standard)
.take(1024)
.collect::<Vec<_>>();
for _ in 0..200 {
result.extend(v.iter().map(|x: &u8| *x));
}
let mut d = BzDecoder::new(&result[..]);
let mut data = Vec::with_capacity(m.len());
unsafe {
data.set_len(m.len());
}
assert!(d.read(&mut data).unwrap() == m.len());
assert!(data == &m[..]);
}
#[test]
fn zero_length_read_at_eof() {
let m = Vec::new();
let mut c = BzEncoder::new(&m[..], Compression::default());
let mut result = Vec::new();
c.read_to_end(&mut result).unwrap();
let mut d = BzDecoder::new(&result[..]);
let mut data = Vec::new();
assert!(d.read(&mut data).unwrap() == 0);
}
#[test]
fn zero_length_read_with_data() {
let m = vec![3u8; 128 * 1024 + 1];
let mut c = BzEncoder::new(&m[..], Compression::default());
let mut result = Vec::new();
c.read_to_end(&mut result).unwrap();
let mut d = BzDecoder::new(&result[..]);
let mut data = Vec::new();
assert!(d.read(&mut data).unwrap() == 0);
}
#[test]
fn multistream_read_till_eof() {
let m = vec![3u8; 128 * 1024 + 1];
let repeat = 3;
let mut result = Vec::new();
for _i in 0..repeat {
let mut c = BzEncoder::new(&m[..], Compression::default());
c.read_to_end(&mut result).unwrap();
}
let mut d = MultiBzDecoder::new(&result[..]);
let mut data = Vec::new();
let a = d.read_to_end(&mut data).unwrap();
let b = m.len() * repeat;
assert!(a == b, "{} {}", a, b);
}
#[test]
fn empty() {
let r = BzEncoder::new(&[][..], Compression::default());
let mut r = BzDecoder::new(r);
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
assert!(v2.len() == 0);
}
#[test]
fn qc() {
::quickcheck::quickcheck(test as fn(_) -> _);
fn test(v: Vec<u8>) -> bool {
let r = BzEncoder::new(&v[..], Compression::default());
let mut r = BzDecoder::new(r);
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
v == v2
}
}
#[test]
fn qc_partial() {
quickcheck6::quickcheck(test as fn(_, _, _) -> _);
fn test(
v: Vec<u8>,
encode_ops: PartialWithErrors<GenInterrupted>,
decode_ops: PartialWithErrors<GenInterrupted>,
) -> bool {
let r = BzEncoder::new(PartialRead::new(&v[..], encode_ops), Compression::default());
let mut r = BzDecoder::new(PartialRead::new(r, decode_ops));
let mut v2 = Vec::new();
r.read_to_end(&mut v2).unwrap();
v == v2
}
}
}