async-compression 0.2.0

Adaptors between compression crates and Rust's modern asynchronous IO types.
Documentation
use crate::{codec::Encode, util::PartialBuffer};
use std::{fmt, io::Result};

use brotli2::{
    raw::{CoStatus, Compress, CompressOp},
    CompressParams,
};

pub struct BrotliEncoder {
    compress: Compress,
}

impl BrotliEncoder {
    pub(crate) fn new(params: &CompressParams) -> Self {
        let mut compress = Compress::new();
        compress.set_params(params);
        Self { compress }
    }

    fn encode(
        &mut self,
        input: &mut PartialBuffer<&[u8]>,
        output: &mut PartialBuffer<&mut [u8]>,
        op: CompressOp,
    ) -> Result<CoStatus> {
        let mut in_buf = input.unwritten();
        let mut out_buf = output.unwritten_mut();

        let original_input_len = in_buf.len();
        let original_output_len = out_buf.len();

        let status = self.compress.compress(op, &mut in_buf, &mut out_buf)?;

        let input_len = original_input_len - in_buf.len();
        let output_len = original_output_len - out_buf.len();

        input.advance(input_len);
        output.advance(output_len);

        Ok(status)
    }
}

impl Encode for BrotliEncoder {
    fn encode(
        &mut self,
        input: &mut PartialBuffer<&[u8]>,
        output: &mut PartialBuffer<&mut [u8]>,
    ) -> Result<()> {
        self.encode(input, output, CompressOp::Process).map(drop)
    }

    fn flush(&mut self, output: &mut PartialBuffer<&mut [u8]>) -> Result<bool> {
        match self.encode(&mut PartialBuffer::new(&[][..]), output, CompressOp::Flush)? {
            CoStatus::Unfinished => Ok(false),
            CoStatus::Finished => Ok(true),
        }
    }

    fn finish(&mut self, output: &mut PartialBuffer<&mut [u8]>) -> Result<bool> {
        match self.encode(&mut PartialBuffer::new(&[][..]), output, CompressOp::Finish)? {
            CoStatus::Unfinished => Ok(false),
            CoStatus::Finished => Ok(true),
        }
    }
}

impl fmt::Debug for BrotliEncoder {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("BrotliEncoder")
            .field("compress", &"<no debug>")
            .finish()
    }
}