use super::{Arena, ArenaIndex, Iter, IterMut};
use crate::{map, Map};
use core::{
hash::Hash,
ops::{Index, IndexMut},
};
#[derive(Debug)]
pub struct DedupArena<Idx, T> {
entity2idx: Map<T, Idx>,
entities: Arena<Idx, T>,
}
impl<Idx, T> Default for DedupArena<Idx, T> {
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<Idx, T> PartialEq for DedupArena<Idx, T>
where
T: PartialEq,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.entities.eq(&other.entities)
}
}
impl<Idx, T> Eq for DedupArena<Idx, T> where T: Eq {}
impl<Idx, T> DedupArena<Idx, T> {
#[inline]
pub fn new() -> Self {
Self {
entity2idx: Map::new(),
entities: Arena::new(),
}
}
#[inline]
pub fn len(&self) -> usize {
self.entities.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
pub fn clear(&mut self) {
self.entity2idx.clear();
self.entities.clear();
}
#[inline]
pub fn iter(&self) -> Iter<'_, Idx, T> {
self.entities.iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, Idx, T> {
self.entities.iter_mut()
}
}
impl<Idx, T> DedupArena<Idx, T>
where
Idx: ArenaIndex,
T: Hash + Ord + Clone,
{
pub fn alloc(&mut self, entity: T) -> Idx {
match self.entity2idx.entry(entity.clone()) {
map::Entry::Occupied(entry) => *entry.get(),
map::Entry::Vacant(entry) => {
let index = self.entities.next_index();
self.entities.alloc(entity);
entry.insert(index);
index
}
}
}
#[inline]
pub fn get(&self, index: Idx) -> Option<&T> {
self.entities.get(index)
}
#[inline]
pub fn get_mut(&mut self, index: Idx) -> Option<&mut T> {
self.entities.get_mut(index)
}
}
impl<Idx, T> FromIterator<T> for DedupArena<Idx, T>
where
Idx: ArenaIndex,
T: Hash + Clone + Ord,
{
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
let entities = Arena::from_iter(iter);
let entity2idx = entities
.iter()
.map(|(idx, entity)| (entity.clone(), idx))
.collect::<Map<_, _>>();
Self {
entity2idx,
entities,
}
}
}
impl<'a, Idx, T> IntoIterator for &'a DedupArena<Idx, T>
where
Idx: ArenaIndex,
{
type Item = (Idx, &'a T);
type IntoIter = Iter<'a, Idx, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, Idx, T> IntoIterator for &'a mut DedupArena<Idx, T>
where
Idx: ArenaIndex,
{
type Item = (Idx, &'a mut T);
type IntoIter = IterMut<'a, Idx, T>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<Idx, T> Index<Idx> for DedupArena<Idx, T>
where
Idx: ArenaIndex,
{
type Output = T;
#[inline]
fn index(&self, index: Idx) -> &Self::Output {
&self.entities[index]
}
}
impl<Idx, T> IndexMut<Idx> for DedupArena<Idx, T>
where
Idx: ArenaIndex,
{
#[inline]
fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
&mut self.entities[index]
}
}