use std::io;
use std::io::prelude::*;
use std::mem;
use crate::zio;
use crate::{Compress, Decompress};
#[derive(Debug)]
pub struct DeflateEncoder<R> {
obj: R,
data: Compress,
}
impl<R: BufRead> DeflateEncoder<R> {
pub fn new(r: R, level: crate::Compression) -> DeflateEncoder<R> {
DeflateEncoder {
obj: r,
data: Compress::new(level, false),
}
}
}
pub fn reset_encoder_data<R>(zlib: &mut DeflateEncoder<R>) {
zlib.data.reset();
}
impl<R> DeflateEncoder<R> {
pub fn reset(&mut self, r: R) -> R {
reset_encoder_data(self);
mem::replace(&mut self.obj, r)
}
pub fn get_ref(&self) -> &R {
&self.obj
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.obj
}
pub fn into_inner(self) -> R {
self.obj
}
pub fn total_in(&self) -> u64 {
self.data.total_in()
}
pub fn total_out(&self) -> u64 {
self.data.total_out()
}
}
impl<R: BufRead> Read for DeflateEncoder<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
zio::read(&mut self.obj, &mut self.data, buf)
}
}
impl<W: BufRead + Write> Write for DeflateEncoder<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()
}
}
#[derive(Debug)]
pub struct DeflateDecoder<R> {
obj: R,
data: Decompress,
}
pub fn reset_decoder_data<R>(zlib: &mut DeflateDecoder<R>) {
zlib.data = Decompress::new(false);
}
impl<R: BufRead> DeflateDecoder<R> {
pub fn new(r: R) -> DeflateDecoder<R> {
DeflateDecoder {
obj: r,
data: Decompress::new(false),
}
}
}
impl<R> DeflateDecoder<R> {
pub fn reset(&mut self, r: R) -> R {
reset_decoder_data(self);
mem::replace(&mut self.obj, r)
}
pub fn reset_data(&mut self) {
reset_decoder_data(self);
}
pub fn get_ref(&self) -> &R {
&self.obj
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.obj
}
pub fn into_inner(self) -> R {
self.obj
}
pub fn total_in(&self) -> u64 {
self.data.total_in()
}
pub fn total_out(&self) -> u64 {
self.data.total_out()
}
}
impl<R: BufRead> Read for DeflateDecoder<R> {
fn read(&mut self, into: &mut [u8]) -> io::Result<usize> {
zio::read(&mut self.obj, &mut self.data, into)
}
}
impl<W: BufRead + Write> Write for DeflateDecoder<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(test)]
mod test {
use crate::bufread::DeflateDecoder;
use crate::deflate::write;
use crate::Compression;
use std::io::{Read, Write};
#[test]
fn decode_extra_data() {
let expected = "Hello World";
let compressed = {
let mut e = write::DeflateEncoder::new(Vec::new(), Compression::default());
e.write(expected.as_ref()).unwrap();
let mut b = e.finish().unwrap();
b.push(b'x');
b
};
let mut output = Vec::new();
let mut decoder = DeflateDecoder::new(compressed.as_slice());
let decoded_bytes = decoder.read_to_end(&mut output).unwrap();
assert_eq!(decoded_bytes, output.len());
let actual = std::str::from_utf8(&output).expect("String parsing error");
assert_eq!(
actual, expected,
"after decompression we obtain the original input"
);
output.clear();
assert_eq!(
decoder.read(&mut output).unwrap(),
0,
"subsequent read of decoder returns 0, but inner reader can return additional data"
);
let mut reader = decoder.into_inner();
assert_eq!(
reader.read_to_end(&mut output).unwrap(),
1,
"extra data is accessible in underlying buf-read"
);
assert_eq!(output, b"x");
}
}