use core::hash::Hash; use core::marker::PhantomData; #[derive(Debug, serde::Serialize)] pub struct Id { index: u32, _phantom: PhantomData, } impl Clone for Id { fn clone(&self) -> Self { *self } } impl Copy for Id {} impl PartialEq for Id { fn eq(&self, other: &Self) -> bool { self.index.eq(&other.index) } } impl Eq for Id {} impl Hash for Id { fn hash(&self, h: &mut H) { self.index.hash(h); } } pub struct Arena { store: Vec, } impl Arena { pub fn new() -> Self { Self { store: vec![] } } pub fn alloc_with_id(&mut self, f: impl FnOnce(Id) -> T) -> Id { use std::convert::TryFrom; let id = Id { index: u32::try_from(self.store.len()).expect("Out of capacity!"), _phantom: Default::default(), }; self.store.push(f(id)); id } pub fn iter(&self) -> impl Iterator, &T)> { (0..).map(|index| Id { index, _phantom: Default::default() }).zip(self.store.iter()) } } impl core::ops::Index> for Arena { type Output = T; fn index(&self, id: Id) -> &Self::Output { self.store.index(id.index as usize) } } impl core::ops::IndexMut> for Arena { fn index_mut(&mut self, id: Id) -> &mut Self::Output { self.store.index_mut(id.index as usize) } }