1use core::fmt;
33use core::hash::{Hash, Hasher};
34use core::marker::PhantomData;
35use core::sync::atomic::{AtomicU32, Ordering};
36
37use crate::collections::FastMap;
38
39static NEXT_SCOPE: AtomicU32 = AtomicU32::new(1);
44
45fn next_scope() -> u32 {
47 NEXT_SCOPE.fetch_add(1, Ordering::Relaxed)
48}
49
50pub const UNSCOPED: u32 = 0;
56
57pub struct Key<T> {
63 index: u32,
64 generation: u32,
65 scope: u32,
66 marker: PhantomData<fn() -> T>,
67}
68
69impl<T> Key<T> {
70 const fn new(index: u32, generation: u32, scope: u32) -> Self {
71 Self {
72 index,
73 generation,
74 scope,
75 marker: PhantomData,
76 }
77 }
78
79 #[must_use]
83 pub const fn scope(self) -> u32 {
84 self.scope
85 }
86
87 #[must_use]
94 pub const fn with_scope(self, scope: u32) -> Self {
95 Self { scope, ..self }
96 }
97
98 #[must_use]
100 pub const fn index(self) -> u32 {
101 self.index
102 }
103
104 #[must_use]
106 pub const fn generation(self) -> u32 {
107 self.generation
108 }
109
110 #[must_use]
122 pub const fn from_parts(index: u32, generation: u32) -> Self {
123 Self::new(index, generation, UNSCOPED)
124 }
125}
126
127impl<T> Clone for Key<T> {
129 fn clone(&self) -> Self {
130 *self
131 }
132}
133impl<T> Copy for Key<T> {}
134impl<T> PartialEq for Key<T> {
135 fn eq(&self, other: &Self) -> bool {
136 self.index == other.index
137 && self.generation == other.generation
138 && self.scope == other.scope
139 }
140}
141impl<T> Eq for Key<T> {}
142impl<T> Hash for Key<T> {
150 fn hash<H: Hasher>(&self, state: &mut H) {
151 self.index.hash(state);
152 self.generation.hash(state);
153 }
154}
155impl<T> PartialOrd for Key<T> {
156 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
157 Some(self.cmp(other))
158 }
159}
160impl<T> Ord for Key<T> {
161 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
162 (self.scope, self.index, self.generation).cmp(&(other.scope, other.index, other.generation))
163 }
164}
165impl<T> fmt::Debug for Key<T> {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(f, "Key({}v{}@{})", self.index, self.generation, self.scope)
168 }
169}
170
171#[derive(Debug, Clone)]
174struct Entry<T> {
175 slot: u32,
176 generation: u32,
177 value: T,
178}
179
180#[derive(Debug, Clone)]
190pub struct Arena<T> {
191 entries: Vec<Entry<T>>,
194 tail: u32,
196 tail_at: u32,
198 scattered: Option<FastMap<u32, u32>>,
200 ordered: bool,
203 free: Vec<(u32, u32)>,
206 next_slot: u32,
208 scope: u32,
212}
213
214impl<T> Default for Arena<T> {
215 fn default() -> Self {
216 Self::new()
217 }
218}
219
220impl<T> Arena<T> {
221 #[must_use]
223 pub const fn new() -> Self {
224 Self {
225 entries: Vec::new(),
226 tail: 0,
227 tail_at: 0,
228 scattered: None,
229 ordered: true,
230 free: Vec::new(),
231 next_slot: 0,
232 scope: UNSCOPED,
233 }
234 }
235
236 #[must_use]
238 pub fn with_capacity(capacity: usize) -> Self {
239 Self {
240 entries: Vec::with_capacity(capacity),
241 ..Self::new()
242 }
243 }
244
245 #[must_use]
247 pub const fn len(&self) -> usize {
248 self.entries.len()
249 }
250
251 #[must_use]
253 pub const fn is_empty(&self) -> bool {
254 self.entries.is_empty()
255 }
256
257 #[must_use]
261 pub const fn scope(&self) -> u32 {
262 self.scope
263 }
264
265 #[must_use]
271 pub const fn issued(&self, key: Key<T>) -> bool {
272 key.scope == self.scope
273 }
274
275 #[must_use]
282 pub fn next_index(&self) -> Option<u32> {
283 self.free.is_empty().then_some(self.next_slot)
284 }
285
286 #[must_use]
288 pub fn key_at(&self, index: u32) -> Option<Key<T>> {
289 let entry = self.entries.get(self.position(index)?)?;
290 (entry.slot == index).then(|| Key::new(index, entry.generation, self.scope))
291 }
292
293 #[allow(clippy::expect_used, reason = "documented panic; see # Panics")]
304 pub fn insert(&mut self, value: T) -> Key<T> {
305 if self.scope == UNSCOPED {
306 self.scope = next_scope();
307 }
308 if let Some((slot, generation)) = self.free.pop() {
309 self.scatter_tail();
310 let at = u32::try_from(self.entries.len()).expect("arena exceeded u32::MAX slots");
311 self.ordered &= self.entries.last().is_none_or(|last| last.slot < slot);
312 self.entries.push(Entry {
313 slot,
314 generation,
315 value,
316 });
317 self.scattered
318 .get_or_insert_with(FastMap::default)
319 .insert(slot, at);
320 self.tail_at = at + 1;
321 return Key::new(slot, generation, self.scope);
322 }
323 let slot = self.next_slot;
324 self.next_slot = slot.checked_add(1).expect("arena exceeded u32::MAX slots");
325 self.entries.push(Entry {
326 slot,
327 generation: 0,
328 value,
329 });
330 Key::new(slot, 0, self.scope)
331 }
332
333 #[inline]
336 fn position(&self, index: u32) -> Option<usize> {
337 if index >= self.tail {
338 Some((index - self.tail) as usize + self.tail_at as usize)
339 } else {
340 self.scattered.as_ref()?.get(&index).map(|&at| at as usize)
341 }
342 }
343
344 #[inline]
346 fn live(&self, key: Key<T>) -> Option<usize> {
347 if key.scope != self.scope {
348 return None;
349 }
350 let at = self.position(key.index)?;
351 let entry = self.entries.get(at)?;
352 (entry.slot == key.index && entry.generation == key.generation).then_some(at)
353 }
354
355 #[must_use]
357 #[inline]
358 pub fn get(&self, key: Key<T>) -> Option<&T> {
359 let at = self.live(key)?;
360 self.entries.get(at).map(|entry| &entry.value)
361 }
362
363 #[inline]
365 pub fn get_mut(&mut self, key: Key<T>) -> Option<&mut T> {
366 let at = self.live(key)?;
367 self.entries.get_mut(at).map(|entry| &mut entry.value)
368 }
369
370 #[must_use]
372 pub fn contains(&self, key: Key<T>) -> bool {
373 self.live(key).is_some()
374 }
375
376 #[allow(
379 clippy::cast_possible_truncation,
380 reason = "`insert` keeps positions within u32"
381 )]
382 fn scatter_tail(&mut self) {
383 let from = self.tail_at as usize;
384 if from < self.entries.len() {
385 let map = self.scattered.get_or_insert_with(FastMap::default);
386 for (at, entry) in self.entries.iter().enumerate().skip(from) {
387 map.insert(entry.slot, at as u32);
388 }
389 }
390 self.tail = self.next_slot;
391 self.tail_at = self.entries.len() as u32;
392 }
393
394 #[allow(
399 clippy::cast_possible_truncation,
400 reason = "`insert` keeps positions within u32"
401 )]
402 pub fn remove(&mut self, key: Key<T>) -> Option<T> {
403 self.live(key)?;
404 self.scatter_tail();
405 let map = self.scattered.as_mut()?;
406 let at = map.remove(&key.index)? as usize;
407 let entry = self.entries.swap_remove(at);
408 if let Some(moved) = self.entries.get(at) {
409 map.insert(moved.slot, at as u32);
410 self.ordered = false;
411 }
412 self.tail_at -= 1;
413 let next = entry.generation.saturating_add(1);
417 if next != u32::MAX {
418 self.free.push((key.index, next));
419 }
420 Some(entry.value)
421 }
422
423 #[allow(
430 clippy::cast_possible_truncation,
431 reason = "`insert` keeps positions within u32"
432 )]
433 pub fn retain(&mut self, mut keep: impl FnMut(Key<T>, &T) -> bool) {
434 let scope = self.scope;
435 self.entries
436 .retain(|entry| keep(Key::new(entry.slot, entry.generation, scope), &entry.value));
437 if !self.ordered {
438 self.entries.sort_unstable_by_key(|entry| entry.slot);
439 self.ordered = true;
440 }
441 let mut tail_len = 0_usize;
444 while tail_len < self.entries.len() {
445 let entry = &self.entries[self.entries.len() - 1 - tail_len];
446 if u64::from(entry.slot) + 1 + tail_len as u64 != u64::from(self.next_slot) {
447 break;
448 }
449 tail_len += 1;
450 }
451 let tail_at = self.entries.len() - tail_len;
452 self.tail = self.next_slot - tail_len as u32;
453 self.tail_at = tail_at as u32;
454 self.scattered = (tail_at > 0).then(|| {
455 self.entries[..tail_at]
456 .iter()
457 .enumerate()
458 .map(|(at, entry)| (entry.slot, at as u32))
459 .collect()
460 });
461 self.entries.shrink_to_fit();
462 }
463
464 fn slot_order(&self) -> impl Iterator<Item = usize> + '_ {
466 let sorted = (!self.ordered).then(|| {
467 let mut order: Vec<usize> = (0..self.entries.len()).collect();
468 order.sort_unstable_by_key(|&at| self.entries[at].slot);
469 order
470 });
471 (0..self.entries.len()).map(move |k| sorted.as_ref().map_or(k, |order| order[k]))
472 }
473
474 #[allow(
476 clippy::cast_possible_truncation,
477 reason = "`insert` keeps positions within u32"
478 )]
479 fn sort(&mut self) {
480 if self.ordered {
481 return;
482 }
483 self.scatter_tail();
484 self.entries.sort_unstable_by_key(|entry| entry.slot);
485 if let Some(map) = &mut self.scattered {
486 for (at, entry) in self.entries.iter().enumerate() {
487 map.insert(entry.slot, at as u32);
488 }
489 }
490 self.ordered = true;
491 }
492
493 pub fn iter(&self) -> impl Iterator<Item = (Key<T>, &T)> {
495 let scope = self.scope;
496 self.slot_order().map(move |at| {
497 let entry = &self.entries[at];
498 (Key::new(entry.slot, entry.generation, scope), &entry.value)
499 })
500 }
501
502 pub fn iter_mut(&mut self) -> impl Iterator<Item = (Key<T>, &mut T)> {
504 self.sort();
505 let scope = self.scope;
506 self.entries.iter_mut().map(move |entry| {
507 (
508 Key::new(entry.slot, entry.generation, scope),
509 &mut entry.value,
510 )
511 })
512 }
513
514 pub fn values(&self) -> impl Iterator<Item = &T> {
516 self.iter().map(|(_, v)| v)
517 }
518
519 pub fn into_values(mut self) -> impl Iterator<Item = T> {
524 self.sort();
525 self.entries.into_iter().map(|entry| entry.value)
526 }
527
528 #[must_use]
534 pub fn is_dense(&self) -> bool {
535 self.entries.len() == self.next_slot as usize
536 && self.entries.iter().all(|entry| entry.generation == 0)
537 }
538
539 pub fn clear(&mut self) {
542 self.retain(|_, _| false);
543 }
544}
545
546impl<T> core::ops::Index<Key<T>> for Arena<T> {
547 type Output = T;
548
549 #[allow(
553 clippy::expect_used,
554 reason = "Index cannot return Result; see # Panics"
555 )]
556 fn index(&self, key: Key<T>) -> &T {
557 self.get(key).expect("stale arena key")
558 }
559}
560
561impl<T> core::ops::IndexMut<Key<T>> for Arena<T> {
562 #[allow(
566 clippy::expect_used,
567 reason = "IndexMut cannot return Result; see # Panics"
568 )]
569 fn index_mut(&mut self, key: Key<T>) -> &mut T {
570 self.get_mut(key).expect("stale arena key")
571 }
572}
573
574#[cfg(test)]
575#[allow(clippy::unwrap_used)]
576mod tests {
577 use super::*;
578
579 #[test]
580 fn insert_and_get() {
581 let mut a = Arena::new();
582 let k1 = a.insert("one");
583 let k2 = a.insert("two");
584 assert_eq!(a.get(k1), Some(&"one"));
585 assert_eq!(a.get(k2), Some(&"two"));
586 assert_eq!(a.len(), 2);
587 }
588
589 #[test]
590 fn removed_key_goes_stale_and_does_not_alias() {
591 let mut a = Arena::new();
592 let old = a.insert(1_u32);
593 assert_eq!(a.remove(old), Some(1));
594
595 let new = a.insert(2_u32);
597 assert_eq!(new.index(), old.index(), "slot should have been reused");
598 assert_eq!(a.get(new), Some(&2));
599 assert_eq!(a.get(old), None, "stale key aliased a live entry");
600 assert!(!a.contains(old));
601 }
602
603 #[test]
604 fn double_remove_is_none() {
605 let mut a = Arena::new();
606 let k = a.insert(7_u8);
607 assert_eq!(a.remove(k), Some(7));
608 assert_eq!(a.remove(k), None);
609 assert_eq!(a.len(), 0);
610 }
611
612 #[test]
613 fn iteration_skips_holes() {
614 let mut a = Arena::new();
615 let keys: Vec<_> = (0..5_u32).map(|i| a.insert(i)).collect();
616 a.remove(keys[1]);
617 a.remove(keys[3]);
618 let live: Vec<_> = a.values().copied().collect();
619 assert_eq!(live, vec![0, 2, 4]);
620 assert_eq!(a.len(), 3);
621 }
622
623 #[test]
624 fn into_values_yields_values_in_index_order() {
625 let mut a = Arena::new();
626 for i in 0..5_u32 {
627 a.insert(i * 10);
628 }
629 let values: Vec<_> = a.into_values().collect();
630 assert_eq!(values, vec![0, 10, 20, 30, 40]);
631 }
632
633 #[test]
634 fn an_arena_that_never_removed_is_dense() {
635 let mut a = Arena::new();
636 assert!(a.is_dense(), "an empty arena has no holes");
637 for i in 0..4_u32 {
638 a.insert(i);
639 }
640 assert!(a.is_dense());
641 }
642
643 #[test]
644 fn a_removal_makes_an_arena_not_dense() {
645 let mut a = Arena::new();
646 let keys: Vec<_> = (0..3_u32).map(|i| a.insert(i)).collect();
647 a.remove(keys[1]);
648 assert!(!a.is_dense(), "a vacant slot is a hole");
649
650 a.insert(9);
654 assert!(!a.is_dense(), "a recycled slot is off generation zero");
655 }
656
657 #[test]
658 fn clear_invalidates_every_key() {
659 let mut a = Arena::new();
660 let keys: Vec<_> = (0..4_u32).map(|i| a.insert(i)).collect();
661 a.clear();
662 assert!(a.is_empty());
663 assert!(keys.iter().all(|&k| a.get(k).is_none()));
664 }
665
666 #[test]
667 fn retained_keys_resolve_and_dropped_slots_are_never_handed_out_again() {
668 let mut a = Arena::new();
669 let keys: Vec<_> = (0..10_u32).map(|i| a.insert(i)).collect();
670 a.retain(|_, v| v % 3 == 0);
671 assert_eq!(a.len(), 4);
672 for (i, key) in keys.iter().enumerate() {
673 let want = (i % 3 == 0).then_some(u32::try_from(i).unwrap());
674 assert_eq!(a.get(*key).copied(), want, "slot {i}");
675 }
676 assert_eq!(a.next_index(), Some(10), "a fresh insert appends");
677 let fresh = a.insert(10);
678 assert_eq!(fresh.index(), 10);
679 assert!(keys.iter().all(|&k| k != fresh));
680 assert_eq!(
681 a.values().copied().collect::<Vec<_>>(),
682 vec![0, 3, 6, 9, 10]
683 );
684 assert_eq!(a.key_at(3), Some(keys[3]));
685 assert_eq!(a.key_at(4), None);
686
687 let copy = a.clone();
690 assert!(keys.iter().all(|&k| copy.get(k) == a.get(k)));
691 assert_eq!(a.remove(keys[6]), Some(6));
692 assert_eq!(a.next_index(), None, "the freed slot is refilled first");
693 let refill = a.insert(60);
694 assert_eq!(refill.index(), 6);
695 assert_eq!(a.get(keys[6]), None);
696 assert_eq!(
697 a.iter().map(|(k, v)| (k.index(), *v)).collect::<Vec<_>>(),
698 vec![(0, 0), (3, 3), (6, 60), (9, 9), (10, 10)]
699 );
700 }
701
702 #[test]
703 fn keys_are_hashable_and_distinct() {
704 use crate::collections::FastSet;
705 let mut a = Arena::new();
706 let set: FastSet<_> = (0..64_u32).map(|i| a.insert(i)).collect();
707 assert_eq!(set.len(), 64);
708 }
709}
710
711#[cfg(test)]
712#[allow(clippy::unwrap_used)]
713mod scope_tests {
714 use super::*;
715
716 #[test]
717 fn a_key_from_one_arena_does_not_resolve_in_another() {
718 let mut a: Arena<&str> = Arena::new();
723 let mut b: Arena<&str> = Arena::new();
724 let here = a.insert("in a");
725 let there = b.insert("in b");
726
727 assert_eq!(a.get(here), Some(&"in a"));
728 assert_eq!(b.get(there), Some(&"in b"));
729 assert_eq!(here.index(), there.index(), "the same slot in both");
730 assert_eq!(a.get(there), None, "a foreign key must not resolve");
731 assert_eq!(b.get(here), None);
732 assert!(!a.issued(there));
733 }
734
735 #[test]
736 fn foreign_keys_are_refused_by_every_route_in() {
737 let mut a: Arena<u32> = Arena::new();
738 let mut b: Arena<u32> = Arena::new();
739 let key = a.insert(1);
740 b.insert(2);
741
742 assert!(!b.contains(key));
743 assert_eq!(b.get_mut(key), None);
744 assert_eq!(b.remove(key), None, "and it must not remove something else");
745 assert_eq!(b.len(), 1, "nothing was taken out");
746 }
747
748 #[test]
749 fn keys_from_different_arenas_are_not_equal_and_do_not_collide() {
750 use crate::collections::FastSet;
753 let mut a: Arena<u32> = Arena::new();
754 let mut b: Arena<u32> = Arena::new();
755 let here = a.insert(1);
756 let there = b.insert(2);
757
758 assert_ne!(here, there);
759 let mut set = FastSet::default();
760 set.insert(here);
761 set.insert(there);
762 assert_eq!(set.len(), 2, "two documents' handles collided in a map");
763 }
764
765 #[test]
766 fn a_table_of_keys_walks_in_the_same_order_whatever_the_scope() {
767 use crate::collections::FastSet;
772 let walk = |skip: usize| {
773 for _ in 0..skip {
774 Arena::<u8>::new().insert(0);
775 }
776 let mut a: Arena<u32> = Arena::new();
777 let set: FastSet<Key<u32>> = (0..200_u32).map(|i| a.insert(i)).collect();
778 set.iter().map(|k| k.index()).collect::<Vec<_>>()
779 };
780 let first = walk(0);
781 for skip in [1, 2, 3, 17, 1000] {
782 assert_eq!(walk(skip), first, "{skip} arenas filled before");
783 }
784 }
785
786 #[test]
787 fn an_unscoped_key_resolves_nowhere_until_it_is_bound() {
788 let mut a: Arena<u32> = Arena::new();
791 let real = a.insert(7);
792 let loose: Key<u32> = Key::from_parts(real.index(), real.generation());
793
794 assert_eq!(loose.scope(), UNSCOPED);
795 assert_eq!(a.get(loose), None);
796 assert_eq!(a.get(loose.with_scope(a.scope())), Some(&7));
797 }
798
799 #[test]
800 fn a_clone_answers_to_the_originals_handles() {
801 let mut a: Arena<u32> = Arena::new();
805 let key = a.insert(5);
806 let copy = a.clone();
807 assert_eq!(copy.get(key), Some(&5));
808 }
809
810 #[test]
811 fn an_empty_arena_has_issued_nothing_to_disagree_with() {
812 let empty: Arena<u32> = Arena::new();
816 assert_eq!(empty.scope(), UNSCOPED);
817 let mut used: Arena<u32> = Arena::new();
818 used.insert(1);
819 assert_ne!(used.scope(), UNSCOPED);
820 }
821}