use crate::{Checkpoint, Idx, IterIndexed, IterIndexedMut};
pub struct Arena<T> {
items: Vec<T>,
}
impl<T> Arena<T> {
#[must_use]
pub const fn new() -> Self {
Self { items: Vec::new() }
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
items: Vec::with_capacity(capacity),
}
}
pub fn alloc(&mut self, value: T) -> Idx<T> {
let index = self.items.len();
self.items.push(value);
Idx::from_raw(index)
}
#[must_use]
pub fn get(&self, idx: Idx<T>) -> &T {
&self.items[idx.into_raw()]
}
#[must_use]
pub fn get_mut(&mut self, idx: Idx<T>) -> &mut T {
&mut self.items[idx.into_raw()]
}
#[must_use]
pub const fn len(&self) -> usize {
self.items.len()
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.items.is_empty()
}
#[must_use]
pub const fn capacity(&self) -> usize {
self.items.capacity()
}
#[must_use]
pub const fn checkpoint(&self) -> Checkpoint<T> {
Checkpoint::from_len(self.items.len())
}
pub fn rollback(&mut self, cp: Checkpoint<T>) {
assert!(
cp.len() <= self.items.len(),
"checkpoint {} beyond current length {}",
cp.len(),
self.items.len(),
);
self.items.truncate(cp.len());
}
pub fn reset(&mut self) {
self.items.clear();
}
pub fn iter(&self) -> std::slice::Iter<'_, T> {
self.items.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, T> {
self.items.iter_mut()
}
pub fn alloc_extend(&mut self, iter: impl IntoIterator<Item = T>) -> Option<Idx<T>> {
let start = self.items.len();
self.items.extend(iter);
if self.items.len() > start {
Some(Idx::from_raw(start))
} else {
None
}
}
#[must_use]
pub const fn is_valid(&self, idx: Idx<T>) -> bool {
idx.into_raw() < self.items.len()
}
#[must_use]
pub fn try_get(&self, idx: Idx<T>) -> Option<&T> {
self.items.get(idx.into_raw())
}
#[must_use]
pub fn try_get_mut(&mut self, idx: Idx<T>) -> Option<&mut T> {
self.items.get_mut(idx.into_raw())
}
pub fn drain(&mut self) -> std::vec::Drain<'_, T> {
self.items.drain(..)
}
#[must_use]
pub fn iter_indexed(&self) -> IterIndexed<'_, T> {
IterIndexed::new(self.items.iter().enumerate())
}
pub fn iter_indexed_mut(&mut self) -> IterIndexedMut<'_, T> {
IterIndexedMut::new(self.items.iter_mut().enumerate())
}
pub fn reserve(&mut self, additional: usize) {
self.items.reserve(additional);
}
pub fn shrink_to_fit(&mut self) {
self.items.shrink_to_fit();
}
}
impl<T> Default for Arena<T> {
fn default() -> Self {
Self::new()
}
}
impl<T> std::ops::Index<Idx<T>> for Arena<T> {
type Output = T;
fn index(&self, idx: Idx<T>) -> &T {
self.get(idx)
}
}
impl<T> std::ops::IndexMut<Idx<T>> for Arena<T> {
fn index_mut(&mut self, idx: Idx<T>) -> &mut T {
self.get_mut(idx)
}
}
impl<'a, T> IntoIterator for &'a Arena<T> {
type Item = &'a T;
type IntoIter = std::slice::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut Arena<T> {
type Item = &'a mut T;
type IntoIter = std::slice::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> Extend<T> for Arena<T> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
self.items.extend(iter);
}
}
impl<T> std::iter::FromIterator<T> for Arena<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
Self {
items: iter.into_iter().collect(),
}
}
}
impl<T> IntoIterator for Arena<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}