use core::error::Error;
use core::fmt::{Display, Formatter};
#[cfg(feature = "std")]
use crate::prelude::{delta_tables, gamma_tables, zeta_tables};
use crate::traits::*;
use common_traits::CastableInto;
pub trait Peek<const N: usize> {}
macro_rules! impl_peekable {
($($n:literal),*) => {$(
impl<T: Peek<{$n + 1}>> Peek<$n> for T {}
)*};
}
impl_peekable!(
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
26, 27, 28, 29, 30, 31, 32
);
#[derive(Debug, Clone)]
pub enum CopyError<RE: Error + Send + Sync + 'static, WE: Error + Send + Sync + 'static> {
ReadError(RE),
WriteError(WE),
}
impl<RE: Error + Send + Sync + 'static, WE: Error + Send + Sync + 'static> Display
for CopyError<RE, WE>
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
CopyError::ReadError(e) => write!(f, "Read error while copying: {}", e),
CopyError::WriteError(e) => write!(f, "Write error while copying: {}", e),
}
}
}
impl<RE: Error + Send + Sync + 'static, WE: Error + Send + Sync + 'static> Error
for CopyError<RE, WE>
{
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
CopyError::ReadError(e) => Some(e),
CopyError::WriteError(e) => Some(e),
}
}
}
pub trait BitRead<E: Endianness> {
type Error: Error + Send + Sync + 'static;
type PeekWord: CastableInto<u64>;
fn read_bits(&mut self, n: usize) -> Result<u64, Self::Error>;
fn peek_bits(&mut self, n: usize) -> Result<Self::PeekWord, Self::Error>;
fn skip_bits(&mut self, n: usize) -> Result<(), Self::Error>;
#[doc(hidden)]
fn skip_bits_after_peek(&mut self, n: usize);
fn read_unary(&mut self) -> Result<u64, Self::Error>;
fn copy_to<F: Endianness, W: BitWrite<F>>(
&mut self,
bit_write: &mut W,
mut n: u64,
) -> Result<(), CopyError<Self::Error, W::Error>> {
while n > 0 {
let to_read = core::cmp::min(n, 64) as usize;
let read = self.read_bits(to_read).map_err(CopyError::ReadError)?;
bit_write
.write_bits(read, to_read)
.map_err(CopyError::WriteError)?;
n -= to_read as u64;
}
Ok(())
}
}
pub trait BitWrite<E: Endianness> {
type Error: Error + Send + Sync + 'static;
fn write_bits(&mut self, value: u64, n: usize) -> Result<usize, Self::Error>;
fn write_unary(&mut self, value: u64) -> Result<usize, Self::Error>;
fn flush(&mut self) -> Result<usize, Self::Error>;
fn copy_from<F: Endianness, R: BitRead<F>>(
&mut self,
bit_read: &mut R,
mut n: u64,
) -> Result<(), CopyError<R::Error, Self::Error>> {
while n > 0 {
let to_read = core::cmp::min(n, 64) as usize;
let read = bit_read.read_bits(to_read).map_err(CopyError::ReadError)?;
self.write_bits(read, to_read)
.map_err(CopyError::WriteError)?;
n -= to_read as u64;
}
Ok(())
}
}
pub trait BitSeek {
type Error: Error + Send + Sync + 'static;
fn bit_pos(&mut self) -> Result<u64, Self::Error>;
fn set_bit_pos(&mut self, bit_pos: u64) -> Result<(), Self::Error>;
}
#[cfg(feature = "std")]
pub fn check_tables(peek_bits: usize) {
if peek_bits < gamma_tables::READ_BITS {
eprintln!(
"DANGER: your BitRead can peek at {} bits, but the tables for γ codes use {} bits",
peek_bits,
gamma_tables::READ_BITS
);
}
if peek_bits < delta_tables::READ_BITS {
eprintln!(
"DANGER: your BitRead can peek at {} bits, but the tables for δ codes use {} bits",
peek_bits,
delta_tables::READ_BITS
);
}
if peek_bits < zeta_tables::READ_BITS {
eprintln!(
"DANGER: your BitRead can peek at {} bits, but the tables for ζ₃ codes use {} bits",
peek_bits,
zeta_tables::READ_BITS
);
}
}