#[derive(Debug, PartialEq, Eq, Hash)]
pub struct Slot(usize);
impl Slot {
pub fn index(&self) -> usize {
self.0
}
}
pub struct TypedArena<T: Copy> {
slots: Vec<T>,
free: Vec<usize>,
capacity: usize,
reuse_hits: u64,
}
impl<T: Copy> TypedArena<T> {
pub fn with_capacity(capacity: usize) -> Self {
let capacity = capacity.max(1);
Self {
slots: Vec::with_capacity(capacity),
free: Vec::with_capacity(capacity),
capacity,
reuse_hits: 0,
}
}
pub fn alloc(&mut self, value: T) -> Slot {
match self.try_alloc(value) {
Ok(slot) => slot,
Err(_) => panic!(
"TypedArena full: capacity={} len={}",
self.capacity,
self.len()
),
}
}
pub fn try_alloc(&mut self, value: T) -> Result<Slot, T> {
if let Some(idx) = self.free.pop() {
self.slots[idx] = value;
self.reuse_hits += 1;
return Ok(Slot(idx));
}
if self.slots.len() >= self.capacity {
return Err(value);
}
self.slots.push(value);
Ok(Slot(self.slots.len() - 1))
}
pub fn get(&self, slot: &Slot) -> &T {
&self.slots[slot.0]
}
pub fn get_mut(&mut self, slot: &Slot) -> &mut T {
&mut self.slots[slot.0]
}
pub fn free(&mut self, slot: Slot) {
self.free.push(slot.0);
}
pub fn reset(&mut self) {
self.slots.clear();
self.free.clear();
self.reuse_hits = 0;
}
pub fn len(&self) -> usize {
self.slots.len() - self.free.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn reuse_hits(&self) -> u64 {
self.reuse_hits
}
}
#[cfg(test)]
#[path = "typed_tests.rs"]
mod tests;