base91le 0.1.0

little-endian base91 encoding format that supports padding
Documentation
use std::io::{self, Read, Write};

use crate::DecodeError;

#[derive(Debug, Clone, Copy)]
pub(crate) struct Copier {
    cnt: [u8; 16],
    pos: usize,
    write: bool,
}

impl Copier {
    pub(crate) const fn write(&self) -> bool {
        self.write
    }
    pub(crate) const fn is_empty(&self) -> bool {
        // cnt will not be erased
        !self.write && self.pos == 0
    }
    pub(crate) const fn new_decode() -> Self {
        Self {
            cnt: [0; 16],
            pos: 0,
            write: false,
        }
    }
    pub(crate) const fn new_encode() -> Self {
        Self {
            cnt: [0; 16],
            pos: 3,
            write: false,
        }
    }

    pub(crate) fn copy_encoded(
        &mut self,
        reader: &mut (impl Read + ?Sized),
        nth_chunk: usize,
    ) -> io::Result<bool> {
        let remainder = &mut self.cnt[self.pos..];
        let n = reader.read(remainder)?;
        if n == 0 {
            if self.pos == 0 {
                return Ok(true);
            } else {
                return Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    DecodeError::UnpaddedTail {
                        index: self.pos + 16 * nth_chunk,
                    },
                ));
            }
        }
        self.pos += n;
        Ok(self.pos == 16)
    }

    pub(crate) fn copy_from(&mut self, reader: &mut (impl Read + ?Sized)) -> io::Result<bool> {
        let remainder = &mut self.cnt[self.pos..];
        let n = reader.read(remainder)?;
        self.pos += n;
        Ok(self.pos == 16)
    }

    pub(crate) fn copy_to(&mut self, writer: &mut (impl Write + ?Sized)) -> io::Result<bool> {
        let remainder = &self.cnt[self.pos..];
        let n = writer.write(remainder)?;
        self.pos += n;
        Ok(self.pos == 16)
    }

    pub(crate) fn decode(&mut self) -> Result<(), crate::DecodeError> {
        self.write = true;
        let mut buf = [0; 13];
        let len = crate::decode_chunk(&self.cnt, &mut buf)?;
        self.pos = 16 - len;
        self.cnt[self.pos..].copy_from_slice(&buf[..len]);
        Ok(())
    }

    pub(crate) fn encode(&mut self) {
        self.write = true;
        self.cnt = crate::encode_chunk(self.cnt.last_chunk().unwrap());
        self.pos = 0;
    }

    pub(crate) fn encode_tail(&mut self) -> [u8; 16] {
        let res = crate::encode_tail(&self.cnt[3..self.pos]);
        *self = Self::new_encode();
        res
    }
}