75 lines
1.4 KiB
Rust
75 lines
1.4 KiB
Rust
|
use std::{
|
||
|
fmt::{self, Debug},
|
||
|
hash::Hash,
|
||
|
marker::PhantomData,
|
||
|
};
|
||
|
|
||
|
pub trait IdKind: Debug + Copy + Clone + Hash + PartialEq + Eq + Default {
|
||
|
fn tag() -> &'static str;
|
||
|
}
|
||
|
|
||
|
/// A generalized abstract identifier type of up to 2^32-1 entries.
|
||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
|
||
|
pub struct Id<T>
|
||
|
where T: IdKind
|
||
|
{
|
||
|
idx: u32,
|
||
|
t: PhantomData<T>,
|
||
|
}
|
||
|
|
||
|
impl<T> Id<T>
|
||
|
where T: IdKind
|
||
|
{
|
||
|
fn new(n: u32) -> Self {
|
||
|
Self { idx: n, t: PhantomData }
|
||
|
}
|
||
|
|
||
|
#[allow(dead_code)]
|
||
|
pub fn as_u32(&self) -> u32 {
|
||
|
self.idx
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl<T> fmt::Display for Id<T>
|
||
|
where T: IdKind
|
||
|
{
|
||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||
|
write!(f, "{}:{}", self.idx, T::tag())
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub struct IdStore<T>
|
||
|
where T: IdKind
|
||
|
{
|
||
|
last_idx: u32,
|
||
|
t: PhantomData<T>,
|
||
|
}
|
||
|
|
||
|
impl<T> IdStore<T>
|
||
|
where T: IdKind
|
||
|
{
|
||
|
pub fn new() -> Self {
|
||
|
Self { last_idx: 0, t: PhantomData }
|
||
|
}
|
||
|
|
||
|
pub fn fresh(&mut self) -> Id<T> {
|
||
|
let idx = self.last_idx;
|
||
|
self.last_idx += 1;
|
||
|
Id::new(idx)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
macro_rules! define_id_kind {
|
||
|
($name:ident) => {
|
||
|
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Default)]
|
||
|
pub struct $name;
|
||
|
impl crate::identifier::IdKind for $name {
|
||
|
fn tag() -> &'static str {
|
||
|
stringify!($name)
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
pub(crate) use define_id_kind;
|