use std::io::{self, Write};
use std::vec::Vec;
use super::{Encoder, Flush, Level};
use crate::Format;
const BUF_LEN: usize = 256 * 1024;
const _: () = assert!(BUF_LEN >= 2 * super::MIN_BUFFER_LEN);
const OUT_LEN: usize = 64 * 1024;
pub struct Writer<W: Write> {
inner: W,
encoder: std::boxed::Box<Encoder>,
buf: Vec<u8>,
out: Vec<u8>,
}
impl<W: Write + core::fmt::Debug> core::fmt::Debug for Writer<W> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Writer")
.field("inner", &self.inner)
.field("encoder", &self.encoder)
.finish_non_exhaustive()
}
}
impl<W: Write> Writer<W> {
pub fn new(format: Format, level: Level, inner: W) -> Self {
Writer {
inner,
encoder: std::boxed::Box::new(Encoder::new(format, level)),
buf: Vec::new(),
out: Vec::new(),
}
}
pub fn encoder(&self) -> &Encoder {
&self.encoder
}
pub fn get_ref(&self) -> &W {
&self.inner
}
pub fn get_mut(&mut self) -> &mut W {
&mut self.inner
}
pub fn finish(mut self) -> io::Result<W> {
self.run(Flush::Finish)?;
Ok(self.inner)
}
fn run(&mut self, flush: Flush) -> io::Result<()> {
if self.out.is_empty() {
self.out = std::vec![0; OUT_LEN];
}
loop {
let p = self.encoder.compress(&self.buf, &mut self.out, flush);
let full = p.full;
self.inner.write_all(p.output)?;
if !full {
return Ok(());
}
}
}
}
impl<W: Write> Write for Writer<W> {
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
if data.is_empty() {
return Ok(0);
}
if self.buf.capacity() == 0 {
self.buf.reserve_exact(BUF_LEN);
}
if self.buf.len() == BUF_LEN {
self.run(Flush::None)?;
let dropped = self.encoder.make_room(&mut self.buf);
self.buf.truncate(BUF_LEN - dropped);
}
let n = data.len().min(BUF_LEN - self.buf.len());
self.buf.extend_from_slice(&data[..n]);
Ok(n)
}
fn flush(&mut self) -> io::Result<()> {
self.run(Flush::Sync)?;
self.get_mut().flush()
}
}