use std::iter::FusedIterator;
use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::{iter, mem, slice, vec};
use crate::key::{Generation, Key, Reservation};
pub mod key;
#[cfg(test)]
mod tests;
pub struct Arena<K, T> {
entries: Vec<Entry<T>>,
len: usize,
next: usize,
_key: PhantomData<K>,
}
impl<K, T> Clone for Arena<K, T>
where
T: Clone,
{
fn clone(&self) -> Self {
Self {
entries: self.entries.clone(),
len: self.len,
next: self.next,
_key: PhantomData,
}
}
fn clone_from(&mut self, source: &Self) {
self.entries.clone_from(&source.entries);
self.len = source.len;
self.next = source.next;
}
}
impl<K, T> Default for Arena<K, T> {
fn default() -> Self {
Self::new()
}
}
#[derive(Clone)]
struct Entry<T> {
generation: Generation,
slot: Slot<T>,
}
impl<T> Entry<T> {
fn is_occupied(&self) -> bool {
matches!(self.slot, Slot::Occupied(_))
}
fn is_reserved_for<K>(&self, reservation: &Reservation<K>) -> bool {
self.generation == reservation.key.generation
&& matches!(self.slot, Slot::Reserved)
}
}
#[derive(Clone)]
enum Slot<T> {
Occupied(T),
Reserved,
Vecant { next: usize },
}
impl<T> Arena<Key, T> {
pub fn new_with_default() -> Self {
Self { entries: Vec::new(), len: 0, next: 0, _key: PhantomData }
}
}
impl<K, T> Arena<K, T> {
pub fn new() -> Self {
Self { entries: Vec::new(), len: 0, next: 0, _key: PhantomData }
}
pub fn with_capcity(capacity: usize) -> Self {
Self {
entries: Vec::with_capacity(capacity),
len: 0,
next: 0,
_key: PhantomData,
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
impl<K, T> Arena<K, T>
where
K: From<Key>,
Key: From<K>,
{
pub fn contains_key(&self, key: K) -> bool {
let k = Key::from(key);
self.entries
.get(k.index)
.is_some_and(|e| e.generation == k.generation && e.is_occupied())
}
pub fn insert(&mut self, value: T) -> K {
self.len += 1;
let key = self.insert_slot(Slot::Occupied(value));
K::from(key)
}
pub fn reserve(&mut self) -> Reservation<K> {
let key = self.insert_slot(Slot::Reserved);
Reservation::new(key)
}
pub fn claim(&mut self, reservation: Reservation<K>, value: T) -> K {
let key = reservation.key;
let entry = &mut self.entries[key.index];
debug_assert!(entry.is_reserved_for(&reservation));
self.len += 1;
entry.slot = Slot::Occupied(value);
K::from(key)
}
pub fn cancel(&mut self, reservation: Reservation<K>) {
let key = reservation.key;
let entry = &mut self.entries[key.index];
debug_assert!(entry.is_reserved_for(&reservation));
entry.generation = entry.generation.next().unwrap();
entry.slot = Slot::Vecant { next: self.next };
self.next = key.index;
}
fn insert_slot(&mut self, slot: Slot<T>) -> Key {
let index = self.next;
let generation = if index == self.entries.len() {
let generation = Generation::FIRST;
self.entries.push(Entry { generation, slot });
self.next = index + 1;
generation
} else {
self.next = match self.entries.get(index) {
Some(Entry { slot: Slot::Vecant { next }, .. }) => *next,
_ => unreachable!("next should point to a vecant slot"),
};
self.entries[index].slot = slot;
self.entries[index].generation
};
Key { index, generation }
}
pub fn remove(&mut self, key: K) -> Option<T> {
let k = Key::from(key);
let entry = self
.entries
.get_mut(k.index)
.filter(|e| e.generation == k.generation && e.is_occupied())?;
match mem::replace(&mut entry.slot, Slot::Vecant { next: self.next }) {
Slot::Occupied(value) => {
entry.generation = entry.generation.next().unwrap();
self.len -= 1;
self.next = k.index;
Some(value)
}
_ => unreachable!("should be occupied"),
}
}
pub fn get(&self, key: K) -> Option<&T> {
let k = Key::from(key);
let entry = self
.entries
.get(k.index)
.filter(|e| e.generation == k.generation)?;
match entry.slot {
Slot::Occupied(ref value) => Some(value),
_ => None,
}
}
pub fn get_mut(&mut self, key: K) -> Option<&mut T> {
let k = Key::from(key);
let entry = self
.entries
.get_mut(k.index)
.filter(|e| e.generation == k.generation)?;
match entry.slot {
Slot::Occupied(ref mut value) => Some(value),
_ => None,
}
}
}
impl<K, T> Arena<K, T>
where
K: From<Key>,
{
pub fn iter(&self) -> Iter<'_, K, T> {
Iter {
inner: self.entries.iter().enumerate(),
len: self.len,
_key: PhantomData,
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, K, T> {
IterMut {
inner: self.entries.iter_mut().enumerate(),
len: self.len,
_key: PhantomData,
}
}
pub fn keys(&self) -> Keys<'_, K, T> {
Keys {
inner: self.entries.iter().enumerate(),
len: self.len,
_key: PhantomData,
}
}
pub fn values(&self) -> Values<'_, T> {
Values { inner: self.entries.iter(), len: self.len }
}
pub fn values_mut(&mut self) -> ValuesMut<'_, T> {
ValuesMut { inner: self.entries.iter_mut(), len: self.len }
}
pub fn into_values(self) -> IntoValues<T> {
IntoValues { inner: self.entries.into_iter(), len: self.len }
}
}
impl<K, T> Index<K> for Arena<K, T>
where
K: From<Key>,
Key: From<K>,
{
type Output = T;
fn index(&self, key: K) -> &Self::Output {
self.get(key).expect("no entry found for key")
}
}
impl<K, T> IndexMut<K> for Arena<K, T>
where
K: From<Key>,
Key: From<K>,
{
fn index_mut(&mut self, key: K) -> &mut Self::Output {
self.get_mut(key).expect("no entry found for key")
}
}
pub struct Iter<'a, K, T> {
inner: iter::Enumerate<slice::Iter<'a, Entry<T>>>,
len: usize,
_key: PhantomData<K>,
}
impl<'a, K, T> Iterator for Iter<'a, K, T>
where
K: From<Key>,
{
type Item = (K, &'a T);
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next()
{
if let Slot::Occupied(ref value) = entry.slot {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some((K::from(key), value));
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a, K, T> DoubleEndedIterator for Iter<'a, K, T>
where
K: From<Key>,
{
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next_back()
{
if let Slot::Occupied(ref value) = entry.slot {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some((K::from(key), value));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<K, T> ExactSizeIterator for Iter<'_, K, T>
where
K: From<Key>,
{
fn len(&self) -> usize {
self.len
}
}
impl<K, T> FusedIterator for Iter<'_, K, T> where K: From<Key> {}
pub struct IterMut<'a, K, T> {
inner: iter::Enumerate<slice::IterMut<'a, Entry<T>>>,
len: usize,
_key: PhantomData<K>,
}
impl<'a, K, T> Iterator for IterMut<'a, K, T>
where
K: From<Key>,
{
type Item = (K, &'a mut T);
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next()
{
if let Slot::Occupied(ref mut value) = entry.slot {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some((K::from(key), value));
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<'a, K, T> DoubleEndedIterator for IterMut<'a, K, T>
where
K: From<Key>,
{
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next_back()
{
if let Slot::Occupied(ref mut value) = entry.slot {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some((K::from(key), value));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<K, T> ExactSizeIterator for IterMut<'_, K, T>
where
K: From<Key>,
{
fn len(&self) -> usize {
self.len
}
}
impl<K, T> FusedIterator for IterMut<'_, K, T> where K: From<Key> {}
pub struct IntoIter<K, T> {
inner: iter::Enumerate<vec::IntoIter<Entry<T>>>,
len: usize,
_key: PhantomData<K>,
}
impl<K, T> Iterator for IntoIter<K, T>
where
K: From<Key>,
{
type Item = (K, T);
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next()
{
if let Slot::Occupied(value) = entry.slot {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some((K::from(key), value));
}
}
debug_assert_eq!(self.len, 0);
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<K, T> DoubleEndedIterator for IntoIter<K, T>
where
K: From<Key>,
{
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next_back()
{
if let Slot::Occupied(value) = entry.slot {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some((K::from(key), value));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<K, T> ExactSizeIterator for IntoIter<K, T>
where
K: From<Key>,
{
fn len(&self) -> usize {
self.len
}
}
impl<K, T> FusedIterator for IntoIter<K, T> where K: From<Key> {}
impl<'a, K, T> IntoIterator for &'a Arena<K, T>
where
K: From<Key>,
{
type Item = (K, &'a T);
type IntoIter = Iter<'a, K, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, K, T> IntoIterator for &'a mut Arena<K, T>
where
K: From<Key>,
{
type Item = (K, &'a mut T);
type IntoIter = IterMut<'a, K, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<K, T> IntoIterator for Arena<K, T>
where
K: From<Key>,
{
type Item = (K, T);
type IntoIter = IntoIter<K, T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.entries.into_iter().enumerate(),
len: self.len,
_key: PhantomData,
}
}
}
pub struct Keys<'a, K, T> {
inner: iter::Enumerate<slice::Iter<'a, Entry<T>>>,
len: usize,
_key: PhantomData<K>,
}
impl<'a, K, T> Iterator for Keys<'a, K, T>
where
K: From<Key>,
{
type Item = K;
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next()
{
if entry.is_occupied() {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some(K::from(key));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<'a, K, T> DoubleEndedIterator for Keys<'a, K, T>
where
K: From<Key>,
{
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some((index, entry)) = self.inner.next_back()
{
if entry.is_occupied() {
self.len -= 1;
let key = Key { index, generation: entry.generation };
return Some(K::from(key));
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<K, T> ExactSizeIterator for Keys<'_, K, T>
where
K: From<Key>,
{
fn len(&self) -> usize {
self.len
}
}
impl<K, T> FusedIterator for Keys<'_, K, T> where K: From<Key> {}
pub struct Values<'a, T> {
inner: slice::Iter<'a, Entry<T>>,
len: usize,
}
impl<'a, T> Iterator for Values<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some(entry) = self.inner.next()
{
if let Slot::Occupied(ref value) = entry.slot {
self.len -= 1;
return Some(value);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<'a, T> DoubleEndedIterator for Values<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some(entry) = self.inner.next_back()
{
if let Slot::Occupied(ref value) = entry.slot {
self.len -= 1;
return Some(value);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for Values<'_, T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for Values<'_, T> {}
pub struct ValuesMut<'a, T> {
inner: slice::IterMut<'a, Entry<T>>,
len: usize,
}
impl<'a, T> Iterator for ValuesMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some(entry) = self.inner.next()
{
if let Slot::Occupied(ref mut value) = entry.slot {
self.len -= 1;
return Some(value);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<'a, T> DoubleEndedIterator for ValuesMut<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some(entry) = self.inner.next_back()
{
if let Slot::Occupied(ref mut value) = entry.slot {
self.len -= 1;
return Some(value);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for ValuesMut<'_, T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for ValuesMut<'_, T> {}
pub struct IntoValues<T> {
inner: vec::IntoIter<Entry<T>>,
len: usize,
}
impl<T> Iterator for IntoValues<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some(entry) = self.inner.next()
{
if let Slot::Occupied(value) = entry.slot {
self.len -= 1;
return Some(value);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> DoubleEndedIterator for IntoValues<T> {
fn next_back(&mut self) -> Option<Self::Item> {
while self.len != 0
&& let Some(entry) = self.inner.next_back()
{
if let Slot::Occupied(value) = entry.slot {
self.len -= 1;
return Some(value);
}
}
debug_assert_eq!(self.len, 0);
None
}
}
impl<T> ExactSizeIterator for IntoValues<T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> FusedIterator for IntoValues<T> {}