macro_rules! impl_id {
($name:ident, $tp:ty) => {
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Default,
serde::Serialize,
serde::Deserialize,
)]
pub(crate) struct $name($tp);
impl $name {
#[inline]
pub(crate) const fn new(index: $tp) -> Self {
$name(index)
}
#[allow(dead_code)]
#[inline]
pub(crate) fn as_usize(&self) -> usize {
self.0 as usize
}
#[allow(dead_code)]
#[inline]
pub(crate) fn id(&self) -> $tp {
self.0
}
}
impl core::ops::Add<$tp> for $name {
type Output = $name;
#[inline]
fn add(self, rhs: $tp) -> Self::Output {
$name(self.0 + rhs)
}
}
impl core::ops::AddAssign<$tp> for $name {
#[inline]
fn add_assign(&mut self, rhs: $tp) {
self.0 = self.0 + rhs;
}
}
impl<T> std::ops::Index<$name> for [T] {
type Output = T;
#[inline]
fn index(&self, index: $name) -> &Self::Output {
&self[index.0 as usize]
}
}
impl<T> std::ops::IndexMut<$name> for [T] {
#[inline]
fn index_mut(&mut self, index: $name) -> &mut T {
&mut self[index.0 as usize]
}
}
impl<T> std::ops::Index<$name> for Vec<T> {
type Output = T;
#[inline]
fn index(&self, index: $name) -> &Self::Output {
&self[index.0 as usize]
}
}
impl<T> std::ops::IndexMut<$name> for Vec<T> {
#[inline]
fn index_mut(&mut self, index: $name) -> &mut T {
&mut self[index.0 as usize]
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<$tp> for $name {
fn from(index: $tp) -> Self {
$name::new(index)
}
}
};
}
pub(crate) type StateIDBase = u32;
impl_id!(StateID, StateIDBase);
impl_id!(StateSetID, StateIDBase);
pub(crate) type CharClassIDBase = u32;
impl_id!(CharClassID, CharClassIDBase);
pub(crate) type PatternIDBase = usize;
impl_id!(PatternID, PatternIDBase);
pub(crate) type TerminalIDBase = u32;
impl_id!(TerminalID, TerminalIDBase);
pub(crate) type ScannerModeIDBase = usize;
impl_id!(ScannerModeID, ScannerModeIDBase);
pub(crate) type StateGroupIDBase = u16;
impl_id!(StateGroupID, StateGroupIDBase);