use std::ops::{Deref, DerefMut};
use std::slice;
pub struct SparseSet<T> {
dense: Vec<Entry<T>>,
sparse: Vec<usize>,
}
pub struct Entry<T> {
key: usize,
pub value: T,
}
impl<T> Entry<T> {
pub fn key(&self) -> usize {
self.key
}
pub fn value(&self) -> &T {
&self.value
}
pub fn value_mut(&mut self) -> &mut T {
&mut self.value
}
}
impl<T> SparseSet<T> {
pub fn with_capacity(size: usize) -> Self {
let mut sparse = Vec::with_capacity(size);
unsafe { sparse.set_len(size) }
SparseSet {
dense: Vec::with_capacity(size),
sparse: sparse,
}
}
pub fn len(&self) -> usize {
self.dense.len()
}
pub fn capacity(&self) -> usize {
self.sparse.len()
}
pub fn clear(&mut self) {
self.dense.clear();
}
fn dense_idx(&self, key: usize) -> Option<usize> {
let dense_idx = self.sparse[key];
if dense_idx < self.len() {
let entry = &self.dense[dense_idx];
if entry.key == key {
return Some(dense_idx);
}
}
None
}
pub fn get(&self, key: usize) -> Option<&T> {
if let Some(dense_idx) = self.dense_idx(key) {
Some(&self.dense[dense_idx].value)
} else {
None
}
}
pub fn get_mut(&mut self, key: usize) -> Option<&mut T> {
if let Some(dense_idx) = self.dense_idx(key) {
Some(&mut self.dense[dense_idx].value)
} else {
None
}
}
pub fn contains(&self, key: usize) -> bool {
self.dense_idx(key).is_some()
}
pub fn insert(&mut self, key: usize, value: T) -> bool {
assert!(
key < self.capacity(),
"key ({}) must be under capacity ({})",
key,
self.capacity()
);
if let Some(stored_value) = self.get_mut(key) {
*stored_value = value;
return false;
}
let n = self.dense.len();
self.dense.push(Entry {
key: key,
value: value,
});
self.sparse[key] = n;
true
}
pub fn remove(&mut self, key: usize) -> Option<T> {
if self.contains(key) {
let dense_idx = self.sparse[key];
let r = self.dense.swap_remove(dense_idx).value;
if dense_idx < self.len() {
let swapped_entry = &self.dense[dense_idx];
self.sparse[swapped_entry.key] = dense_idx;
}
self.sparse[key] = self.capacity();
Some(r)
} else {
None
}
}
}
impl<T> Deref for SparseSet<T> {
type Target = [Entry<T>];
fn deref(&self) -> &Self::Target {
&self.dense[..]
}
}
impl<T> DerefMut for SparseSet<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.dense[..]
}
}
impl<T> IntoIterator for SparseSet<T> {
type Item = Entry<T>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.dense.into_iter()
}
}
impl<'a, T> IntoIterator for &'a SparseSet<T> {
type Item = &'a Entry<T>;
type IntoIter = slice::Iter<'a, Entry<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 = slice::IterMut<'a, Entry<T>>;
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
#[test]
fn create() {
let s = SparseSet::<()>::with_capacity(42);
assert_eq!(s.len(), 0);
assert_eq!(s.capacity(), 42);
}
#[test]
fn insert() {
let mut s = SparseSet::with_capacity(42);
s.insert(3, ());
assert_eq!(s.len(), 1);
assert_eq!(s.capacity(), 42);
s.insert(3, ());
assert_eq!(s.len(), 1);
assert_eq!(s.capacity(), 42);
}
#[test]
fn clear() {
let mut s = SparseSet::with_capacity(42);
s.insert(3, ());
assert_eq!(s.len(), 1);
assert_eq!(s.capacity(), 42);
s.clear();
assert_eq!(s.len(), 0);
assert_eq!(s.capacity(), 42);
}
#[test]
fn contains() {
let mut s = SparseSet::with_capacity(5);
s.insert(3, ());
s.insert(1, ());
assert_eq!(s.len(), 2);
assert_eq!(s.capacity(), 5);
assert!(s.contains(0) == false);
assert!(s.contains(1) == true);
assert!(s.contains(2) == false);
assert!(s.contains(3) == true);
assert!(s.contains(4) == false);
}
#[test]
fn remove() {
let mut s = SparseSet::with_capacity(5);
s.insert(3, ());
s.insert(1, ());
assert_eq!(s.len(), 2);
assert_eq!(s.capacity(), 5);
assert!(s.contains(1));
assert!(s.contains(3));
s.remove(3);
assert_eq!(s.len(), 1);
assert_eq!(s.capacity(), 5);
assert!(s.contains(1));
assert!(s.contains(3) == false);
s.remove(3);
assert_eq!(s.len(), 1);
assert_eq!(s.capacity(), 5);
s.remove(1);
assert_eq!(s.len(), 0);
assert_eq!(s.capacity(), 5);
assert!(s.contains(1) == false);
assert!(s.contains(3) == false);
}
#[test]
fn remove2() {
let mut s = SparseSet::with_capacity(20_000);
for i in 1..=10_000 {
s.insert(i, 42);
}
for i in 1..=10_000 {
s.remove(i);
}
}
#[test]
fn remove3() {
let mut s = SparseSet::with_capacity(100);
s.insert(3, 42);
s.insert(2, 42);
s.insert(1, 42);
s.remove(3);
s.remove(2);
s.remove(1);
}
#[test]
fn iter() {
let mut s = SparseSet::with_capacity(5);
s.insert(3, ());
s.insert(1, ());
s.insert(2, ());
s.remove(1);
assert_eq!(s.len(), 2);
let mut i = 0;
let mut total = 0;
for entry in &s {
i += 1;
total += entry.key();
}
assert_eq!(i, 2);
assert_eq!(total, 5);
assert_eq!(s.len(), 2);
}
#[test]
fn iter_mut() {
let mut s = SparseSet::with_capacity(5);
s.insert(1, 11);
s.insert(2, 22);
s.remove(1);
s.insert(4, 44);
assert_eq!(s.len(), 2);
let mut i = 0;
let mut total = 0;
for entry in &mut s {
i += 1;
total += entry.value;
entry.value += 1;
}
assert_eq!(i, 2);
assert_eq!(total, 22 + 44);
let mut i = 0;
let mut total = 0;
for entry in &s {
i += 1;
total += entry.value;
}
assert_eq!(i, 2);
assert_eq!(total, 23 + 45);
}
#[test]
fn into_iter() {
let mut s = SparseSet::with_capacity(5);
s.insert(3, ());
s.insert(1, ());
s.insert(2, ());
assert_eq!(s.len(), 3);
let mut i = 0;
let mut total = 0;
for entry in s {
i += 1;
total += entry.key();
}
assert_eq!(i, 3);
assert_eq!(total, 3 + 1 + 2);
}
#[test]
fn slice() {
let mut s = SparseSet::with_capacity(5);
s.insert(3, ());
s.insert(1, ());
s.insert(2, ());
{
let the_slice: &[Entry<()>] = &s;
let mut i = 0;
let mut total: usize = 0;
for entry in the_slice {
i += 1;
total += entry.key();
}
assert_eq!(i, 3);
assert_eq!(total, 3 + 1 + 2);
}
s.insert(0, ());
{
let the_slice: &mut [Entry<()>] = &mut s;
let mut i = 0;
let mut total: usize = 0;
for entry in the_slice {
i += 1;
total += entry.key();
entry.value = ();
}
assert_eq!(i, 4);
assert_eq!(total, 3 + 1 + 2);
}
}
#[test]
fn get() {
let mut s = SparseSet::with_capacity(5);
s.insert(1, 11);
s.insert(2, 22);
{
let v = s.get(2);
assert!(v.is_some());
let g = s.get(1);
assert!(g.is_some());
}
{
let v = s.get_mut(2);
assert!(v.is_some());
let v = v.unwrap();
*v += 1;
}
assert_eq!(*s.get(1).unwrap(), 11);
assert_eq!(*s.get(2).unwrap(), 23);
}
#[test]
fn slice_indexing() {
let mut s = SparseSet::with_capacity(5);
s.insert(2, ());
s.insert(1, ());
let e = &s[0];
assert_eq!(e.key(), 2);
}