use core::error::Error;
use num_primitive::PrimitiveUnsigned;
pub trait Word: PrimitiveUnsigned {
const ZERO: Self;
const ONE: Self;
}
macro_rules! impl_word {
($($t:ty),*) => {
$(
impl Word for $t {
const ZERO: Self = 0;
const ONE: Self = 1;
}
)*
};
}
impl_word!(u8, u16, u32, u64, u128, usize);
pub trait DoubleType {
type DoubleType: Word;
fn as_double(&self) -> Self::DoubleType;
fn as_u64(&self) -> u64;
}
macro_rules! impl_double_type {
($($t:ty => $d:ty),*) => {
$(
impl DoubleType for $t {
type DoubleType = $d;
fn as_double(&self) -> Self::DoubleType {
*self as Self::DoubleType
}
fn as_u64(&self) -> u64 {
*self as u64
}
}
)*
};
}
impl_double_type!(
u8 => u16,
u16 => u32,
u32 => u64,
u64 => u128
);
pub trait WordRead {
type Error: Error + Send + Sync + 'static;
type Word: Word;
fn read_word(&mut self) -> Result<Self::Word, Self::Error>;
}
pub trait WordWrite {
type Error: Error + Send + Sync + 'static;
type Word: Word;
fn write_word(&mut self, word: Self::Word) -> Result<(), Self::Error>;
fn flush(&mut self) -> Result<(), Self::Error>;
}
pub trait WordSeek {
type Error: Error + Send + Sync + 'static;
fn word_pos(&mut self) -> Result<u64, Self::Error>;
fn set_word_pos(&mut self, word_pos: u64) -> Result<(), Self::Error>;
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum WordError {
UnexpectedEof { word_pos: usize },
}
impl core::error::Error for WordError {}
impl core::fmt::Display for WordError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
WordError::UnexpectedEof { word_pos } => {
write!(f, "unexpected end of data at word position {}", word_pos)
}
}
}
}