dfir_rs/util/
sparse_vec.rs
1use std::collections::HashMap;
3use std::hash::Hash;
4use std::iter::FusedIterator;
5
6pub struct SparseVec<T> {
8 items: Vec<Option<T>>,
9 item_locs: HashMap<T, Vec<usize>>,
10}
11
12impl<T> Default for SparseVec<T> {
13 fn default() -> Self {
14 SparseVec {
15 items: Vec::default(),
16 item_locs: HashMap::default(),
17 }
18 }
19}
20
21impl<T: Clone + Eq + Hash> SparseVec<T> {
22 pub fn push(&mut self, item: T) {
24 self.items.push(Some(item.clone()));
25 self.item_locs
26 .entry(item)
27 .or_insert(Vec::with_capacity(1))
28 .push(self.items.len() - 1);
29 }
30
31 pub fn delete(&mut self, item: &T) {
33 if let Some(indices) = self.item_locs.get(item) {
34 for index in indices {
35 self.items[*index] = None;
36 }
37 }
38 }
39
40 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> + FusedIterator + Clone {
42 self.items.iter().filter_map(|x| x.as_ref())
43 }
44}
45
46#[cfg(test)]
47mod test {
48 use super::*;
49
50 fn collect<T: Eq + Hash + Clone>(sv: &SparseVec<T>) -> Vec<T> {
51 sv.iter().cloned().collect()
52 }
53
54 #[test]
55 fn basic() {
56 let mut x = SparseVec::default();
57
58 x.push(0);
59 x.push(1);
60 x.push(2);
61
62 x.delete(&1);
63
64 assert_eq!(collect(&x), vec![0, 2]);
65 }
66
67 #[test]
68 fn can_implement_default_on_types_that_dont_implement_default() {
69 struct NoDefault;
70
71 let x = SparseVec::<NoDefault>::default();
72
73 assert_eq!(x.items.len(), 0);
74 assert_eq!(x.item_locs.len(), 0);
75 }
76}