termal 4.2.1

Rust library for fancy colored cli using ansi codes
Documentation
use std::io::{BufRead, Read, Write};

use termal::{
    Result,
    raw::{IoProvider, ValueOrMut, WaitForIn},
};

pub struct BufProvider {
    buf: &'static [&'static [u8]],
    idx: usize,
    pos: usize,
    eof_panic: usize,
}

impl BufProvider {
    pub fn new(buf: &'static [&'static [u8]]) -> Self {
        Self {
            buf,
            idx: 0,
            pos: 0,
            eof_panic: 0,
        }
    }

    pub fn eof_panic(eof_cnt: usize, buf: &'static [&'static [u8]]) -> Self {
        Self {
            buf,
            idx: 0,
            pos: 0,
            eof_panic: eof_cnt + 1,
        }
    }

    pub fn has_data(&self) -> bool {
        self.idx < self.buf.len()
    }

    fn check_eof_panic(&mut self) {
        if self.eof_panic == 1 {
            panic!("Infinite wait.");
        }
        self.eof_panic = self.eof_panic.saturating_sub(1);
    }
}

impl Read for BufProvider {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        if !self.has_data() {
            self.check_eof_panic();
            return Ok(0);
        }

        let len = buf.len().min(self.buf[self.idx].len());
        buf[..len].copy_from_slice(&self.buf[self.idx][..len]);
        self.consume(len);
        Ok(len)
    }
}

impl BufRead for BufProvider {
    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
        if !self.has_data() {
            self.check_eof_panic();
            Ok(&[])
        } else {
            Ok(&self.buf[self.idx][self.pos..])
        }
    }

    fn consume(&mut self, amt: usize) {
        if !self.has_data() {
            return;
        }
        self.pos += amt;
        if self.pos >= self.buf[self.idx].len() {
            self.pos = 0;
            self.idx += 1;
        }
    }
}

impl Write for BufProvider {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        Ok(buf.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

impl WaitForIn for BufProvider {
    fn wait_for_in(&self, _timeout: std::time::Duration) -> Result<bool> {
        Ok(true)
    }
}

impl IoProvider for BufProvider {
    type Out = Self;
    type In = Self;

    fn get_out(&mut self) -> ValueOrMut<'_, Self::Out> {
        ValueOrMut::Mut(self)
    }

    fn get_in(&mut self) -> ValueOrMut<'_, Self::In> {
        ValueOrMut::Mut(self)
    }

    fn is_in_terminal(&self) -> bool {
        true
    }

    fn is_out_raw(&self) -> bool {
        true
    }

    fn is_out_terminal(&self) -> bool {
        true
    }
}