1use core::fmt;
32use core::hash::{Hash, Hasher};
33use core::marker::PhantomData;
34use core::sync::atomic::{AtomicU32, Ordering};
35
36static NEXT_SCOPE: AtomicU32 = AtomicU32::new(1);
41
42fn next_scope() -> u32 {
44 NEXT_SCOPE.fetch_add(1, Ordering::Relaxed)
45}
46
47pub const UNSCOPED: u32 = 0;
53
54pub struct Key<T> {
60 index: u32,
61 generation: u32,
62 scope: u32,
63 marker: PhantomData<fn() -> T>,
64}
65
66impl<T> Key<T> {
67 const fn new(index: u32, generation: u32, scope: u32) -> Self {
68 Self {
69 index,
70 generation,
71 scope,
72 marker: PhantomData,
73 }
74 }
75
76 #[must_use]
80 pub const fn scope(self) -> u32 {
81 self.scope
82 }
83
84 #[must_use]
91 pub const fn with_scope(self, scope: u32) -> Self {
92 Self { scope, ..self }
93 }
94
95 #[must_use]
97 pub const fn index(self) -> u32 {
98 self.index
99 }
100
101 #[must_use]
103 pub const fn generation(self) -> u32 {
104 self.generation
105 }
106
107 #[must_use]
119 pub const fn from_parts(index: u32, generation: u32) -> Self {
120 Self::new(index, generation, UNSCOPED)
121 }
122}
123
124impl<T> Clone for Key<T> {
126 fn clone(&self) -> Self {
127 *self
128 }
129}
130impl<T> Copy for Key<T> {}
131impl<T> PartialEq for Key<T> {
132 fn eq(&self, other: &Self) -> bool {
133 self.index == other.index
134 && self.generation == other.generation
135 && self.scope == other.scope
136 }
137}
138impl<T> Eq for Key<T> {}
139impl<T> Hash for Key<T> {
140 fn hash<H: Hasher>(&self, state: &mut H) {
141 self.index.hash(state);
142 self.generation.hash(state);
143 self.scope.hash(state);
144 }
145}
146impl<T> PartialOrd for Key<T> {
147 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
148 Some(self.cmp(other))
149 }
150}
151impl<T> Ord for Key<T> {
152 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
153 (self.scope, self.index, self.generation).cmp(&(other.scope, other.index, other.generation))
154 }
155}
156impl<T> fmt::Debug for Key<T> {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 write!(f, "Key({}v{}@{})", self.index, self.generation, self.scope)
159 }
160}
161
162#[derive(Debug, Clone)]
163enum Slot<T> {
164 Occupied {
165 generation: u32,
166 value: T,
167 },
168 Vacant {
169 generation: u32,
170 next_free: Option<u32>,
171 },
172}
173
174#[derive(Debug, Clone)]
176pub struct Arena<T> {
177 slots: Vec<Slot<T>>,
178 free_head: Option<u32>,
179 len: usize,
180 scope: u32,
184}
185
186impl<T> Default for Arena<T> {
187 fn default() -> Self {
188 Self::new()
189 }
190}
191
192impl<T> Arena<T> {
193 #[must_use]
195 pub const fn new() -> Self {
196 Self {
197 slots: Vec::new(),
198 free_head: None,
199 len: 0,
200 scope: UNSCOPED,
201 }
202 }
203
204 #[must_use]
206 pub fn with_capacity(capacity: usize) -> Self {
207 Self {
208 slots: Vec::with_capacity(capacity),
209 free_head: None,
210 len: 0,
211 scope: UNSCOPED,
212 }
213 }
214
215 #[must_use]
217 pub const fn len(&self) -> usize {
218 self.len
219 }
220
221 #[must_use]
223 pub const fn is_empty(&self) -> bool {
224 self.len == 0
225 }
226
227 #[must_use]
231 pub const fn scope(&self) -> u32 {
232 self.scope
233 }
234
235 #[must_use]
241 pub const fn issued(&self, key: Key<T>) -> bool {
242 key.scope == self.scope
243 }
244
245 #[allow(clippy::expect_used, reason = "documented panic; see # Panics")]
256 pub fn insert(&mut self, value: T) -> Key<T> {
257 if self.scope == UNSCOPED {
258 self.scope = next_scope();
259 }
260 self.len += 1;
261 match self.free_head {
262 Some(index) => {
263 let idx = index as usize;
264 let (generation, next_free) = match &self.slots[idx] {
265 Slot::Vacant {
266 generation,
267 next_free,
268 } => (*generation, *next_free),
269 Slot::Occupied { .. } => unreachable!("free list pointed at an occupied slot"),
270 };
271 self.free_head = next_free;
272 self.slots[idx] = Slot::Occupied { generation, value };
273 Key::new(index, generation, self.scope)
274 }
275 None => {
276 let index = u32::try_from(self.slots.len()).expect("arena exceeded u32::MAX slots");
277 self.slots.push(Slot::Occupied {
278 generation: 0,
279 value,
280 });
281 Key::new(index, 0, self.scope)
282 }
283 }
284 }
285
286 #[must_use]
288 pub fn get(&self, key: Key<T>) -> Option<&T> {
289 if key.scope != self.scope {
290 return None;
291 }
292 match self.slots.get(key.index as usize)? {
293 Slot::Occupied { generation, value } if *generation == key.generation => Some(value),
294 _ => None,
295 }
296 }
297
298 pub fn get_mut(&mut self, key: Key<T>) -> Option<&mut T> {
300 if key.scope != self.scope {
301 return None;
302 }
303 match self.slots.get_mut(key.index as usize)? {
304 Slot::Occupied { generation, value } if *generation == key.generation => Some(value),
305 _ => None,
306 }
307 }
308
309 #[must_use]
311 pub fn contains(&self, key: Key<T>) -> bool {
312 self.get(key).is_some()
313 }
314
315 pub fn remove(&mut self, key: Key<T>) -> Option<T> {
320 if key.scope != self.scope {
321 return None;
322 }
323 let slot = self.slots.get_mut(key.index as usize)?;
324 let generation = match slot {
325 Slot::Occupied { generation, .. } if *generation == key.generation => *generation,
326 _ => return None,
327 };
328 let next = generation.saturating_add(1);
332 let replaced = core::mem::replace(
333 slot,
334 Slot::Vacant {
335 generation: next,
336 next_free: self.free_head,
337 },
338 );
339 if next != u32::MAX {
340 self.free_head = Some(key.index);
341 }
342 self.len -= 1;
343 match replaced {
344 Slot::Occupied { value, .. } => Some(value),
345 Slot::Vacant { .. } => None,
346 }
347 }
348
349 pub fn iter(&self) -> impl Iterator<Item = (Key<T>, &T)> {
351 let scope = self.scope;
352 self.slots
353 .iter()
354 .enumerate()
355 .filter_map(move |(i, slot)| match slot {
356 Slot::Occupied { generation, value } => {
357 #[allow(clippy::cast_possible_truncation)]
359 Some((Key::new(i as u32, *generation, scope), value))
360 }
361 Slot::Vacant { .. } => None,
362 })
363 }
364
365 pub fn iter_mut(&mut self) -> impl Iterator<Item = (Key<T>, &mut T)> {
367 let scope = self.scope;
368 self.slots
369 .iter_mut()
370 .enumerate()
371 .filter_map(move |(i, slot)| match slot {
372 Slot::Occupied { generation, value } =>
373 {
374 #[allow(clippy::cast_possible_truncation)]
375 Some((Key::new(i as u32, *generation, scope), value))
376 }
377 Slot::Vacant { .. } => None,
378 })
379 }
380
381 pub fn values(&self) -> impl Iterator<Item = &T> {
383 self.iter().map(|(_, v)| v)
384 }
385
386 pub fn into_values(self) -> impl Iterator<Item = T> {
391 self.slots.into_iter().filter_map(|slot| match slot {
392 Slot::Occupied { value, .. } => Some(value),
393 Slot::Vacant { .. } => None,
394 })
395 }
396
397 #[must_use]
404 pub fn is_dense(&self) -> bool {
405 self.len == self.slots.len()
406 && self
407 .slots
408 .iter()
409 .all(|slot| matches!(slot, Slot::Occupied { generation: 0, .. }))
410 }
411
412 pub fn clear(&mut self) {
414 let keys: Vec<_> = self.iter().map(|(k, _)| k).collect();
415 for key in keys {
416 self.remove(key);
417 }
418 }
419}
420
421impl<T> core::ops::Index<Key<T>> for Arena<T> {
422 type Output = T;
423
424 #[allow(
428 clippy::expect_used,
429 reason = "Index cannot return Result; see # Panics"
430 )]
431 fn index(&self, key: Key<T>) -> &T {
432 self.get(key).expect("stale arena key")
433 }
434}
435
436impl<T> core::ops::IndexMut<Key<T>> for Arena<T> {
437 #[allow(
441 clippy::expect_used,
442 reason = "IndexMut cannot return Result; see # Panics"
443 )]
444 fn index_mut(&mut self, key: Key<T>) -> &mut T {
445 self.get_mut(key).expect("stale arena key")
446 }
447}
448
449#[cfg(test)]
450#[allow(clippy::unwrap_used)]
451mod tests {
452 use super::*;
453
454 #[test]
455 fn insert_and_get() {
456 let mut a = Arena::new();
457 let k1 = a.insert("one");
458 let k2 = a.insert("two");
459 assert_eq!(a.get(k1), Some(&"one"));
460 assert_eq!(a.get(k2), Some(&"two"));
461 assert_eq!(a.len(), 2);
462 }
463
464 #[test]
465 fn removed_key_goes_stale_and_does_not_alias() {
466 let mut a = Arena::new();
467 let old = a.insert(1_u32);
468 assert_eq!(a.remove(old), Some(1));
469
470 let new = a.insert(2_u32);
472 assert_eq!(new.index(), old.index(), "slot should have been reused");
473 assert_eq!(a.get(new), Some(&2));
474 assert_eq!(a.get(old), None, "stale key aliased a live entry");
475 assert!(!a.contains(old));
476 }
477
478 #[test]
479 fn double_remove_is_none() {
480 let mut a = Arena::new();
481 let k = a.insert(7_u8);
482 assert_eq!(a.remove(k), Some(7));
483 assert_eq!(a.remove(k), None);
484 assert_eq!(a.len(), 0);
485 }
486
487 #[test]
488 fn iteration_skips_holes() {
489 let mut a = Arena::new();
490 let keys: Vec<_> = (0..5_u32).map(|i| a.insert(i)).collect();
491 a.remove(keys[1]);
492 a.remove(keys[3]);
493 let live: Vec<_> = a.values().copied().collect();
494 assert_eq!(live, vec![0, 2, 4]);
495 assert_eq!(a.len(), 3);
496 }
497
498 #[test]
499 fn into_values_yields_values_in_index_order() {
500 let mut a = Arena::new();
501 for i in 0..5_u32 {
502 a.insert(i * 10);
503 }
504 let values: Vec<_> = a.into_values().collect();
505 assert_eq!(values, vec![0, 10, 20, 30, 40]);
506 }
507
508 #[test]
509 fn an_arena_that_never_removed_is_dense() {
510 let mut a = Arena::new();
511 assert!(a.is_dense(), "an empty arena has no holes");
512 for i in 0..4_u32 {
513 a.insert(i);
514 }
515 assert!(a.is_dense());
516 }
517
518 #[test]
519 fn a_removal_makes_an_arena_not_dense() {
520 let mut a = Arena::new();
521 let keys: Vec<_> = (0..3_u32).map(|i| a.insert(i)).collect();
522 a.remove(keys[1]);
523 assert!(!a.is_dense(), "a vacant slot is a hole");
524
525 a.insert(9);
529 assert!(!a.is_dense(), "a recycled slot is off generation zero");
530 }
531
532 #[test]
533 fn clear_invalidates_every_key() {
534 let mut a = Arena::new();
535 let keys: Vec<_> = (0..4_u32).map(|i| a.insert(i)).collect();
536 a.clear();
537 assert!(a.is_empty());
538 assert!(keys.iter().all(|&k| a.get(k).is_none()));
539 }
540
541 #[test]
542 fn keys_are_hashable_and_distinct() {
543 use std::collections::HashSet;
544 let mut a = Arena::new();
545 let set: HashSet<_> = (0..64_u32).map(|i| a.insert(i)).collect();
546 assert_eq!(set.len(), 64);
547 }
548}
549
550#[cfg(test)]
551#[allow(clippy::unwrap_used)]
552mod scope_tests {
553 use super::*;
554
555 #[test]
556 fn a_key_from_one_arena_does_not_resolve_in_another() {
557 let mut a: Arena<&str> = Arena::new();
562 let mut b: Arena<&str> = Arena::new();
563 let here = a.insert("in a");
564 let there = b.insert("in b");
565
566 assert_eq!(a.get(here), Some(&"in a"));
567 assert_eq!(b.get(there), Some(&"in b"));
568 assert_eq!(here.index(), there.index(), "the same slot in both");
569 assert_eq!(a.get(there), None, "a foreign key must not resolve");
570 assert_eq!(b.get(here), None);
571 assert!(!a.issued(there));
572 }
573
574 #[test]
575 fn foreign_keys_are_refused_by_every_route_in() {
576 let mut a: Arena<u32> = Arena::new();
577 let mut b: Arena<u32> = Arena::new();
578 let key = a.insert(1);
579 b.insert(2);
580
581 assert!(!b.contains(key));
582 assert_eq!(b.get_mut(key), None);
583 assert_eq!(b.remove(key), None, "and it must not remove something else");
584 assert_eq!(b.len(), 1, "nothing was taken out");
585 }
586
587 #[test]
588 fn keys_from_different_arenas_are_not_equal_and_do_not_collide() {
589 use std::collections::HashSet;
592 let mut a: Arena<u32> = Arena::new();
593 let mut b: Arena<u32> = Arena::new();
594 let here = a.insert(1);
595 let there = b.insert(2);
596
597 assert_ne!(here, there);
598 let mut set = HashSet::new();
599 set.insert(here);
600 set.insert(there);
601 assert_eq!(set.len(), 2, "two documents' handles collided in a map");
602 }
603
604 #[test]
605 fn an_unscoped_key_resolves_nowhere_until_it_is_bound() {
606 let mut a: Arena<u32> = Arena::new();
609 let real = a.insert(7);
610 let loose: Key<u32> = Key::from_parts(real.index(), real.generation());
611
612 assert_eq!(loose.scope(), UNSCOPED);
613 assert_eq!(a.get(loose), None);
614 assert_eq!(a.get(loose.with_scope(a.scope())), Some(&7));
615 }
616
617 #[test]
618 fn a_clone_answers_to_the_originals_handles() {
619 let mut a: Arena<u32> = Arena::new();
623 let key = a.insert(5);
624 let copy = a.clone();
625 assert_eq!(copy.get(key), Some(&5));
626 }
627
628 #[test]
629 fn an_empty_arena_has_issued_nothing_to_disagree_with() {
630 let empty: Arena<u32> = Arena::new();
634 assert_eq!(empty.scope(), UNSCOPED);
635 let mut used: Arena<u32> = Arena::new();
636 used.insert(1);
637 assert_ne!(used.scope(), UNSCOPED);
638 }
639}