#![allow(dead_code)]
pub type Generation = u32;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArenaHandle {
pub index: usize,
pub generation: Generation,
}
pub struct ObjectArena<T> {
data: Vec<T>,
generation: Generation,
}
impl<T> ObjectArena<T> {
pub fn with_capacity(cap: usize) -> Self {
Self {
data: Vec::with_capacity(cap),
generation: 0,
}
}
pub fn alloc(&mut self, value: T) -> ArenaHandle {
let index = self.data.len();
self.data.push(value);
ArenaHandle {
index,
generation: self.generation,
}
}
pub fn get(&self, handle: ArenaHandle) -> Option<&T> {
if handle.generation == self.generation {
self.data.get(handle.index)
} else {
None
}
}
pub fn len(&self) -> usize {
self.data.len()
}
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
pub fn reset(&mut self) {
self.data.clear();
self.generation = self.generation.wrapping_add(1);
}
pub fn generation(&self) -> Generation {
self.generation
}
}
pub fn new_object_arena<T>(cap: usize) -> ObjectArena<T> {
ObjectArena::with_capacity(cap)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_alloc_and_get() {
let mut arena: ObjectArena<i32> = ObjectArena::with_capacity(8);
let h = arena.alloc(42);
assert_eq!(arena.get(h), Some(&42));
}
#[test]
fn test_reset_invalidates_handles() {
let mut arena: ObjectArena<i32> = ObjectArena::with_capacity(8);
let h = arena.alloc(1);
arena.reset();
assert_eq!(arena.get(h), None);
}
#[test]
fn test_len_after_alloc() {
let mut arena: ObjectArena<u8> = ObjectArena::with_capacity(4);
arena.alloc(1);
arena.alloc(2);
assert_eq!(arena.len(), 2);
}
#[test]
fn test_is_empty_initial() {
let arena: ObjectArena<i32> = ObjectArena::with_capacity(4);
assert!(arena.is_empty());
}
#[test]
fn test_is_empty_after_reset() {
let mut arena: ObjectArena<i32> = ObjectArena::with_capacity(4);
arena.alloc(5);
arena.reset();
assert!(arena.is_empty());
}
#[test]
fn test_generation_increments() {
let mut arena: ObjectArena<i32> = ObjectArena::with_capacity(4);
let g0 = arena.generation();
arena.reset();
assert_eq!(arena.generation(), g0 + 1);
}
#[test]
fn test_multiple_allocs() {
let mut arena: ObjectArena<f32> = ObjectArena::with_capacity(16);
let handles: Vec<_> = (0..8).map(|i| arena.alloc(i as f32)).collect();
for (i, h) in handles.iter().enumerate() {
assert_eq!(arena.get(*h), Some(&(i as f32)));
}
}
#[test]
fn test_new_helper() {
let arena = new_object_arena::<u64>(32);
assert!(arena.is_empty());
}
#[test]
fn test_handle_index() {
let mut arena: ObjectArena<i32> = ObjectArena::with_capacity(4);
let h = arena.alloc(7);
assert_eq!(h.index, 0);
}
}