use anyhow::Result;
use flate2::{Compression, CrcReader, CrcWriter};
use crate::RwBuilder;
#[derive(Debug)]
pub struct CompressionBuilder<B, C>
where
B: RwBuilder,
C: CoderBuilder<B::Reader, B::Writer>,
{
builder: B,
compression: Compression,
coder: C,
}
impl<B, C> RwBuilder for CompressionBuilder<B, C>
where
B: RwBuilder,
B::Reader: std::io::Read,
B::Writer: std::io::Write,
C: CoderBuilder<B::Reader, B::Writer>,
C::Decoder: std::io::Read,
C::Encoder: std::io::Write,
{
type Reader = C::Decoder;
type Writer = C::Encoder;
fn reader(&self) -> Result<Self::Reader> {
let reader = self.builder.reader()?;
Ok(self.coder.decoder(reader))
}
fn writer(&self) -> Result<Self::Writer> {
let writer = self.builder.writer()?;
Ok(self.coder.encoder(writer, self.compression))
}
}
pub trait CoderBuilder<R, W> {
type Encoder;
fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder;
type Decoder;
fn decoder(&self, reader: R) -> Self::Decoder;
}
#[derive(Default, Debug, Copy, Clone)]
pub struct Zlib;
impl<R, W> CoderBuilder<R, W> for Zlib
where
R: std::io::Read,
W: std::io::Write,
{
type Decoder = flate2::read::ZlibDecoder<R>;
type Encoder = flate2::write::ZlibEncoder<W>;
fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder {
flate2::write::ZlibEncoder::new(writer, compression)
}
fn decoder(&self, reader: R) -> Self::Decoder {
flate2::read::ZlibDecoder::new(reader)
}
}
pub trait Constructor<B>
where
Self: Sized + CoderBuilder<B::Reader, B::Writer> + Default,
B: RwBuilder,
{
fn new(builder: B, compression: Compression) -> CompressionBuilder<B, Self> {
CompressionBuilder { builder, compression, coder: Self::default() }
}
}
impl<B> Constructor<B> for Zlib where B: RwBuilder {}
#[derive(Default, Debug, Copy, Clone)]
pub struct Gz;
impl<R, W> CoderBuilder<R, W> for Gz
where
R: std::io::Read,
W: std::io::Write,
{
type Decoder = flate2::read::GzDecoder<R>;
type Encoder = flate2::write::GzEncoder<W>;
fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder {
flate2::write::GzEncoder::new(writer, compression)
}
fn decoder(&self, reader: R) -> Self::Decoder {
flate2::read::GzDecoder::new(reader)
}
}
impl<B> Constructor<B> for Gz where B: RwBuilder {}
#[derive(Default, Debug, Copy, Clone)]
pub struct Deflate;
impl<R, W> CoderBuilder<R, W> for Deflate
where
R: std::io::Read,
W: std::io::Write,
{
type Decoder = flate2::read::DeflateDecoder<R>;
type Encoder = flate2::write::DeflateEncoder<W>;
fn encoder(&self, writer: W, compression: Compression) -> Self::Encoder {
flate2::write::DeflateEncoder::new(writer, compression)
}
fn decoder(&self, reader: R) -> Self::Decoder {
flate2::read::DeflateDecoder::new(reader)
}
}
impl<B> Constructor<B> for Deflate where B: RwBuilder {}
#[derive(Debug)]
pub struct CrcBuilder<B>
where
B: RwBuilder,
{
builder: B,
}
impl<B> CrcBuilder<B>
where
B: RwBuilder,
{
#[must_use]
pub const fn new(builder: B) -> Self {
Self { builder }
}
}
impl<B> RwBuilder for CrcBuilder<B>
where
B: RwBuilder,
B::Reader: std::io::Read,
B::Writer: std::io::Write,
{
type Reader = CrcReader<B::Reader>;
type Writer = CrcWriter<B::Writer>;
fn reader(&self) -> Result<Self::Reader> {
Ok(CrcReader::new(self.builder.reader()?))
}
fn writer(&self) -> Result<Self::Writer> {
Ok(CrcWriter::new(self.builder.writer()?))
}
}