use crate::entity;
use crate::iter;
pub struct Set {
sparse: Vec<entity::Index>,
dense: Vec<entity::Entity>,
}
impl Set {
#[must_use]
#[inline]
pub fn new() -> Self {
Self {
sparse: Vec::new(),
dense: Vec::new(),
}
}
#[must_use]
#[inline]
pub fn len(&self) -> usize {
self.dense.len()
}
#[must_use]
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
#[inline]
pub fn contains(&self, entity: entity::Entity) -> bool {
self.index_of(entity).is_some()
}
#[must_use]
#[inline]
pub fn index_of(&self, entity: entity::Entity) -> Option<usize> {
self.sparse
.get(entity.as_usize())
.filter(|&&i| i != entity::Index::UNINIT)
.map(|&i| i.as_usize())
}
#[inline]
pub fn insert(&mut self, entity: entity::Entity) -> bool {
if self.contains(entity) {
return false;
}
self.dense.push(entity);
let sparse_index = entity.as_usize();
let dense_index = entity::Index::from_usize_truncate(self.dense.len() - 1);
let min_size = sparse_index + 1;
if self.sparse.len() < min_size {
self.sparse.resize(min_size, entity::Index::UNINIT);
}
self.sparse[sparse_index] = dense_index;
true
}
#[inline]
pub fn remove(&mut self, entity: entity::Entity) -> bool {
if let (Some(index), Some(last)) = (self.index_of(entity), self.dense.pop()) {
if last != entity {
self.dense[index] = last;
self.sparse[last.as_usize()] = entity::Index::from_usize_truncate(index);
}
self.sparse[entity.as_usize()] = entity::Index::UNINIT;
true
} else {
false
}
}
#[inline]
pub fn reserve(&mut self, additional: usize) {
self.dense.reserve(additional);
if self.dense.capacity() > self.sparse.len() {
self.sparse
.resize(self.dense.capacity(), entity::Index::UNINIT);
}
}
#[inline]
pub fn iter(&self) -> iter::Iter<'_, entity::Entity> {
self.dense.iter().copied()
}
}
impl<'a> IntoIterator for &'a Set {
type IntoIter = iter::Iter<'a, entity::Entity>;
type Item = entity::Entity;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl Default for Set {
#[inline]
fn default() -> Set {
Set::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::entity::Entity;
#[test]
fn sparse_set_append_then_remove() {
let mut set = Set::new();
set.insert(Entity::from(17));
assert_eq!(set.dense.len(), 1);
assert_eq!(set.sparse.len(), 18);
assert_eq!(set.index_of(Entity::from(17)), Some(0));
set.insert(Entity::from(99));
assert_eq!(set.dense.len(), 2);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(17)), Some(0));
assert_eq!(set.index_of(Entity::from(99)), Some(1));
set.insert(Entity::from(42));
assert_eq!(set.dense.len(), 3);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(17)), Some(0));
assert_eq!(set.index_of(Entity::from(99)), Some(1));
assert_eq!(set.index_of(Entity::from(42)), Some(2));
set.remove(Entity::from(99));
assert_eq!(set.dense.len(), 2);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(17)), Some(0));
assert_eq!(set.index_of(Entity::from(42)), Some(1));
assert_eq!(set.index_of(Entity::from(99)), None);
set.insert(Entity::from(0));
assert_eq!(set.dense.len(), 3);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(17)), Some(0));
assert_eq!(set.index_of(Entity::from(42)), Some(1));
assert_eq!(set.index_of(Entity::from(99)), None);
assert_eq!(set.index_of(Entity::from(0)), Some(2));
set.remove(Entity::from(0));
assert_eq!(set.dense.len(), 2);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(17)), Some(0));
assert_eq!(set.index_of(Entity::from(42)), Some(1));
assert_eq!(set.index_of(Entity::from(99)), None);
assert_eq!(set.index_of(Entity::from(0)), None);
set.remove(Entity::from(17));
assert_eq!(set.dense.len(), 1);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(42)), Some(0));
assert_eq!(set.index_of(Entity::from(17)), None);
assert_eq!(set.index_of(Entity::from(99)), None);
assert_eq!(set.index_of(Entity::from(0)), None);
set.remove(Entity::from(42));
assert_eq!(set.dense.len(), 0);
assert_eq!(set.sparse.len(), 100);
assert_eq!(set.index_of(Entity::from(17)), None);
assert_eq!(set.index_of(Entity::from(99)), None);
assert_eq!(set.index_of(Entity::from(42)), None);
assert_eq!(set.index_of(Entity::from(0)), None);
}
#[test]
fn sparse_set_maximum_range() {
let mut set = Set::new();
for i in 0..256 {
set.insert(Entity::from(i));
}
assert_eq!(set.dense.len(), 256);
assert_eq!(set.sparse.len(), 256);
assert_eq!(set.index_of(Entity::from(0)), Some(0));
assert_eq!(set.index_of(Entity::from(255)), Some(255));
for i in 0..256 {
set.remove(Entity::from(i));
}
assert_eq!(set.dense.len(), 0);
assert_eq!(set.sparse.len(), 256);
assert_eq!(set.index_of(Entity::from(0)), None);
assert_eq!(set.index_of(Entity::from(255)), None);
}
#[test]
fn reserve() {
let mut set = Set::new();
set.insert(Entity::from(50));
assert_eq!(set.dense.len(), 1);
assert!(set.dense.capacity() > 0);
assert_eq!(set.sparse.len(), 51);
let additional = 100;
set.reserve(additional);
assert_eq!(set.dense.len(), 1);
assert!(set.dense.capacity() >= set.dense.len() + additional);
assert_eq!(set.sparse.len(), set.dense.capacity());
let mut set = Set::new();
set.insert(Entity::from(1000));
assert_eq!(set.dense.len(), 1);
assert!(set.dense.capacity() > 0);
let sparse_len = set.sparse.len();
assert_eq!(sparse_len, 1001);
let additional = 100;
set.reserve(additional);
assert_eq!(set.dense.len(), 1);
assert!(set.dense.capacity() >= set.dense.len() + additional);
assert_eq!(set.sparse.len(), sparse_len);
}
#[test]
fn contains() {
let mut set = Set::new();
let e0 = entity::Entity::from(0);
let e1 = entity::Entity::from(1);
let e2 = entity::Entity::from(2);
set.insert(e0);
set.insert(e2);
assert_eq!(set.contains(e0), true);
assert_eq!(set.contains(e1), false);
assert_eq!(set.contains(e2), true);
}
}