diff --git a/src/protocol/arena.rs b/src/protocol/arena.rs new file mode 100644 index 0000000000000000000000000000000000000000..e83360611516969e9e1e97dfff8898cea39fb9a3 --- /dev/null +++ b/src/protocol/arena.rs @@ -0,0 +1,57 @@ +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) + } +}