use std::io::{self, Read, Write};
use crate::{Decoder, Encoder as FormatEncoder, Format, Level, Limits, Status, deflate::Flush};
const BUF: usize = 32 * 1024;
#[derive(Debug)]
pub struct Reader<R> {
inner: R,
decoder: Decoder,
buf: Box<[u8]>,
pos: usize,
len: usize,
eof: bool,
}
impl<R: Read> Reader<R> {
pub fn new(inner: R, format: Format) -> Self {
Self {
inner,
decoder: Decoder::new(format),
buf: vec![0; BUF].into_boxed_slice(),
pos: 0,
len: 0,
eof: false,
}
}
#[must_use]
pub fn with_limits(mut self, limits: Limits) -> Self {
self.decoder = self.decoder.with_limits(limits);
self
}
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R: Read> Read for Reader<R> {
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
if out.is_empty() || self.decoder.is_done() {
return Ok(0);
}
loop {
if self.pos == self.len && !self.eof {
self.len = self.inner.read(&mut self.buf)?;
self.pos = 0;
self.eof = self.len == 0;
}
let input = &self.buf[self.pos..self.len];
let p = if self.eof {
self.decoder.finish(input, out)?
} else {
self.decoder.decompress(input, out)?
};
self.pos += p.consumed;
if p.produced > 0 || p.status == Status::Done {
return Ok(p.produced);
}
}
}
}
#[derive(Debug)]
pub struct Writer<W: Write> {
inner: Option<W>,
encoder: FormatEncoder,
buf: Box<[u8]>,
finished: bool,
}
impl<W: Write> Writer<W> {
pub fn new(inner: W, format: Format, level: Level) -> Self {
Self {
inner: Some(inner),
encoder: FormatEncoder::new(format, level),
buf: vec![0; BUF].into_boxed_slice(),
finished: false,
}
}
fn pump(&mut self, mut input: &[u8], flush: Flush) -> io::Result<usize> {
let mut taken = 0;
let Some(inner) = self.inner.as_mut() else {
return Err(io::Error::other("writer already finished"));
};
loop {
let p = self.encoder.compress(input, &mut self.buf, flush)?;
inner.write_all(&self.buf[..p.produced])?;
input = &input[p.consumed..];
taken += p.consumed;
if p.status != Status::NeedsOutput {
return Ok(taken);
}
}
}
pub fn finish(mut self) -> io::Result<W> {
self.pump(&[], Flush::Finish)?;
self.finished = true;
let mut inner = self
.inner
.take()
.ok_or_else(|| io::Error::other("writer already finished"))?;
inner.flush()?;
Ok(inner)
}
}
impl<W: Write> Write for Writer<W> {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
self.pump(data, Flush::None)
}
fn flush(&mut self) -> io::Result<()> {
self.pump(&[], Flush::Sync)?;
match self.inner.as_mut() {
Some(inner) => inner.flush(),
None => Ok(()),
}
}
}
impl<W: Write> Drop for Writer<W> {
fn drop(&mut self) {
if !self.finished && self.inner.is_some() {
let _ = self.pump(&[], Flush::Finish);
}
}
}
#[derive(Debug)]
pub struct Encoder<R> {
inner: R,
encoder: FormatEncoder,
buf: Box<[u8]>,
pos: usize,
len: usize,
eof: bool,
done: bool,
}
impl<R: Read> Encoder<R> {
pub fn new(inner: R, format: Format, level: Level) -> Self {
Self {
inner,
encoder: FormatEncoder::new(format, level),
buf: vec![0; BUF].into_boxed_slice(),
pos: 0,
len: 0,
eof: false,
done: false,
}
}
}
impl<R: Read> Read for Encoder<R> {
fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
if out.is_empty() || self.done {
return Ok(0);
}
loop {
if self.pos == self.len && !self.eof {
self.len = self.inner.read(&mut self.buf)?;
self.pos = 0;
self.eof = self.len == 0;
}
let flush = if self.eof { Flush::Finish } else { Flush::None };
let p = self
.encoder
.compress(&self.buf[self.pos..self.len], out, flush)?;
self.pos += p.consumed;
if p.status == Status::Done && self.eof {
self.done = true;
}
if p.produced > 0 || self.done {
return Ok(p.produced);
}
}
}
}
#[derive(Debug)]
pub struct DecodeWriter<W: Write> {
inner: W,
decoder: Decoder,
buf: Box<[u8]>,
}
impl<W: Write> DecodeWriter<W> {
pub fn new(inner: W, format: Format) -> Self {
Self {
inner,
decoder: Decoder::new(format),
buf: vec![0; BUF].into_boxed_slice(),
}
}
#[must_use]
pub fn with_limits(mut self, limits: Limits) -> Self {
self.decoder = self.decoder.with_limits(limits);
self
}
fn pump(&mut self, mut data: &[u8], last: bool) -> io::Result<usize> {
let mut taken = 0;
loop {
let p = if last {
self.decoder.finish(data, &mut self.buf)?
} else {
self.decoder.decompress(data, &mut self.buf)?
};
self.inner.write_all(&self.buf[..p.produced])?;
data = &data[p.consumed..];
taken += p.consumed;
match p.status {
Status::NeedsOutput => continue,
Status::Done if !data.is_empty() => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
crate::Error::new(crate::ErrorKind::TrailingData, self.decoder.total_in()),
));
}
_ => return Ok(taken),
}
}
}
pub fn finish(mut self) -> io::Result<W> {
self.pump(&[], true)?;
self.inner.flush()?;
Ok(self.inner)
}
}
impl<W: Write> Write for DecodeWriter<W> {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
self.pump(data, false)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}