#[macro_export]
macro_rules! from_bytes {
($($name:ident: $from:ident),*) => {
$(
#[inline]
pub fn $name(raw: Vec<u8>) -> Self {
let len = raw.len();
assert!(len != 0, "cannot convert empty bytes to length");
match len {
1 => {
let mut bytes = [0; 1];
bytes.copy_from_slice(&raw);
SmallLength::Byte(u8::$from(bytes))
},
2 => {
let mut bytes = [0; 2];
bytes.copy_from_slice(&raw);
SmallLength::Word(u16::$from(bytes))
},
4 => {
let mut bytes = [0; 4];
bytes.copy_from_slice(&raw);
SmallLength::Double(u32::$from(bytes))
},
8 => {
let mut bytes = [0; 8];
bytes.copy_from_slice(&raw);
SmallLength::Quad(u64::$from(bytes))
},
_ => panic!("invalid byte length: {}", len),
}
}
)*
};
}
#[macro_export]
macro_rules! to_bytes {
($($name:ident: $to:ident),*) => {
$(
#[inline]
pub fn $name(&self) -> Vec<u8> {
match self {
SmallLength::Byte(v) => {
v.$to().to_vec()
},
SmallLength::Word(v) => {
v.$to().to_vec()
},
SmallLength::Double(v) => {
v.$to().to_vec()
},
SmallLength::Quad(v) => {
v.$to().to_vec()
},
}
}
)*
};
}
#[macro_export]
macro_rules! from_length_bytes {
($($method:ident: $impl_method:ident),*) => {
$(
#[inline]
pub fn $method(bytes: Vec<u8>) -> Self {
SmallLength::$impl_method(bytes).into()
}
)*
};
}
#[macro_export]
macro_rules! to_length_bytes {
($($method:ident: $impl_method:ident),*) => {
$(
#[inline]
pub fn $method(&self) -> Vec<u8> {
let s: SmallLength = self.index.into();
s.$impl_method()
}
)*
};
}
#[macro_export]
macro_rules! length_not_expr {
($($type:ident),*) => {
$(
impl std::ops::Not for $type {
type Output = Self;
#[inline]
fn not(self) -> Self::Output {
(!self.index()).into()
}
}
)*
};
}
#[macro_export]
macro_rules! length_bin_expr {
($type:ident; $($name:ident: $method:ident($op:tt)),*) => {
$(
impl $name<$type> for usize {
type Output = $type;
#[inline]
#[deny(arithmetic_overflow)]
fn $method(self, rhs: $type) -> Self::Output {
(self $op rhs.index()).into()
}
}
impl $name<usize> for $type {
type Output = $type;
#[inline]
#[deny(arithmetic_overflow)]
fn $method(self, rhs: usize) -> Self::Output {
(self.index() $op rhs).into()
}
}
impl $name<$type> for $type {
type Output = $type;
#[inline]
#[deny(arithmetic_overflow)]
fn $method(self, rhs: $type) -> Self::Output {
(self.index() $op rhs.index()).into()
}
}
)*
};
}
#[macro_export]
macro_rules! to_primitive {
($($t:ty)*) => {
$(
impl From<SmallLength> for $t {
#[inline]
fn from(v: SmallLength) -> Self {
match v {
SmallLength::Byte(v) => {
v as $t
}
SmallLength::Word(v) => {
if v <= (<$t>::MAX as u16) {
v as $t
} else {
panic!("word overflow: {} -> {}", v, stringify!($t))
}
},
SmallLength::Double(v) => {
if v <= (<$t>::MAX as u32) {
v as $t
} else {
panic!("double overflow: {} -> {}", v, stringify!($t))
}
},
SmallLength::Quad(v) => {
if v <= (<$t>::MAX as u64) {
v as $t
} else {
panic!("quad overflow: {} -> {}", v, stringify!($t))
}
},
}
}
}
)*
};
}
#[macro_export]
macro_rules! impl_len {
($($t:ty)*) => {
$(
impl Len for $t {
#[inline]
fn length(&self) -> Length {
self.len().into()
}
}
)*
};
}
#[macro_export]
macro_rules! impl_len_lifetime {
($($t:ty),*) => {
$(
impl <'l> Len for $t {
#[inline]
fn length(&self) -> Length {
self.len().into()
}
}
)*
};
}
#[macro_export]
macro_rules! impl_len_generic {
($($t:ty)*) => {
$(
impl <T> Len for $t {
#[inline]
fn length(&self) -> Length {
self.len().into()
}
}
)*
};
}
#[macro_export]
macro_rules! impl_len_kv {
($($t:ty)*) => {
$(
impl <K, V> Len for $t {
#[inline]
fn length(&self) -> Length {
self.len().into()
}
}
)*
};
}
#[macro_export]
macro_rules! from_primitive {
($($ty:ty { $uty:ty })*) => {
$(
impl From<$ty> for SmallLength {
#[inline]
fn from(v: $ty) -> Self {
if v < 0 {
panic!("cannot convert negative value to length")
}
(v as $uty).into()
}
}
)*
};
}