use std::io;
use std::io::prelude::*;
use crate::zio;
use crate::{Compress, Decompress};
#[derive(Debug)]
pub struct DeflateEncoder<W: Write> {
inner: zio::Writer<W, Compress>,
}
impl<W: Write> DeflateEncoder<W> {
pub fn new(w: W, level: crate::Compression) -> DeflateEncoder<W> {
DeflateEncoder {
inner: zio::Writer::new(w, Compress::new(level, false)),
}
}
pub fn get_ref(&self) -> &W {
self.inner.get_ref()
}
pub fn get_mut(&mut self) -> &mut W {
self.inner.get_mut()
}
pub fn reset(&mut self, w: W) -> io::Result<W> {
self.inner.finish()?;
self.inner.data.reset();
Ok(self.inner.replace(w))
}
pub fn try_finish(&mut self) -> io::Result<()> {
self.inner.finish()
}
pub fn finish(mut self) -> io::Result<W> {
self.inner.finish()?;
Ok(self.inner.take_inner())
}
pub fn flush_finish(mut self) -> io::Result<W> {
self.inner.flush()?;
Ok(self.inner.take_inner())
}
pub fn total_in(&self) -> u64 {
self.inner.data.total_in()
}
pub fn total_out(&self) -> u64 {
self.inner.data.total_out()
}
}
impl<W: Write> Write for DeflateEncoder<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
impl<W: Read + Write> Read for DeflateEncoder<W> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.get_mut().read(buf)
}
}
#[derive(Debug)]
pub struct DeflateDecoder<W: Write> {
inner: zio::Writer<W, Decompress>,
}
impl<W: Write> DeflateDecoder<W> {
pub fn new(w: W) -> DeflateDecoder<W> {
DeflateDecoder {
inner: zio::Writer::new(w, Decompress::new(false)),
}
}
pub fn get_ref(&self) -> &W {
self.inner.get_ref()
}
pub fn get_mut(&mut self) -> &mut W {
self.inner.get_mut()
}
pub fn reset(&mut self, w: W) -> io::Result<W> {
self.inner.finish()?;
self.inner.data = Decompress::new(false);
Ok(self.inner.replace(w))
}
pub fn try_finish(&mut self) -> io::Result<()> {
self.inner.finish()
}
pub fn finish(mut self) -> io::Result<W> {
self.inner.finish()?;
Ok(self.inner.take_inner())
}
pub fn total_in(&self) -> u64 {
self.inner.data.total_in()
}
pub fn total_out(&self) -> u64 {
self.inner.data.total_out()
}
}
impl<W: Write> Write for DeflateDecoder<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.inner.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
impl<W: Read + Write> Read for DeflateDecoder<W> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.get_mut().read(buf)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Compression;
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World \
Hello World Hello World Hello World Hello World Hello World";
#[test]
fn decode_extra_data() {
let compressed = {
let mut e = DeflateEncoder::new(Vec::new(), Compression::default());
e.write(STR.as_ref()).unwrap();
let mut b = e.finish().unwrap();
b.push(b'x');
b
};
let mut writer = Vec::new();
let mut decoder = DeflateDecoder::new(writer);
let mut consumed_bytes = 0;
loop {
let n = decoder.write(&compressed[consumed_bytes..]).unwrap();
if n == 0 {
break;
}
consumed_bytes += n;
}
writer = decoder.finish().unwrap();
let actual = String::from_utf8(writer).expect("String parsing error");
assert_eq!(actual, STR);
assert_eq!(&compressed[consumed_bytes..], b"x");
}
}