extern crate alloc;
extern crate std;
use alloc::vec;
use alloc::vec::Vec;
use std::io::{self, Read, Write};
use crate::{Decoder, Encoder, Status};
const SCRATCH: usize = 64 * 1024;
pub struct EncoderWriter<W: Write, E: Encoder> {
enc: E,
inner: Option<W>,
scratch: Vec<u8>,
finished: bool,
}
impl<W: Write, E: Encoder> EncoderWriter<W, E> {
pub fn new(inner: W, enc: E) -> Self {
Self {
enc,
inner: Some(inner),
scratch: vec![0u8; SCRATCH],
finished: false,
}
}
pub fn get_ref(&self) -> &W {
self.inner
.as_ref()
.expect("inner already taken by finish()")
}
pub fn get_mut(&mut self) -> &mut W {
self.inner
.as_mut()
.expect("inner already taken by finish()")
}
pub fn finish(mut self) -> io::Result<W> {
self.do_finish()?;
Ok(self
.inner
.take()
.expect("inner present until finish() taken it"))
}
fn do_finish(&mut self) -> io::Result<()> {
if self.finished {
return Ok(());
}
let inner = match self.inner.as_mut() {
Some(w) => w,
None => return Ok(()),
};
loop {
let (p, status) = self.enc.finish(&mut self.scratch)?;
inner.write_all(&self.scratch[..p.written])?;
if matches!(status, Status::StreamEnd) {
break;
}
if p.written == 0 {
return Err(io::Error::other("encoder stalled in finish"));
}
}
self.finished = true;
Ok(())
}
}
impl<W: Write, E: Encoder> Write for EncoderWriter<W, E> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.finished {
return Err(io::Error::other("encoder writer already finished"));
}
let inner = self
.inner
.as_mut()
.ok_or_else(|| io::Error::other("encoder writer already finished"))?;
let mut consumed = 0;
while consumed < buf.len() {
let (p, status) = self.enc.encode(&buf[consumed..], &mut self.scratch)?;
inner.write_all(&self.scratch[..p.written])?;
consumed += p.consumed;
match status {
Status::InputEmpty => break,
Status::OutputFull => continue,
Status::StreamEnd => break,
}
}
Ok(consumed)
}
fn flush(&mut self) -> io::Result<()> {
match self.inner.as_mut() {
Some(w) => w.flush(),
None => Ok(()),
}
}
}
impl<W: Write, E: Encoder> Drop for EncoderWriter<W, E> {
fn drop(&mut self) {
let _ = self.do_finish();
}
}
pub struct EncoderReader<R: Read, E: Encoder> {
enc: E,
inner: R,
in_buf: Vec<u8>,
in_filled: usize,
in_consumed: usize,
inner_eof: bool,
finished: bool,
}
impl<R: Read, E: Encoder> EncoderReader<R, E> {
pub fn new(inner: R, enc: E) -> Self {
Self {
enc,
inner,
in_buf: vec![0u8; SCRATCH],
in_filled: 0,
in_consumed: 0,
inner_eof: false,
finished: false,
}
}
pub fn get_ref(&self) -> &R {
&self.inner
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R: Read, E: Encoder> Read for EncoderReader<R, E> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if buf.is_empty() {
return Ok(0);
}
loop {
if self.finished {
return Ok(0);
}
if self.in_consumed < self.in_filled {
let (p, status) = self
.enc
.encode(&self.in_buf[self.in_consumed..self.in_filled], buf)?;
self.in_consumed += p.consumed;
if p.written > 0 {
let _ = status;
return Ok(p.written);
}
if matches!(status, Status::OutputFull) {
return Ok(0);
}
}
if !self.inner_eof {
self.in_consumed = 0;
self.in_filled = self.inner.read(&mut self.in_buf)?;
if self.in_filled == 0 {
self.inner_eof = true;
}
continue;
}
let (p, status) = self.enc.finish(buf)?;
if matches!(status, Status::StreamEnd) {
self.finished = true;
}
if p.written > 0 {
return Ok(p.written);
}
if self.finished {
return Ok(0);
}
return Ok(0);
}
}
}
pub struct DecoderWriter<W: Write, D: Decoder> {
dec: D,
inner: Option<W>,
scratch: Vec<u8>,
finished: bool,
}
impl<W: Write, D: Decoder> DecoderWriter<W, D> {
pub fn new(inner: W, dec: D) -> Self {
Self {
dec,
inner: Some(inner),
scratch: vec![0u8; SCRATCH],
finished: false,
}
}
pub fn get_ref(&self) -> &W {
self.inner
.as_ref()
.expect("inner already taken by finish()")
}
pub fn get_mut(&mut self) -> &mut W {
self.inner
.as_mut()
.expect("inner already taken by finish()")
}
pub fn finish(mut self) -> io::Result<W> {
self.do_finish()?;
Ok(self
.inner
.take()
.expect("inner present until finish() takes it"))
}
fn do_finish(&mut self) -> io::Result<()> {
if self.finished {
return Ok(());
}
let inner = match self.inner.as_mut() {
Some(w) => w,
None => return Ok(()),
};
loop {
let (p, status) = self.dec.finish(&mut self.scratch)?;
inner.write_all(&self.scratch[..p.written])?;
if matches!(status, Status::StreamEnd) {
break;
}
if p.written == 0 {
return Err(io::Error::other("decoder stalled in finish"));
}
}
self.finished = true;
Ok(())
}
}
impl<W: Write, D: Decoder> Write for DecoderWriter<W, D> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
if self.finished {
return Err(io::Error::other("decoder writer already finished"));
}
let inner = self
.inner
.as_mut()
.ok_or_else(|| io::Error::other("decoder writer already finished"))?;
let mut consumed = 0;
while consumed < buf.len() {
let (p, status) = self.dec.decode(&buf[consumed..], &mut self.scratch)?;
inner.write_all(&self.scratch[..p.written])?;
consumed += p.consumed;
match status {
Status::InputEmpty => break,
Status::OutputFull => continue,
Status::StreamEnd => break,
}
}
Ok(consumed)
}
fn flush(&mut self) -> io::Result<()> {
match self.inner.as_mut() {
Some(w) => w.flush(),
None => Ok(()),
}
}
}
impl<W: Write, D: Decoder> Drop for DecoderWriter<W, D> {
fn drop(&mut self) {
let _ = self.do_finish();
}
}
pub struct DecoderReader<R: Read, D: Decoder> {
dec: D,
inner: R,
in_buf: Vec<u8>,
in_filled: usize,
in_consumed: usize,
inner_eof: bool,
finished: bool,
}
impl<R: Read, D: Decoder> DecoderReader<R, D> {
pub fn new(inner: R, dec: D) -> Self {
Self {
dec,
inner,
in_buf: vec![0u8; SCRATCH],
in_filled: 0,
in_consumed: 0,
inner_eof: false,
finished: false,
}
}
pub fn get_ref(&self) -> &R {
&self.inner
}
pub fn get_mut(&mut self) -> &mut R {
&mut self.inner
}
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R: Read, D: Decoder> Read for DecoderReader<R, D> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
if buf.is_empty() {
return Ok(0);
}
loop {
if self.finished {
return Ok(0);
}
let (p, status) = self
.dec
.decode(&self.in_buf[self.in_consumed..self.in_filled], buf)?;
self.in_consumed += p.consumed;
if matches!(status, Status::StreamEnd) {
self.finished = true;
}
if p.written > 0 {
return Ok(p.written);
}
if self.finished {
return Ok(0);
}
if !self.inner_eof {
self.in_consumed = 0;
self.in_filled = self.inner.read(&mut self.in_buf)?;
if self.in_filled == 0 {
self.inner_eof = true;
}
continue;
}
let (p, status) = self.dec.finish(buf)?;
if matches!(status, Status::StreamEnd) {
self.finished = true;
}
if p.written > 0 {
return Ok(p.written);
}
return Ok(0);
}
}
}