use std::io::{self, Write};
use zstd_safe;
use crate::dict::{DecoderDictionary, EncoderDictionary};
use crate::stream::{raw, zio};
#[cfg(test)]
mod tests;
pub struct Encoder<'a, W: Write> {
writer: zio::Writer<W, raw::Encoder<'a>>,
}
pub struct Decoder<'a, W: Write> {
writer: zio::Writer<W, raw::Decoder<'a>>,
}
pub struct AutoFinishEncoder<
'a,
W: Write,
F: FnMut(io::Result<W>) = Box<dyn Send + FnMut(io::Result<W>)>,
> {
encoder: Option<Encoder<'a, W>>,
on_finish: Option<F>,
}
pub struct AutoFlushDecoder<
'a,
W: Write,
F: FnMut(io::Result<()>) = Box<dyn Send + FnMut(io::Result<()>)>,
> {
decoder: Option<Decoder<'a, W>>,
on_flush: Option<F>,
}
impl<'a, W: Write, F: FnMut(io::Result<()>)> AutoFlushDecoder<'a, W, F> {
fn new(decoder: Decoder<'a, W>, on_flush: F) -> Self {
AutoFlushDecoder {
decoder: Some(decoder),
on_flush: Some(on_flush),
}
}
pub fn get_ref(&self) -> &W {
self.decoder.as_ref().unwrap().get_ref()
}
pub fn get_mut(&mut self) -> &mut W {
self.decoder.as_mut().unwrap().get_mut()
}
}
impl<W, F> Drop for AutoFlushDecoder<'_, W, F>
where
W: Write,
F: FnMut(io::Result<()>),
{
fn drop(&mut self) {
let mut decoder = self.decoder.take().unwrap();
let result = decoder.flush();
if let Some(mut on_finish) = self.on_flush.take() {
on_finish(result);
}
}
}
impl<W: Write, F: FnMut(io::Result<()>)> Write for AutoFlushDecoder<'_, W, F> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.decoder.as_mut().unwrap().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.decoder.as_mut().unwrap().flush()
}
}
impl<'a, W: Write, F: FnMut(io::Result<W>)> AutoFinishEncoder<'a, W, F> {
fn new(encoder: Encoder<'a, W>, on_finish: F) -> Self {
AutoFinishEncoder {
encoder: Some(encoder),
on_finish: Some(on_finish),
}
}
pub fn get_ref(&self) -> &W {
self.encoder.as_ref().unwrap().get_ref()
}
pub fn get_mut(&mut self) -> &mut W {
self.encoder.as_mut().unwrap().get_mut()
}
}
impl<W: Write, F: FnMut(io::Result<W>)> Drop for AutoFinishEncoder<'_, W, F> {
fn drop(&mut self) {
let result = self.encoder.take().unwrap().finish();
if let Some(mut on_finish) = self.on_finish.take() {
on_finish(result);
}
}
}
impl<W: Write, F: FnMut(io::Result<W>)> Write for AutoFinishEncoder<'_, W, F> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.encoder.as_mut().unwrap().write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.encoder.as_mut().unwrap().flush()
}
}
impl<W: Write> Encoder<'static, W> {
pub fn new(writer: W, level: i32) -> io::Result<Self> {
Self::with_dictionary(writer, level, &[])
}
pub fn with_dictionary(
writer: W,
level: i32,
dictionary: &[u8],
) -> io::Result<Self> {
let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
Ok(Self::with_encoder(writer, encoder))
}
}
impl<'a, W: Write> Encoder<'a, W> {
pub fn with_writer(writer: zio::Writer<W, raw::Encoder<'a>>) -> Self {
Self { writer }
}
pub fn with_encoder(writer: W, encoder: raw::Encoder<'a>) -> Self {
let writer = zio::Writer::new(writer, encoder);
Self::with_writer(writer)
}
pub fn with_context(
writer: W,
context: &'a mut zstd_safe::CCtx<'static>,
) -> Self {
let encoder = raw::Encoder::with_context(context);
Self::with_encoder(writer, encoder)
}
pub fn with_prepared_dictionary<'b>(
writer: W,
dictionary: &EncoderDictionary<'b>,
) -> io::Result<Self>
where
'b: 'a,
{
let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
Ok(Self::with_encoder(writer, encoder))
}
pub fn with_ref_prefix<'b>(
writer: W,
level: i32,
ref_prefix: &'b [u8],
) -> io::Result<Self>
where
'b: 'a,
{
let encoder = raw::Encoder::with_ref_prefix(level, ref_prefix)?;
Ok(Self::with_encoder(writer, encoder))
}
pub fn auto_finish(self) -> AutoFinishEncoder<'a, W> {
AutoFinishEncoder {
encoder: Some(self),
on_finish: None,
}
}
pub fn on_finish<F: FnMut(io::Result<W>)>(
self,
f: F,
) -> AutoFinishEncoder<'a, W, F> {
AutoFinishEncoder::new(self, f)
}
pub fn get_ref(&self) -> &W {
self.writer.writer()
}
pub fn get_mut(&mut self) -> &mut W {
self.writer.writer_mut()
}
pub fn finish(self) -> io::Result<W> {
self.try_finish().map_err(|(_, err)| err)
}
pub fn try_finish(mut self) -> Result<W, (Self, io::Error)> {
match self.writer.finish() {
Ok(()) => Ok(self.writer.into_inner().0),
Err(e) => Err((self, e)),
}
}
pub fn do_finish(&mut self) -> io::Result<()> {
self.writer.finish()
}
pub fn recommended_input_size() -> usize {
zstd_safe::CCtx::in_size()
}
crate::encoder_common!(writer);
}
impl<'a, W: Write> Write for Encoder<'a, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.writer.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.writer.flush()
}
}
impl<W: Write> Decoder<'static, W> {
pub fn new(writer: W) -> io::Result<Self> {
Self::with_dictionary(writer, &[])
}
pub fn with_dictionary(writer: W, dictionary: &[u8]) -> io::Result<Self> {
let decoder = raw::Decoder::with_dictionary(dictionary)?;
Ok(Self::with_decoder(writer, decoder))
}
}
impl<'a, W: Write> Decoder<'a, W> {
pub fn with_writer(writer: zio::Writer<W, raw::Decoder<'a>>) -> Self {
Decoder { writer }
}
pub fn with_decoder(writer: W, decoder: raw::Decoder<'a>) -> Self {
let writer = zio::Writer::new(writer, decoder);
Decoder { writer }
}
pub fn with_prepared_dictionary<'b>(
writer: W,
dictionary: &DecoderDictionary<'b>,
) -> io::Result<Self>
where
'b: 'a,
{
let decoder = raw::Decoder::with_prepared_dictionary(dictionary)?;
Ok(Self::with_decoder(writer, decoder))
}
pub fn get_ref(&self) -> &W {
self.writer.writer()
}
pub fn get_mut(&mut self) -> &mut W {
self.writer.writer_mut()
}
pub fn into_inner(self) -> W {
self.writer.into_inner().0
}
pub fn recommended_input_size() -> usize {
zstd_safe::DCtx::in_size()
}
pub fn auto_flush(self) -> AutoFlushDecoder<'a, W> {
AutoFlushDecoder {
decoder: Some(self),
on_flush: None,
}
}
pub fn on_flush<F: FnMut(io::Result<()>)>(
self,
f: F,
) -> AutoFlushDecoder<'a, W, F> {
AutoFlushDecoder::new(self, f)
}
crate::decoder_common!(writer);
}
impl<W: Write> Write for Decoder<'_, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.writer.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.writer.flush()
}
}
fn _assert_traits() {
fn _assert_send<T: Send>(_: T) {}
_assert_send(Decoder::new(Vec::new()));
_assert_send(Encoder::new(Vec::new(), 1));
_assert_send(Decoder::new(Vec::new()).unwrap().auto_flush());
_assert_send(Encoder::new(Vec::new(), 1).unwrap().auto_finish());
}