blob: 9d48eee6f5d83e6854a8677d2b9b63085034a612 [file] [log] [blame]
Chih-Hung Hsiehe42c5052020-04-16 10:44:21 -07001use std::ops::Deref;
2use std::slice;
3
4/// A sparse set used for representing ordered NFA states.
5///
6/// This supports constant time addition and membership testing. Clearing an
7/// entire set can also be done in constant time. Iteration yields elements
8/// in the order in which they were inserted.
9///
10/// The data structure is based on: http://research.swtch.com/sparse
11/// Note though that we don't actually use uninitialized memory. We generally
12/// reuse allocations, so the initial allocation cost is bareable. However,
13/// its other properties listed above are extremely useful.
14#[derive(Clone, Debug)]
15pub struct SparseSet {
16 /// Dense contains the instruction pointers in the order in which they
17 /// were inserted.
18 dense: Vec<usize>,
19 /// Sparse maps instruction pointers to their location in dense.
20 ///
21 /// An instruction pointer is in the set if and only if
22 /// sparse[ip] < dense.len() && ip == dense[sparse[ip]].
23 sparse: Box<[usize]>,
24}
25
26impl SparseSet {
27 pub fn new(size: usize) -> SparseSet {
28 SparseSet {
29 dense: Vec::with_capacity(size),
30 sparse: vec![0; size].into_boxed_slice(),
31 }
32 }
33
34 pub fn len(&self) -> usize {
35 self.dense.len()
36 }
37
38 pub fn is_empty(&self) -> bool {
39 self.dense.is_empty()
40 }
41
42 pub fn capacity(&self) -> usize {
43 self.dense.capacity()
44 }
45
46 pub fn insert(&mut self, value: usize) {
47 let i = self.len();
48 assert!(i < self.capacity());
49 self.dense.push(value);
50 self.sparse[value] = i;
51 }
52
53 pub fn contains(&self, value: usize) -> bool {
54 let i = self.sparse[value];
55 self.dense.get(i) == Some(&value)
56 }
57
58 pub fn clear(&mut self) {
59 self.dense.clear();
60 }
61}
62
63impl Deref for SparseSet {
64 type Target = [usize];
65
66 fn deref(&self) -> &Self::Target {
67 &self.dense
68 }
69}
70
71impl<'a> IntoIterator for &'a SparseSet {
72 type Item = &'a usize;
73 type IntoIter = slice::Iter<'a, usize>;
74 fn into_iter(self) -> Self::IntoIter {
75 self.iter()
76 }
77}