1#[derive(Debug)]
17pub struct Store<T> {
18 sparse: Vec<u32>,
22 dense: Vec<u32>,
23 values: Vec<T>,
24}
25
26const ABSENT: u32 = u32::MAX;
28
29impl<T> Default for Store<T> {
30 fn default() -> Self {
31 Self::new()
32 }
33}
34
35impl<T> Store<T> {
36 #[must_use]
38 pub const fn new() -> Self {
39 Self {
40 sparse: Vec::new(),
41 dense: Vec::new(),
42 values: Vec::new(),
43 }
44 }
45
46 #[must_use]
48 pub fn len(&self) -> usize {
49 self.values.len()
50 }
51
52 #[must_use]
54 pub fn is_empty(&self) -> bool {
55 self.values.is_empty()
56 }
57
58 #[must_use]
60 pub fn contains(&self, slot: u32) -> bool {
61 self.position(slot).is_some()
62 }
63
64 fn position(&self, slot: u32) -> Option<usize> {
66 match self.sparse.get(slot as usize).copied() {
67 Some(ABSENT) | None => None,
68 Some(position) => Some(position as usize),
69 }
70 }
71
72 #[must_use]
74 pub fn get(&self, slot: u32) -> Option<&T> {
75 self.values.get(self.position(slot)?)
76 }
77
78 pub fn get_mut(&mut self, slot: u32) -> Option<&mut T> {
80 let position = self.position(slot)?;
81 self.values.get_mut(position)
82 }
83
84 pub fn insert(&mut self, slot: u32, value: T) -> Option<T> {
86 if let Some(position) = self.position(slot) {
87 let existing = self.values.get_mut(position)?;
88 return Some(core::mem::replace(existing, value));
89 }
90 let needed = (slot as usize).checked_add(1)?;
91 if self.sparse.len() < needed {
92 self.sparse.resize(needed, ABSENT);
93 }
94 let position = u32::try_from(self.dense.len()).ok()?;
95 if let Some(entry) = self.sparse.get_mut(slot as usize) {
96 *entry = position;
97 }
98 self.dense.push(slot);
99 self.values.push(value);
100 None
101 }
102
103 pub fn remove(&mut self, slot: u32) -> Option<T> {
109 let position = self.position(slot)?;
110 let last = self.dense.len().checked_sub(1)?;
111 self.dense.swap(position, last);
112 self.values.swap(position, last);
113
114 if let Some(moved) = self.dense.get(position).copied()
118 && position != last
119 && let Some(entry) = self.sparse.get_mut(moved as usize)
120 {
121 *entry = u32::try_from(position).unwrap_or(ABSENT);
122 }
123 if let Some(entry) = self.sparse.get_mut(slot as usize) {
124 *entry = ABSENT;
125 }
126 self.dense.pop();
127 self.values.pop()
128 }
129
130 pub fn iter(&self) -> impl Iterator<Item = (u32, &T)> + '_ {
139 self.sparse
140 .iter()
141 .enumerate()
142 .filter(|(_, position)| **position != ABSENT)
143 .filter_map(move |(slot, position)| {
144 let value = self.values.get(*position as usize)?;
145 Some((u32::try_from(slot).ok()?, value))
146 })
147 }
148
149 pub(crate) fn scan_len(&self) -> usize {
159 self.sparse.len()
160 }
161
162 pub fn for_each_mut(&mut self, mut visit: impl FnMut(u32, &mut T)) {
169 let order: Vec<(u32, u32)> = self
170 .sparse
171 .iter()
172 .enumerate()
173 .filter(|(_, position)| **position != ABSENT)
174 .filter_map(|(slot, position)| Some((u32::try_from(slot).ok()?, *position)))
175 .collect();
176 for (slot, position) in order {
177 if let Some(value) = self.values.get_mut(position as usize) {
178 visit(slot, value);
179 }
180 }
181 }
182
183 pub fn iter_unordered(&self) -> impl Iterator<Item = &T> + '_ {
191 self.values.iter()
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn a_new_store_is_empty() {
201 let store: Store<u32> = Store::new();
202 assert!(store.is_empty());
203 assert_eq!(store.len(), 0);
204 assert!(store.get(0).is_none());
205 assert!(!store.contains(0));
206 }
207
208 #[test]
211 fn default_and_new_agree() {
212 let made: Store<u32> = Store::default();
213 assert!(made.is_empty());
214 assert_eq!(made.len(), Store::<u32>::new().len());
215 }
216
217 #[test]
218 fn insert_then_get_returns_the_value() {
219 let mut store = Store::new();
220 assert!(store.insert(3, "three").is_none());
221 assert_eq!(store.get(3), Some(&"three"));
222 assert!(store.contains(3));
223 assert_eq!(store.len(), 1);
224 assert!(!store.contains(0));
226 }
227
228 #[test]
229 fn inserting_twice_replaces_and_returns_the_old_value() {
230 let mut store = Store::new();
231 store.insert(1, 10);
232 assert_eq!(store.insert(1, 20), Some(10));
233 assert_eq!(store.get(1), Some(&20));
234 assert_eq!(store.len(), 1, "replacing must not grow the store");
235 }
236
237 #[test]
238 fn get_mut_edits_in_place() {
239 let mut store = Store::new();
240 store.insert(2, 5);
241 if let Some(value) = store.get_mut(2) {
242 *value += 1;
243 }
244 assert_eq!(store.get(2), Some(&6));
245 assert!(store.get_mut(9).is_none());
246 }
247
248 #[test]
252 fn removing_from_the_middle_keeps_every_other_lookup_correct() {
253 let mut store = Store::new();
254 for slot in 0..5 {
255 store.insert(slot, slot * 100);
256 }
257 assert_eq!(store.remove(1), Some(100));
258 assert_eq!(store.len(), 4);
259 assert!(!store.contains(1));
260 for slot in [0u32, 2, 3, 4] {
261 assert_eq!(store.get(slot), Some(&(slot * 100)), "slot {slot}");
262 }
263 }
264
265 #[test]
266 fn removing_the_last_element_is_also_correct() {
267 let mut store = Store::new();
268 store.insert(0, 'a');
269 store.insert(1, 'b');
270 assert_eq!(store.remove(1), Some('b'));
271 assert_eq!(store.get(0), Some(&'a'));
272 assert!(!store.contains(1));
273 assert_eq!(store.remove(0), Some('a'));
274 assert!(store.is_empty());
275 }
276
277 #[test]
278 fn removing_what_is_not_there_returns_nothing() {
279 let mut store: Store<u8> = Store::new();
280 assert!(store.remove(7).is_none());
281 store.insert(0, 1);
282 assert!(store.remove(7).is_none());
283 assert_eq!(store.len(), 1);
284 }
285
286 #[test]
290 fn iteration_is_by_slot_whatever_the_churn() {
291 let mut store = Store::new();
292 for slot in [5u32, 1, 9, 3, 7] {
293 store.insert(slot, slot);
294 }
295 store.remove(3);
296 store.insert(2, 2);
297 store.remove(9);
298
299 let seen: Vec<u32> = store.iter().map(|(slot, _)| slot).collect();
300 assert_eq!(seen, vec![1, 2, 5, 7]);
301
302 let dense: Vec<u32> = store.iter_unordered().copied().collect();
305 assert_ne!(
306 dense, seen,
307 "dense order happened to match; pick harsher churn"
308 );
309 }
310
311 #[test]
312 fn for_each_mut_visits_in_slot_order_and_can_edit() {
313 let mut store = Store::new();
314 for slot in [4u32, 0, 2] {
315 store.insert(slot, slot);
316 }
317 let mut order = Vec::new();
318 store.for_each_mut(|slot, value| {
319 order.push(slot);
320 *value += 1;
321 });
322 assert_eq!(order, vec![0, 2, 4]);
323 assert_eq!(store.get(0), Some(&1));
324 assert_eq!(store.get(4), Some(&5));
325 }
326
327 #[test]
328 fn the_store_survives_a_long_churn() {
329 let mut store = Store::new();
330 for round in 0..50u32 {
331 for slot in 0..20u32 {
332 store.insert(slot, round * 100 + slot);
333 }
334 for slot in (0..20u32).step_by(3) {
335 store.remove(slot);
336 }
337 }
338 let seen: Vec<u32> = store.iter().map(|(slot, _)| slot).collect();
339 let expected: Vec<u32> = (0..20).filter(|slot| slot % 3 != 0).collect();
340 assert_eq!(seen, expected);
341 assert_eq!(store.len(), expected.len());
342 }
343}