use std::fmt::{Display, Formatter};
use crate::{from_bytes, from_length_bytes, length_bin_expr, length_not_expr, to_bytes, to_length_bytes};
use std::ops::{Add, BitAnd, BitOr, BitXor, Div, Index, IndexMut, Mul, Rem, Sub};
#[derive(Copy, Clone, Debug, PartialEq, Hash, PartialOrd, Ord, Eq)]
pub struct Length {
pub(crate) index: usize
}
impl Length {
#[inline]
pub fn new(index: usize) -> Length {
Length {
index
}
}
#[inline]
pub fn index(&self) -> usize {
self.index
}
from_length_bytes! { from_le_bytes: from_le_bytes, from_be_bytes: from_be_bytes }
to_length_bytes! { to_le_bytes: to_le_bytes, to_be_bytes: to_be_bytes }
}
impl Display for Length {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.index)
}
}
#[derive(Copy, Clone, Debug, PartialEq, Hash, PartialOrd, Ord, Eq)]
pub enum SmallLength {
Byte(u8),
Word(u16),
Double(u32),
Quad(u64),
}
impl Display for SmallLength {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
SmallLength::Byte(u) => write!(f, "{}", u),
SmallLength::Word(u) => write!(f, "{}", u),
SmallLength::Double(u) => write!(f, "{}", u),
SmallLength::Quad(u) => write!(f, "{}", u),
}
}
}
impl Default for SmallLength {
#[inline]
fn default() -> Self {
SmallLength::Byte(0)
}
}
impl <T> Index<SmallLength> for Vec<T> {
type Output = T;
#[inline]
fn index(&self, index: SmallLength) -> &Self::Output {
&self[index.index()]
}
}
impl <T> Index<Length> for Vec<T> {
type Output = T;
#[inline]
fn index(&self, index: Length) -> &Self::Output {
&self[index.index]
}
}
use std::borrow::BorrowMut;
impl <T> IndexMut<SmallLength> for Vec<T> {
fn index_mut(&mut self, index: SmallLength) -> &mut Self::Output {
self[index.index()].borrow_mut()
}
}
impl <T> IndexMut<Length> for Vec<T> {
fn index_mut(&mut self, index: Length) -> &mut Self::Output {
self[index.index].borrow_mut()
}
}
length_not_expr!(SmallLength, Length);
length_bin_expr! {
SmallLength;
Add: add(+),
Sub: sub(-),
Mul: mul(*),
Div: div(/),
Rem: rem(%),
BitAnd: bitand(&),
BitOr: bitor(|),
BitXor: bitxor(^)
}
length_bin_expr! {
Length;
Add: add(+),
Sub: sub(-),
Mul: mul(*),
Div: div(/),
Rem: rem(%),
BitAnd: bitand(&),
BitOr: bitor(|),
BitXor: bitxor(^)
}
impl SmallLength {
#[inline]
pub fn index(&self) -> usize {
match self {
SmallLength::Byte(v) => *v as usize,
SmallLength::Word(v) => *v as usize,
SmallLength::Double(v) => *v as usize,
SmallLength::Quad(v) => *v as usize,
}
}
}
impl SmallLength {
from_bytes! { from_le_bytes: from_le_bytes, from_be_bytes: from_be_bytes }
to_bytes! { to_le_bytes: to_le_bytes, to_be_bytes: to_be_bytes }
}