blob: 34c05e7157a4687a82558ab2ce565d8262727fe5 [file] [log] [blame] [edit]
use std::ops::Deref;
use std::slice;
/// A sparse set used for representing ordered NFA states.
///
/// This supports constant time addition and membership testing. Clearing an
/// entire set can also be done in constant time. Iteration yields elements
/// in the order in which they were inserted.
///
/// The data structure is based on: http://research.swtch.com/sparse
/// Note though that we don't actually use unitialized memory. We generally
/// reuse allocations, so the initial allocation cost is bareable. However,
/// its other properties listed above are extremely useful.
#[derive(Clone, Debug)]
pub struct SparseSet {
/// Dense contains the instruction pointers in the order in which they
/// were inserted. Accessing elements >= self.size is illegal.
dense: Vec<usize>,
/// Sparse maps instruction pointers to their location in dense.
///
/// An instruction pointer is in the set if and only if
/// sparse[ip] < size && ip == dense[sparse[ip]].
sparse: Vec<usize>,
/// The number of elements in the set.
size: usize,
}
impl SparseSet {
pub fn new(size: usize) -> SparseSet {
SparseSet {
dense: vec![0; size],
sparse: vec![0; size],
size: 0,
}
}
pub fn len(&self) -> usize {
self.size
}
pub fn is_empty(&self) -> bool {
self.size == 0
}
pub fn capacity(&self) -> usize {
self.dense.len()
}
pub fn insert(&mut self, value: usize) {
let i = self.size;
self.dense[i] = value;
self.sparse[value] = i;
self.size += 1;
}
pub fn contains(&self, value: usize) -> bool {
let i = self.sparse[value];
i < self.size && self.dense[i] == value
}
pub fn clear(&mut self) {
self.size = 0;
}
}
impl Deref for SparseSet {
type Target = [usize];
fn deref(&self) -> &Self::Target {
&self.dense[0..self.size]
}
}
impl<'a> IntoIterator for &'a SparseSet {
type Item = &'a usize;
type IntoIter = slice::Iter<'a, usize>;
fn into_iter(self) -> Self::IntoIter { self.iter() }
}