zrip-encode 0.8.5

zstd encoder for zrip (internal crate)
Documentation
#![forbid(unsafe_code)]

use zrip_core::error::CompressError;

#[cfg(feature = "alloc")]
use alloc::vec::Vec;

pub(crate) trait OutputSink {
    fn push(&mut self, byte: u8) -> Result<(), CompressError>;
    fn extend_from_slice(&mut self, data: &[u8]) -> Result<(), CompressError>;
}

#[cfg(feature = "alloc")]
impl OutputSink for Vec<u8> {
    #[inline]
    fn push(&mut self, byte: u8) -> Result<(), CompressError> {
        Vec::push(self, byte);
        Ok(())
    }

    #[inline]
    fn extend_from_slice(&mut self, data: &[u8]) -> Result<(), CompressError> {
        Vec::extend_from_slice(self, data);
        Ok(())
    }
}

pub(crate) struct SliceSink<'a> {
    output: &'a mut [u8],
    pos: usize,
}

impl<'a> SliceSink<'a> {
    #[inline]
    pub(crate) fn new(output: &'a mut [u8]) -> Self {
        Self { output, pos: 0 }
    }

    #[inline]
    pub(crate) fn pos(&self) -> usize {
        self.pos
    }
}

impl OutputSink for SliceSink<'_> {
    #[inline]
    fn push(&mut self, byte: u8) -> Result<(), CompressError> {
        if self.pos >= self.output.len() {
            return Err(CompressError::OutputTooSmall);
        }
        self.output[self.pos] = byte;
        self.pos += 1;
        Ok(())
    }

    #[inline]
    fn extend_from_slice(&mut self, data: &[u8]) -> Result<(), CompressError> {
        let end = self
            .pos
            .checked_add(data.len())
            .ok_or(CompressError::OutputTooSmall)?;
        if end > self.output.len() {
            return Err(CompressError::OutputTooSmall);
        }
        self.output[self.pos..end].copy_from_slice(data);
        self.pos = end;
        Ok(())
    }
}