use smallvec::SmallVec;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Entry<T> {
sparse_index: usize,
pub value: T,
}
impl<T> Entry<T> {
pub fn index(&self) -> usize {
self.sparse_index
}
}
pub struct SparseSet<T> {
new_index: usize,
sparse: SmallVec<[usize; 32]>,
dense: Vec<Entry<T>>,
}
impl<T> SparseSet<T> {
#[must_use]
pub fn new() -> Self {
Self {
new_index: 0,
sparse: SmallVec::new(),
dense: Vec::new(),
}
}
#[must_use]
pub fn with_capacity(n: usize) -> Self {
Self {
new_index: 0,
sparse: SmallVec::new(),
dense: Vec::with_capacity(n),
}
}
pub fn insert(&mut self, value: T) -> usize {
let dense_index = self.dense.len();
let sparse_index = self.new_index;
self.new_index += 1;
self.dense.push(Entry {
sparse_index,
value,
});
self.sparse.push(dense_index);
return sparse_index;
}
pub fn remove(&mut self, index: usize) -> Option<T> {
if index >= self.sparse.len() {
return None;
}
let dense_index = self.sparse.get(index).copied()?;
if self.dense.get(dense_index).is_none() {
return None;
}
self.sparse[index] = self.dense.len();
Some(self.dense.swap_remove(dense_index).value)
}
#[must_use]
pub fn get(&self, index: usize) -> Option<&T> {
if index >= self.sparse.len() {
return None;
}
let dense_index = self.sparse.get(index).copied()?;
self.dense.get(dense_index).map(|entry| &entry.value)
}
#[must_use]
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index >= self.sparse.len() {
return None;
}
let dense_index = self.sparse.get(index).copied()?;
self.dense
.get_mut(dense_index)
.map(|entry| &mut entry.value)
}
#[must_use]
pub fn iter<'a>(&'a self) -> iter::Iter<'a, T> {
iter::Iter::new(self)
}
#[must_use]
pub fn iter_mut<'a>(&'a mut self) -> iter::IterMut<'a, T> {
iter::IterMut::new(self)
}
}
impl<T> Default for SparseSet<T> {
fn default() -> Self {
Self::new()
}
}
impl<'a, T> IntoIterator for &'a SparseSet<T> {
type Item = &'a Entry<T>;
type IntoIter = iter::Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T> IntoIterator for &'a mut SparseSet<T> {
type Item = &'a mut Entry<T>;
type IntoIter = iter::IterMut<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T> IntoIterator for SparseSet<T> {
type Item = Entry<T>;
type IntoIter = iter::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
iter::IntoIter::new(self)
}
}
#[cfg(feature = "serde")]
impl<T: serde::Serialize> serde::Serialize for SparseSet<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let v = self.dense.iter().map(|e| &e.value).collect::<Vec<_>>();
v.serialize(serializer)
}
}
#[cfg(feature = "serde")]
impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for SparseSet<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let de: Vec<T> = Vec::deserialize(deserializer)?;
let mut s = SparseSet::new();
for e in de {
s.insert(e);
}
Ok(s)
}
}
pub mod iter {
use std::mem;
use super::{Entry, SparseSet};
pub struct Iter<'a, T> {
sparse: &'a SparseSet<T>,
index: usize,
}
impl<'a, T> Iter<'a, T> {
pub(crate) fn new(sparse: &'a SparseSet<T>) -> Self {
Self { sparse, index: 0 }
}
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a Entry<T>;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
self.index += 1;
self.sparse.dense.get(index)
}
}
pub struct IterMut<'a, T> {
sparse: &'a mut SparseSet<T>,
index: usize,
}
impl<'a, T> IterMut<'a, T> {
pub(crate) fn new(sparse: &'a mut SparseSet<T>) -> Self {
Self { sparse, index: 0 }
}
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut Entry<T>;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
self.index += 1;
self.sparse
.dense
.get_mut(index)
.map(|v| unsafe { &mut *(v as *mut Entry<T>) })
}
}
pub struct IntoIter<T> {
sparse: SparseSet<T>,
index: usize,
}
impl<T> IntoIter<T> {
pub(crate) fn new(sparse: SparseSet<T>) -> Self {
Self { sparse, index: 0 }
}
}
impl<T> Iterator for IntoIter<T> {
type Item = Entry<T>;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
if index == self.sparse.dense.len() {
None
} else {
self.index += 1;
let mut entry = unsafe { mem::zeroed() };
mem::swap(&mut self.sparse.dense[index], &mut entry);
Some(entry)
}
}
}
}
#[cfg(test)]
mod tests {
use super::SparseSet;
#[test]
fn insert() {
let mut set = SparseSet::new();
set.insert(1);
let index = set.insert(2);
assert_eq!(set.remove(index), Some(2));
assert_eq!(set.insert(3), 2);
}
#[test]
fn iter() {
let mut set = SparseSet::new();
set.insert("static string");
set.insert("another static string");
let i = set.insert("abcdefghi");
set.remove(i);
assert_eq!(set.insert("hello"), 3);
set.insert("feijfoej");
for entry in set.iter() {
println!("entry #{}: {}", entry.index(), entry.value);
}
println!("{:?}, {:#?}", set.sparse, set.dense);
}
}