| 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() } |
| } |