cjc_data/detcoll/
index_vec.rs1use std::marker::PhantomData;
14
15pub trait Idx: Copy + Eq + std::fmt::Debug {
18 fn from_usize(i: usize) -> Self;
19 fn index(self) -> usize;
20}
21
22#[macro_export]
24macro_rules! det_idx {
25 ($name:ident) => {
26 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
27 pub struct $name(pub u32);
28 impl $crate::detcoll::Idx for $name {
29 #[inline]
30 fn from_usize(i: usize) -> Self {
31 debug_assert!(i <= u32::MAX as usize);
32 Self(i as u32)
33 }
34 #[inline]
35 fn index(self) -> usize {
36 self.0 as usize
37 }
38 }
39 };
40}
41
42#[derive(Debug, Clone)]
43pub struct IndexVec<I: Idx, V> {
44 data: Vec<V>,
45 _marker: PhantomData<I>,
46}
47
48impl<I: Idx, V> Default for IndexVec<I, V> {
49 fn default() -> Self {
50 Self::new()
51 }
52}
53
54impl<I: Idx, V> IndexVec<I, V> {
55 pub fn new() -> Self {
56 Self {
57 data: Vec::new(),
58 _marker: PhantomData,
59 }
60 }
61
62 pub fn with_capacity(cap: usize) -> Self {
63 Self {
64 data: Vec::with_capacity(cap),
65 _marker: PhantomData,
66 }
67 }
68
69 pub fn len(&self) -> usize {
70 self.data.len()
71 }
72
73 pub fn is_empty(&self) -> bool {
74 self.data.is_empty()
75 }
76
77 pub fn push(&mut self, value: V) -> I {
80 let i = self.data.len();
81 self.data.push(value);
82 I::from_usize(i)
83 }
84
85 pub fn get(&self, id: I) -> Option<&V> {
87 self.data.get(id.index())
88 }
89
90 pub fn get_mut(&mut self, id: I) -> Option<&mut V> {
92 self.data.get_mut(id.index())
93 }
94
95 pub fn iter(&self) -> impl Iterator<Item = (I, &V)> + '_ {
97 self.data
98 .iter()
99 .enumerate()
100 .map(|(i, v)| (I::from_usize(i), v))
101 }
102
103 pub fn values(&self) -> impl Iterator<Item = &V> + '_ {
105 self.data.iter()
106 }
107
108 pub fn as_slice(&self) -> &[V] {
110 &self.data
111 }
112}
113
114impl<I: Idx, V> std::ops::Index<I> for IndexVec<I, V> {
115 type Output = V;
116 fn index(&self, id: I) -> &V {
117 &self.data[id.index()]
118 }
119}
120
121impl<I: Idx, V> std::ops::IndexMut<I> for IndexVec<I, V> {
122 fn index_mut(&mut self, id: I) -> &mut V {
123 &mut self.data[id.index()]
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use super::*;
130
131 crate::det_idx!(NodeId);
132
133 #[test]
134 fn push_and_lookup_roundtrip() {
135 let mut iv: IndexVec<NodeId, &'static str> = IndexVec::new();
136 let a = iv.push("alpha");
137 let b = iv.push("beta");
138 let c = iv.push("gamma");
139 assert_eq!(a, NodeId(0));
140 assert_eq!(b, NodeId(1));
141 assert_eq!(c, NodeId(2));
142 assert_eq!(iv[a], "alpha");
143 assert_eq!(iv[b], "beta");
144 assert_eq!(iv[c], "gamma");
145 }
146
147 #[test]
148 fn out_of_range_get_returns_none() {
149 let iv: IndexVec<NodeId, i32> = IndexVec::new();
150 assert!(iv.get(NodeId(0)).is_none());
151 }
152
153 #[test]
154 fn iter_yields_insertion_order() {
155 let mut iv: IndexVec<NodeId, i32> = IndexVec::new();
156 iv.push(10);
157 iv.push(20);
158 iv.push(30);
159 let collected: Vec<i32> = iv.values().copied().collect();
160 assert_eq!(collected, vec![10, 20, 30]);
161 }
162
163 #[test]
164 fn deterministic_under_repeat() {
165 let mut a: IndexVec<NodeId, i32> = IndexVec::new();
166 let mut b: IndexVec<NodeId, i32> = IndexVec::new();
167 for v in [3, 1, 4, 1, 5, 9, 2, 6] {
168 a.push(v);
169 b.push(v);
170 }
171 let av: Vec<i32> = a.values().copied().collect();
172 let bv: Vec<i32> = b.values().copied().collect();
173 assert_eq!(av, bv);
174 }
175}