macro_rules! lossless_integer {
(
$(#[$attr:meta])*
$sizet:ident $str_name:literal
pub struct $name:ident ($under:ty)
) => {
$(#[$attr])*
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct $name($under);
impl $name {
#[doc = $str_name]
pub fn new(val: $under) -> Option<Self> {
if <$sizet as core::convert::TryFrom<_>>::try_from(val).is_ok() {
Some($name(val))
} else {
None
}
}
#[doc = $str_name]
pub fn get(self) -> $sizet {
self.0 as $sizet
}
pub fn into_inner(self) -> $under {
self.0
}
}
};
}
macro_rules! integer_mem {
($(#[$attr:meta])* pub struct $name:ident ($under:ty)) => {
lossless_integer!($(#[$attr])*
usize "usize"
pub struct $name ($under));
impl<T> core::ops::Index<$name> for [T] {
type Output = T;
fn index(&self, idx: $name) -> &Self::Output {
&self[idx.get()]
}
}
}
}
macro_rules! integer_diff {
($(#[$attr:meta])* pub struct $name:ident ($under:ty)) => {
lossless_integer!($(#[$attr])*
isize "isize"
pub struct $name ($under));
}
}
integer_mem!(
pub struct Imem8(i8)
);
integer_mem!(
pub struct Umem8(u8)
);
integer_mem!(
pub struct Imem16(i16)
);
integer_mem!(
pub struct Umem16(u16)
);
integer_mem!(
pub struct Imem32(i32)
);
integer_mem!(
pub struct Umem32(u32)
);
integer_mem!(
pub struct Imem64(i64)
);
integer_mem!(
pub struct Umem64(u64)
);
integer_mem!(
pub struct Imem(isize)
);
integer_diff!(
pub struct Idiff8(i8)
);
integer_diff!(
pub struct Udiff8(u8)
);
integer_diff!(
pub struct Idiff16(i16)
);
integer_diff!(
pub struct Udiff16(u16)
);
integer_diff!(
pub struct Idiff32(i32)
);
integer_diff!(
pub struct Udiff32(u32)
);
integer_diff!(
pub struct Idiff64(i64)
);
integer_diff!(
pub struct Udiff64(u64)
);
integer_diff!(
pub struct Udiff(usize)
);