use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
pub struct Id<T> {
raw: u32,
marker: PhantomData<fn() -> T>,
}
impl<T> Id<T> {
#[inline]
pub(crate) const fn new(raw: u32) -> Self {
Self {
raw,
marker: PhantomData,
}
}
#[inline]
pub(crate) const fn raw(self) -> u32 {
self.raw
}
}
impl<T> Clone for Id<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for Id<T> {}
impl<T> PartialEq for Id<T> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.raw == other.raw
}
}
impl<T> Eq for Id<T> {}
impl<T> PartialOrd for Id<T> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for Id<T> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.raw.cmp(&other.raw)
}
}
impl<T> Hash for Id<T> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.raw.hash(state);
}
}
impl<T> fmt::Debug for Id<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Id({})", self.raw)
}
}
#[cfg(test)]
mod tests {
extern crate alloc;
use alloc::collections::BTreeSet;
use alloc::format;
use crate::Arena;
#[test]
fn test_id_traits_do_not_depend_on_the_tag() {
struct NotClone;
let mut arena = Arena::<NotClone>::new();
let id = arena.alloc(NotClone);
let copy = id; assert_eq!(id, copy); assert!(format!("{id:?}").starts_with("Id")); }
#[test]
fn test_distinct_allocations_have_distinct_ids() {
let mut arena = Arena::new();
let ids: BTreeSet<_> = (0..16).map(|i| arena.alloc(i)).collect();
assert_eq!(ids.len(), 16); }
#[test]
fn test_id_is_four_bytes_for_any_element() {
assert_eq!(core::mem::size_of::<crate::Id<u8>>(), 4);
assert_eq!(core::mem::size_of::<crate::Id<[u128; 4]>>(), 4);
}
}