use std::slice::{Iter, IterMut};
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct ArenaId(pub usize);
#[derive(Debug, Clone)]
pub struct Arena<T> {
arena: Vec<T>,
}
impl<T> Arena<T> {
pub fn new() -> Self {
Self { arena: Vec::new() }
}
pub fn len(&self) -> usize {
self.arena.len()
}
pub fn is_empty(&self) -> bool {
self.arena.is_empty()
}
pub fn get(&self, id: ArenaId) -> Option<&T> {
self.arena.get(id.0)
}
pub fn get_mut(&mut self, id: ArenaId) -> Option<&mut T> {
self.arena.get_mut(id.0)
}
pub fn iter(&self) -> Iter<'_, T> {
self.arena.iter()
}
pub fn iter_mut(&mut self) -> IterMut<T> {
self.arena.iter_mut()
}
pub fn is_valid(&self, id: ArenaId) -> bool {
id.0 < self.arena.len()
}
pub fn is_valid_slice(&self, slice: &[ArenaId]) -> bool {
slice.iter().all(|id| self.is_valid(*id))
}
pub fn push(&mut self, value: T) -> ArenaId {
self.arena.push(value);
ArenaId(self.arena.len() - 1)
}
pub fn enumerate(&self) -> EnumerableArena<'_, T> {
EnumerableArena {
inner: &self,
pos: 0,
}
}
}
pub struct EnumerableArena<'a, T: 'a> {
inner: &'a Arena<T>,
pos: usize,
}
impl<'a, T> Iterator for EnumerableArena<'a, T> {
type Item = (ArenaId, &'a T);
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.inner.arena.len() {
None
} else {
self.pos += 1;
Some((
ArenaId(self.pos - 1),
self.inner.arena.get(self.pos - 1).unwrap(),
))
}
}
}
impl<T> Default for Arena<T> {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn arena_basic() {
let mut arena = Arena::new();
let a = arena.push("Hello!");
let b = arena.push("World");
assert_eq!(a.0, 0);
assert_eq!(b.0, 1);
assert_eq!(arena.len(), 2);
let a_ref = arena.get(a).expect("Failed to get a");
assert_eq!(*a_ref, "Hello!");
{
let b_ref_mut = arena.get_mut(b).expect("Failed to get b");
*b_ref_mut = "Jenkins";
}
assert_eq!(arena.get(b).unwrap(), &"Jenkins");
}
#[test]
fn arena_iterator() {
let mut arena = Arena::new();
arena.push("my first entry");
arena.push("my second entry");
arena.push("my third entry");
let mut iter = arena.iter();
assert_eq!(iter.next(), Some(&"my first entry"));
assert_eq!(iter.next(), Some(&"my second entry"));
assert_eq!(iter.next(), Some(&"my third entry"));
assert_eq!(iter.next(), None);
}
#[test]
fn arena_iterator_mut() {
let mut arena = Arena::new();
arena.push(1);
arena.push(3);
arena.push(-5);
arena.push(7);
for entry in arena.iter_mut() {
*entry = *entry * *entry;
}
let mut iter = arena.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&9));
assert_eq!(iter.next(), Some(&25));
assert_eq!(iter.next(), Some(&49));
}
#[test]
fn arena_enumerate() {
let mut arena = Arena::new();
let a = arena.push(1);
let b = arena.push(3);
let c = arena.push(4);
let d = arena.push(8);
let mut enumerator = arena.enumerate();
assert_eq!(enumerator.next(), Some((a, &1)));
assert_eq!(enumerator.next(), Some((b, &3)));
assert_eq!(enumerator.next(), Some((c, &4)));
assert_eq!(enumerator.next(), Some((d, &8)));
}
}