thunderdome/
arena.rs

1use core::convert::TryInto;
2use core::mem::replace;
3use core::ops;
4
5// Vec is part of the prelude when std is enabled.
6#[cfg(not(feature = "std"))]
7use alloc::vec::Vec;
8
9use crate::free_pointer::FreePointer;
10use crate::generation::Generation;
11use crate::iter::{Drain, IntoIter, Iter, IterMut};
12
13/// Container that can have elements inserted into it and removed from it.
14///
15/// Indices use the [`Index`] type, created by inserting values with [`Arena::insert`].
16#[derive(Debug, Clone)]
17pub struct Arena<T> {
18    storage: Vec<Entry<T>>,
19    len: u32,
20    first_free: Option<FreePointer>,
21}
22
23/// Index type for [`Arena`] that has a generation attached to it.
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
25pub struct Index {
26    pub(crate) slot: u32,
27    pub(crate) generation: Generation,
28}
29
30impl Index {
31    /// Represents an `Index` that is unlikely to be in use. This is useful for
32    /// programs that want to do two-phase initialization in safe Rust. Avoid
33    /// using this value to represent the absence of an `Index`: prefer
34    /// `Option<Index>`.
35    pub const DANGLING: Self = Self {
36        slot: u32::MAX,
37        generation: Generation::DANGLING,
38    };
39
40    /// Convert this `Index` to an equivalent `u64` representation. Mostly
41    /// useful for passing to code outside of Rust.
42    #[allow(clippy::integer_arithmetic)]
43    pub const fn to_bits(self) -> u64 {
44        // This is safe because a `u32` bit-shifted by 32 will still fit in a `u64`.
45        ((self.generation.to_u32() as u64) << 32) | (self.slot as u64)
46    }
47
48    /// Create an `Index` from bits created with `Index::to_bits`.
49    ///
50    /// If this function is called with bits that are not valid for an `Index`,
51    /// returns `None`. This can happen if the encoded generation value is 0,
52    /// for example.
53    ///
54    /// ## Stability
55    /// Bits from `Index` values are guaranteed to be compatible within all
56    /// semver-compatible versions of Thunderdome. That is, using
57    /// `Index::to_bits` in 0.4.0 and `Index::from_bits` in 0.4.2 is guaranteed
58    /// to work.
59    #[allow(clippy::integer_arithmetic)]
60    pub const fn from_bits(bits: u64) -> Option<Self> {
61        // By bit-shifting right by 32, we're undoing the left-shift in `to_bits`
62        // thus this is okay by the same rationale.
63        let generation = match Generation::from_u32((bits >> 32) as u32) {
64            Some(v) => v,
65            None => return None,
66        };
67
68        let slot = bits as u32;
69
70        Some(Self { generation, slot })
71    }
72
73    /// Convert this `Index` into a generation, discarding its slot.
74    pub const fn generation(self) -> u32 {
75        self.generation.to_u32()
76    }
77
78    /// Convert this `Index` into a slot, discarding its generation. Slots describe a
79    /// location in an [`Arena`] and are reused when entries are removed.
80    pub const fn slot(self) -> u32 {
81        self.slot
82    }
83}
84
85#[derive(Debug, Clone)]
86pub(crate) enum Entry<T> {
87    Occupied(OccupiedEntry<T>),
88    Empty(EmptyEntry),
89}
90
91impl<T> Entry<T> {
92    /// Consume the entry, and if it's occupied, return the value.
93    fn into_value(self) -> Option<T> {
94        match self {
95            Entry::Occupied(occupied) => Some(occupied.value),
96            Entry::Empty(_) => None,
97        }
98    }
99
100    fn get_value_mut(&mut self, generation: Generation) -> Option<&mut T> {
101        match self {
102            Entry::Occupied(occupied) if occupied.generation == generation => {
103                Some(&mut occupied.value)
104            }
105            _ => None,
106        }
107    }
108
109    /// If the entry is empty, a reference to it.
110    fn as_empty(&self) -> Option<&EmptyEntry> {
111        match self {
112            Entry::Empty(empty) => Some(empty),
113            Entry::Occupied(_) => None,
114        }
115    }
116
117    /// If the entry is empty, return a mutable reference to it.
118    fn as_empty_mut(&mut self) -> Option<&mut EmptyEntry> {
119        match self {
120            Entry::Empty(empty) => Some(empty),
121            Entry::Occupied(_) => None,
122        }
123    }
124}
125
126#[derive(Debug, Clone)]
127pub(crate) struct OccupiedEntry<T> {
128    pub(crate) generation: Generation,
129    pub(crate) value: T,
130}
131
132#[derive(Debug, Clone, Copy)]
133pub(crate) struct EmptyEntry {
134    pub(crate) generation: Generation,
135    pub(crate) next_free: Option<FreePointer>,
136}
137
138impl<T> Arena<T> {
139    /// Construct an empty arena.
140    pub const fn new() -> Self {
141        Self {
142            storage: Vec::new(),
143            len: 0,
144            first_free: None,
145        }
146    }
147
148    /// Construct an empty arena with space to hold exactly `capacity` elements
149    /// without reallocating.
150    pub fn with_capacity(capacity: usize) -> Self {
151        Self {
152            storage: Vec::with_capacity(capacity),
153            len: 0,
154            first_free: None,
155        }
156    }
157
158    /// Return the number of elements contained in the arena.
159    pub const fn len(&self) -> usize {
160        self.len as usize
161    }
162
163    /// Return the number of elements the arena can hold without allocating,
164    /// including the elements currently in the arena.
165    pub fn capacity(&self) -> usize {
166        self.storage.capacity()
167    }
168
169    /// Returns whether the arena is empty.
170    pub const fn is_empty(&self) -> bool {
171        self.len == 0
172    }
173
174    /// Insert a new value into the arena, returning an index that can be used
175    /// to later retrieve the value.
176    pub fn insert(&mut self, value: T) -> Index {
177        // This value will definitely be inserted, so we can update length now.
178        self.len = self
179            .len
180            .checked_add(1)
181            .unwrap_or_else(|| panic!("Cannot insert more than u32::MAX elements into Arena"));
182
183        // If there was a previously free entry, we can re-use its slot as long
184        // as we increment its generation.
185        if let Some(free_pointer) = self.first_free {
186            let slot = free_pointer.slot();
187            let entry = self.storage.get_mut(slot as usize).unwrap_or_else(|| {
188                unreachable!("first_free pointed past the end of the arena's storage")
189            });
190
191            let empty = entry
192                .as_empty()
193                .unwrap_or_else(|| unreachable!("first_free pointed to an occupied entry"));
194
195            // If there is another empty entry after this one, we'll update the
196            // arena to point to it to use it on the next insertion.
197            self.first_free = empty.next_free;
198
199            // Overwrite the entry directly using our mutable reference instead
200            // of indexing into our storage again. This should avoid an
201            // additional bounds check.
202            let generation = empty.generation.next();
203            *entry = Entry::Occupied(OccupiedEntry { generation, value });
204
205            Index { slot, generation }
206        } else {
207            // There were no more empty entries left in our free list, so we'll
208            // create a new first-generation entry and push it into storage.
209
210            let generation = Generation::first();
211            let slot: u32 = self.storage.len().try_into().unwrap_or_else(|_| {
212                unreachable!("Arena storage exceeded what can be represented by a u32")
213            });
214
215            self.storage
216                .push(Entry::Occupied(OccupiedEntry { generation, value }));
217
218            Index { slot, generation }
219        }
220    }
221
222    /// Traverse the free list and remove this known-empty slot from it, given the slot to remove
223    /// and the `next_free` pointer of that slot.
224    fn remove_slot_from_free_list(&mut self, slot: u32, new_next_free: Option<FreePointer>) {
225        // We will need to fix up the free list so that whatever pointer previously pointed
226        // to this empty entry will point to the next empty entry after it.
227        let mut next_fp = self
228            .first_free
229            .expect("Free entry exists but first_free is None");
230
231        // As state during this traversal, we keep the "next free" pointer which we are testing
232        // (which will always be `Some` as long as the free list is correct and contains this empty
233        // entry) as well as the current slot that contains that "next free" pointer. If the current
234        // slot is `None`, it means that the container of the relevant "next free" pointer is
235        // actually the root (`self.first_free`).
236        let mut current_slot = None;
237        while next_fp.slot() != slot {
238            current_slot = Some(next_fp.slot());
239            next_fp = self
240                .storage
241                .get(next_fp.slot() as usize)
242                .expect("Empty entry not in storage!")
243                .as_empty()
244                .expect("Entry in free list not actually empty!")
245                .next_free
246                .expect("Hit the end of the free list without finding the target slot!");
247        }
248
249        // If we found the slot to fix, then fix it; otherwise, we know that this slot is
250        // actually the very first in the free list, so fix it at the root.
251        match current_slot {
252            Some(slot_to_fix) => {
253                self.storage[slot_to_fix as usize]
254                    .as_empty_mut()
255                    .unwrap()
256                    .next_free = new_next_free
257            }
258            None => self.first_free = new_next_free,
259        }
260    }
261
262    // Shared functionality between `insert_at` and `insert_at_slot`.
263    #[inline]
264    fn insert_at_inner(
265        &mut self,
266        slot: u32,
267        generation: Option<Generation>,
268        value: T,
269    ) -> (Index, Option<T>) {
270        // Three cases to consider:
271        //
272        // 1.) The slot is free; we need to traverse the free list, remove it from the list, and
273        //     then insert the value.
274        // 2.) The slot is occupied; we can just replace the value and return the old one.
275        // 3.) The slot is beyond the current length of the arena. In this case, we must extend
276        //     the arena with new empty slots filling the free list accordingly, and then insert the
277        //     value.
278
279        let (index, old_value) = match self.storage.get_mut(slot as usize) {
280            Some(Entry::Empty(empty)) => {
281                let generation = generation.unwrap_or_else(|| empty.generation.next());
282                // We will need to fix up the free list so that whatever pointer previously pointed
283                // to this empty entry will point to the next empty entry after it.
284                let new_next_free = empty.next_free;
285                self.remove_slot_from_free_list(slot, new_next_free);
286                self.storage[slot as usize] = Entry::Occupied(OccupiedEntry { generation, value });
287
288                (Index { slot, generation }, None)
289            }
290            Some(Entry::Occupied(occupied)) => {
291                occupied.generation = generation.unwrap_or_else(|| occupied.generation.next());
292                let generation = occupied.generation;
293                let old_value = replace(&mut occupied.value, value);
294
295                (Index { slot, generation }, Some(old_value))
296            }
297            None => {
298                let mut first_free = self.first_free;
299                while self.storage.len() < slot as usize {
300                    let new_slot: u32 = self.storage.len().try_into().unwrap_or_else(|_| {
301                        unreachable!("Arena storage exceeded what can be represented by a u32")
302                    });
303
304                    self.storage.push(Entry::Empty(EmptyEntry {
305                        generation: Generation::first(),
306                        next_free: first_free,
307                    }));
308
309                    first_free = Some(FreePointer::from_slot(new_slot));
310                }
311
312                self.first_free = first_free;
313                let generation = generation.unwrap_or_else(Generation::first);
314                self.storage
315                    .push(Entry::Occupied(OccupiedEntry { generation, value }));
316
317                (Index { slot, generation }, None)
318            }
319        };
320
321        // If this insertion didn't replace an old value, then the arena now contains one more
322        // element; we need to update its length accordingly.
323        if old_value.is_none() {
324            self.len = self
325                .len
326                .checked_add(1)
327                .unwrap_or_else(|| panic!("Cannot insert more than u32::MAX elements into Arena"));
328        }
329
330        (index, old_value)
331    }
332
333    /// Insert a new value at a given index, returning the old value if present. The entry's
334    /// generation is set to the given index's generation.
335    ///
336    /// # Caveats
337    ///
338    /// This method is capable of "resurrecting" an old `Index`. This is unavoidable; if we already
339    /// have an occupied entry (or had) at this index of some generation M, and then `insert_at`
340    /// that same slot but with a generation N < M, eventually after some number of insertions and
341    /// removals it is possible we could end up with an index matching that old index. There are few
342    /// cases where this is likely to be a problem, but it is still possible.
343    pub fn insert_at(&mut self, index: Index, value: T) -> Option<T> {
344        self.insert_at_inner(index.slot, Some(index.generation), value)
345            .1
346    }
347
348    /// Insert a new value at a given slot, returning the old value if present. If the slot is
349    /// already occupied, this will increment the generation of the slot, and invalidate any
350    /// previous indices pointing to it.
351    pub fn insert_at_slot(&mut self, slot: u32, value: T) -> (Index, Option<T>) {
352        self.insert_at_inner(slot, None, value)
353    }
354
355    /// Returns true if the given index is valid for the arena.
356    pub fn contains(&self, index: Index) -> bool {
357        match self.storage.get(index.slot as usize) {
358            Some(Entry::Occupied(occupied)) if occupied.generation == index.generation => true,
359            _ => false,
360        }
361    }
362
363    /// Checks to see whether a slot is occupied in the arena, and if it is,
364    /// returns `Some` with the true `Index` of that slot (slot plus generation.)
365    /// Otherwise, returns `None`.
366    pub fn contains_slot(&self, slot: u32) -> Option<Index> {
367        match self.storage.get(slot as usize) {
368            Some(Entry::Occupied(occupied)) => Some(Index {
369                slot,
370                generation: occupied.generation,
371            }),
372            _ => None,
373        }
374    }
375
376    /// Get an immutable reference to a value inside the arena by
377    /// [`Index`], returning `None` if the index is not contained in the arena.
378    pub fn get(&self, index: Index) -> Option<&T> {
379        match self.storage.get(index.slot as usize) {
380            Some(Entry::Occupied(occupied)) if occupied.generation == index.generation => {
381                Some(&occupied.value)
382            }
383            _ => None,
384        }
385    }
386
387    /// Get a mutable reference to a value inside the arena by [`Index`],
388    /// returning `None` if the index is not contained in the arena.
389    pub fn get_mut(&mut self, index: Index) -> Option<&mut T> {
390        match self.storage.get_mut(index.slot as usize) {
391            Some(entry) => entry.get_value_mut(index.generation),
392            _ => None,
393        }
394    }
395
396    /// Get mutable references of two values inside this arena at once by
397    /// [`Index`], returning `None` if the corresponding `index` is not
398    /// contained in this arena.
399    ///
400    /// # Panics
401    ///
402    /// This function panics when the two indices are equal (having the same
403    /// slot number and generation).
404    pub fn get2_mut(&mut self, index1: Index, index2: Index) -> (Option<&mut T>, Option<&mut T>) {
405        if index1 == index2 {
406            panic!("Arena::get2_mut is called with two identical indices");
407        }
408
409        // Same entry with a different generation. We'll prefer the first value
410        // that matches.
411        if index1.slot == index2.slot {
412            // The borrow checker forces us to index into our storage twice here
413            // due to `return` extending borrows.
414            if self.get(index1).is_some() {
415                return (self.get_mut(index1), None);
416            } else {
417                return (None, self.get_mut(index2));
418            }
419        }
420
421        // If the indices point to different slots, we can mutably split the
422        // underlying storage to get the desired entry in each slice.
423        let (entry1, entry2) = if index1.slot > index2.slot {
424            let (slice1, slice2) = self.storage.split_at_mut(index1.slot as usize);
425            (slice2.get_mut(0), slice1.get_mut(index2.slot as usize))
426        } else {
427            let (slice1, slice2) = self.storage.split_at_mut(index2.slot as usize);
428            (slice1.get_mut(index1.slot as usize), slice2.get_mut(0))
429        };
430
431        (
432            entry1.and_then(|e| e.get_value_mut(index1.generation)),
433            entry2.and_then(|e| e.get_value_mut(index2.generation)),
434        )
435    }
436
437    /// Remove the value contained at the given index from the arena, returning
438    /// it if it was present.
439    pub fn remove(&mut self, index: Index) -> Option<T> {
440        let entry = self.storage.get_mut(index.slot as usize)?;
441
442        match entry {
443            Entry::Occupied(occupied) if occupied.generation == index.generation => {
444                // We can replace an occupied entry with an empty entry with the
445                // same generation. On next insertion, this generation will
446                // increment.
447                let new_entry = Entry::Empty(EmptyEntry {
448                    generation: occupied.generation,
449                    next_free: self.first_free,
450                });
451
452                // Swap our new entry into our storage and take ownership of the
453                // old entry. We'll consume it for its value so we can give that
454                // back to our caller.
455                let old_entry = replace(entry, new_entry);
456                let value = old_entry.into_value().unwrap_or_else(|| unreachable!());
457
458                // The next time we insert, we can re-use the empty entry we
459                // just created. If another removal happens before then, that
460                // entry will be used before this one (FILO).
461                self.first_free = Some(FreePointer::from_slot(index.slot));
462
463                self.len = self.len.checked_sub(1).unwrap_or_else(|| unreachable!());
464
465                Some(value)
466            }
467            _ => None,
468        }
469    }
470
471    /// Invalidate the given index and return a new index to the same value. This
472    /// is roughly equivalent to `remove` followed by `insert`, but much faster.
473    /// If the old index is already invalid, this method returns `None`.
474    pub fn invalidate(&mut self, index: Index) -> Option<Index> {
475        let entry = self.storage.get_mut(index.slot as usize)?;
476
477        match entry {
478            Entry::Occupied(occupied) if occupied.generation == index.generation => {
479                occupied.generation = occupied.generation.next();
480
481                Some(Index {
482                    generation: occupied.generation,
483                    ..index
484                })
485            }
486            _ => None,
487        }
488    }
489
490    /// Attempt to look up the given slot in the arena, disregarding any generational
491    /// information, and retrieve an immutable reference to it. Returns `None` if the
492    /// slot is empty.
493    pub fn get_by_slot(&self, slot: u32) -> Option<(Index, &T)> {
494        match self.storage.get(slot as usize) {
495            Some(Entry::Occupied(occupied)) => {
496                let index = Index {
497                    slot,
498                    generation: occupied.generation,
499                };
500                Some((index, &occupied.value))
501            }
502            _ => None,
503        }
504    }
505
506    /// Attempt to look up the given slot in the arena, disregarding any generational
507    /// information, and retrieve a mutable reference to it. Returns `None` if the
508    /// slot is empty.
509    pub fn get_by_slot_mut(&mut self, slot: u32) -> Option<(Index, &mut T)> {
510        match self.storage.get_mut(slot as usize) {
511            Some(Entry::Occupied(occupied)) => {
512                let index = Index {
513                    slot,
514                    generation: occupied.generation,
515                };
516                Some((index, &mut occupied.value))
517            }
518            _ => None,
519        }
520    }
521
522    /// Remove an entry in the arena by its slot, disregarding any generational info.
523    /// Returns `None` if the slot was already empty.
524    pub fn remove_by_slot(&mut self, slot: u32) -> Option<(Index, T)> {
525        let entry = self.storage.get_mut(slot as usize)?;
526
527        match entry {
528            Entry::Occupied(occupied) => {
529                // Construct the index that would be used to access this entry.
530                let index = Index {
531                    generation: occupied.generation,
532                    slot,
533                };
534
535                // This occupied entry will be replaced with an empty one of the
536                // same generation. Generation will be incremented on the next
537                // insert.
538                let next_entry = Entry::Empty(EmptyEntry {
539                    generation: occupied.generation,
540                    next_free: self.first_free,
541                });
542
543                // Swap new entry into place and consume the old one.
544                let old_entry = replace(entry, next_entry);
545                let value = old_entry.into_value().unwrap_or_else(|| unreachable!());
546
547                // Set this entry as the next one that should be inserted into,
548                // should an insertion happen.
549                self.first_free = Some(FreePointer::from_slot(slot));
550
551                self.len = self.len.checked_sub(1).unwrap_or_else(|| unreachable!());
552
553                Some((index, value))
554            }
555            _ => None,
556        }
557    }
558
559    /// Clear the arena and drop all elements.
560    pub fn clear(&mut self) {
561        self.drain().for_each(drop);
562    }
563
564    /// Iterate over all of the indexes and values contained in the arena.
565    ///
566    /// Iteration order is not defined.
567    pub fn iter(&self) -> Iter<'_, T> {
568        Iter {
569            inner: self.storage.iter(),
570            slot: 0,
571            len: self.len,
572        }
573    }
574
575    /// Iterate over all of the indexes and values contained in the arena, with
576    /// mutable access to each value.
577    ///
578    /// Iteration order is not defined.
579    pub fn iter_mut(&mut self) -> IterMut<'_, T> {
580        IterMut {
581            inner: self.storage.iter_mut(),
582            slot: 0,
583            len: self.len,
584        }
585    }
586
587    /// Returns an iterator that removes each element from the arena.
588    ///
589    /// Iteration order is not defined.
590    ///
591    /// If the iterator is dropped before it is fully consumed, any uniterated
592    /// items will be dropped from the arena, and the arena will be empty.
593    /// The arena's capacity will not be changed.
594    pub fn drain(&mut self) -> Drain<'_, T> {
595        Drain {
596            arena: self,
597            slot: 0,
598        }
599    }
600
601    /// Remove all entries in the `Arena` which don't satisfy the provided predicate.
602    pub fn retain<F: FnMut(Index, &mut T) -> bool>(&mut self, mut f: F) {
603        for (i, entry) in self.storage.iter_mut().enumerate() {
604            if let Entry::Occupied(occupied) = entry {
605                let index = Index {
606                    slot: i as u32,
607                    generation: occupied.generation,
608                };
609
610                if !f(index, &mut occupied.value) {
611                    // We can replace an occupied entry with an empty entry with the
612                    // same generation. On next insertion, this generation will
613                    // increment.
614                    *entry = Entry::Empty(EmptyEntry {
615                        generation: occupied.generation,
616                        next_free: self.first_free,
617                    });
618
619                    // The next time we insert, we can re-use the empty entry we
620                    // just created. If another removal happens before then, that
621                    // entry will be used before this one (FILO).
622                    self.first_free = Some(FreePointer::from_slot(index.slot));
623
624                    // We just verified that this entry is (was) occupied, so there's
625                    // trivially no way for this `checked_sub` to fail.
626                    self.len = self.len.checked_sub(1).unwrap_or_else(|| unreachable!());
627                }
628            }
629        }
630    }
631}
632
633impl<T> Default for Arena<T> {
634    fn default() -> Self {
635        Arena::new()
636    }
637}
638
639impl<T> IntoIterator for Arena<T> {
640    type Item = (Index, T);
641    type IntoIter = IntoIter<T>;
642
643    fn into_iter(self) -> Self::IntoIter {
644        IntoIter {
645            arena: self,
646            slot: 0,
647        }
648    }
649}
650
651impl<'a, T> IntoIterator for &'a Arena<T> {
652    type Item = (Index, &'a T);
653    type IntoIter = Iter<'a, T>;
654
655    fn into_iter(self) -> Self::IntoIter {
656        self.iter()
657    }
658}
659
660impl<'a, T> IntoIterator for &'a mut Arena<T> {
661    type Item = (Index, &'a mut T);
662    type IntoIter = IterMut<'a, T>;
663
664    fn into_iter(self) -> Self::IntoIter {
665        self.iter_mut()
666    }
667}
668
669impl<T> ops::Index<Index> for Arena<T> {
670    type Output = T;
671
672    fn index(&self, index: Index) -> &Self::Output {
673        self.get(index)
674            .unwrap_or_else(|| panic!("No entry at index {:?}", index))
675    }
676}
677
678impl<T> ops::IndexMut<Index> for Arena<T> {
679    fn index_mut(&mut self, index: Index) -> &mut Self::Output {
680        self.get_mut(index)
681            .unwrap_or_else(|| panic!("No entry at index {:?}", index))
682    }
683}
684
685#[cfg(test)]
686mod test {
687    use crate::free_pointer::FreePointer;
688
689    use super::{Arena, Generation, Index};
690
691    use core::mem::size_of;
692
693    #[test]
694    fn size_of_index() {
695        assert_eq!(size_of::<Index>(), 8);
696        assert_eq!(size_of::<Option<Index>>(), 8);
697    }
698
699    #[test]
700    fn new() {
701        let arena: Arena<u32> = Arena::new();
702        assert_eq!(arena.len(), 0);
703        assert_eq!(arena.capacity(), 0);
704    }
705
706    #[test]
707    fn with_capacity() {
708        let arena: Arena<u32> = Arena::with_capacity(8);
709        assert_eq!(arena.len(), 0);
710        assert_eq!(arena.capacity(), 8);
711    }
712
713    #[test]
714    fn insert_and_get() {
715        let mut arena = Arena::new();
716
717        let one = arena.insert(1);
718        assert_eq!(arena.len(), 1);
719        assert_eq!(arena.get(one), Some(&1));
720
721        let two = arena.insert(2);
722        assert_eq!(arena.len(), 2);
723        assert_eq!(arena.get(one), Some(&1));
724        assert_eq!(arena.get(two), Some(&2));
725    }
726
727    #[test]
728    fn insert_remove_get() {
729        let mut arena = Arena::new();
730        let one = arena.insert(1);
731
732        let two = arena.insert(2);
733        assert_eq!(arena.len(), 2);
734        assert!(arena.contains(two));
735        assert_eq!(arena.remove(two), Some(2));
736        assert!(!arena.contains(two));
737
738        let three = arena.insert(3);
739        assert_eq!(arena.len(), 2);
740        assert_eq!(arena.get(one), Some(&1));
741        assert_eq!(arena.get(three), Some(&3));
742        assert_eq!(arena.get(two), None);
743    }
744
745    #[test]
746    fn insert_remove_get_by_slot() {
747        let mut arena = Arena::new();
748        let one = arena.insert(1);
749
750        let two = arena.insert(2);
751        assert_eq!(arena.len(), 2);
752        assert!(arena.contains(two));
753        assert_eq!(arena.remove_by_slot(two.slot()), Some((two, 2)));
754        assert!(!arena.contains(two));
755        assert_eq!(arena.get_by_slot(two.slot()), None);
756
757        let three = arena.insert(3);
758        assert_eq!(arena.len(), 2);
759        assert_eq!(arena.get(one), Some(&1));
760        assert_eq!(arena.get(three), Some(&3));
761        assert_eq!(arena.get(two), None);
762        assert_eq!(arena.get_by_slot(two.slot()), Some((three, &3)));
763    }
764
765    #[test]
766    fn insert_at() {
767        let mut arena = Arena::new();
768        // Numbers definitely not chosen by fair dice roll
769        let index = Index {
770            slot: 42,
771            generation: Generation::from_u32(78).unwrap(),
772        };
773        arena.insert_at(index, 5);
774        assert_eq!(arena.len(), 1);
775        assert_eq!(arena.get(index), Some(&5));
776        assert_eq!(arena.get_by_slot(42), Some((index, &5)));
777    }
778
779    #[test]
780    fn insert_at_first_slot() {
781        let mut arena = Arena::new();
782        // Numbers definitely not chosen by fair dice roll
783        let index = Index {
784            slot: 0,
785            generation: Generation::from_u32(3).unwrap(),
786        };
787        arena.insert_at(index, 5);
788        assert_eq!(arena.len(), 1);
789        assert_eq!(arena.get(index), Some(&5));
790        assert_eq!(arena.get_by_slot(0), Some((index, &5)));
791    }
792
793    #[test]
794    fn insert_at_slot() {
795        let mut arena = Arena::new();
796
797        let (index, _) = arena.insert_at_slot(42, 5);
798        assert_eq!(arena.len(), 1);
799        assert_eq!(arena.get(index), Some(&5));
800        assert_eq!(arena.get_by_slot(42), Some((index, &5)));
801    }
802
803    #[test]
804    fn insert_at_middle() {
805        let mut arena = Arena::new();
806        arena.insert_at_slot(4, 50);
807        arena.insert_at_slot(2, 40);
808
809        let empty = arena.storage.get(3).unwrap().as_empty().unwrap();
810        if empty.next_free != Some(FreePointer::from_slot(1)) {
811            panic!("Invalid free list: {:#?}", arena);
812        }
813    }
814
815    #[test]
816    fn get_mut() {
817        let mut arena = Arena::new();
818        let foo = arena.insert(5);
819
820        let handle = arena.get_mut(foo).unwrap();
821        *handle = 6;
822
823        assert_eq!(arena.get(foo), Some(&6));
824    }
825
826    #[test]
827    fn get2_mut() {
828        let mut arena = Arena::new();
829        let foo = arena.insert(100);
830        let bar = arena.insert(500);
831
832        let (foo_handle, bar_handle) = arena.get2_mut(foo, bar);
833        let foo_handle = foo_handle.unwrap();
834        let bar_handle = bar_handle.unwrap();
835        *foo_handle = 105;
836        *bar_handle = 505;
837
838        assert_eq!(arena.get(foo), Some(&105));
839        assert_eq!(arena.get(bar), Some(&505));
840    }
841
842    #[test]
843    fn get2_mut_reversed_order() {
844        let mut arena = Arena::new();
845        let foo = arena.insert(100);
846        let bar = arena.insert(500);
847
848        let (bar_handle, foo_handle) = arena.get2_mut(bar, foo);
849        let foo_handle = foo_handle.unwrap();
850        let bar_handle = bar_handle.unwrap();
851        *foo_handle = 105;
852        *bar_handle = 505;
853
854        assert_eq!(arena.get(foo), Some(&105));
855        assert_eq!(arena.get(bar), Some(&505));
856    }
857
858    #[test]
859    fn get2_mut_non_exist_handle() {
860        let mut arena = Arena::new();
861        let foo = arena.insert(100);
862        let bar = arena.insert(500);
863        arena.remove(bar);
864
865        let (bar_handle, foo_handle) = arena.get2_mut(bar, foo);
866        let foo_handle = foo_handle.unwrap();
867        assert!(bar_handle.is_none());
868        *foo_handle = 105;
869
870        assert_eq!(arena.get(foo), Some(&105));
871    }
872
873    #[test]
874    fn get2_mut_same_slot_different_generation() {
875        let mut arena = Arena::new();
876        let foo = arena.insert(100);
877        let mut foo1 = foo;
878        foo1.generation = foo1.generation.next();
879
880        let (foo_handle, foo1_handle) = arena.get2_mut(foo, foo1);
881        assert!(foo_handle.is_some());
882        assert!(foo1_handle.is_none());
883    }
884
885    #[test]
886    #[should_panic]
887    fn get2_mut_panics() {
888        let mut arena = Arena::new();
889        let foo = arena.insert(100);
890
891        arena.get2_mut(foo, foo);
892    }
893
894    #[test]
895    fn insert_remove_insert_capacity() {
896        let mut arena = Arena::with_capacity(2);
897        assert_eq!(arena.capacity(), 2);
898
899        let a = arena.insert("a");
900        let b = arena.insert("b");
901        assert_eq!(arena.len(), 2);
902        assert_eq!(arena.capacity(), 2);
903
904        arena.remove(a);
905        arena.remove(b);
906        assert_eq!(arena.len(), 0);
907        assert_eq!(arena.capacity(), 2);
908
909        let _a2 = arena.insert("a2");
910        let _b2 = arena.insert("b2");
911        assert_eq!(arena.len(), 2);
912        assert_eq!(arena.capacity(), 2);
913    }
914
915    #[test]
916    fn invalidate() {
917        let mut arena = Arena::new();
918
919        let a = arena.insert("a");
920        assert_eq!(arena.get(a), Some(&"a"));
921
922        let new_a = arena.invalidate(a).unwrap();
923        assert_eq!(arena.get(a), None);
924        assert_eq!(arena.get(new_a), Some(&"a"));
925    }
926
927    #[test]
928    fn retain() {
929        let mut arena = Arena::new();
930
931        for i in 0..100 {
932            arena.insert(i);
933        }
934
935        arena.retain(|_, &mut i| i % 2 == 1);
936
937        for (_, i) in arena.iter() {
938            assert_eq!(i % 2, 1);
939        }
940
941        assert_eq!(arena.len(), 50);
942    }
943
944    #[test]
945    fn index_bits_roundtrip() {
946        let index = Index::from_bits(0x1BAD_CAFE_DEAD_BEEF).unwrap();
947        assert_eq!(index.to_bits(), 0x1BAD_CAFE_DEAD_BEEF);
948    }
949
950    #[test]
951    fn index_bits_none_on_zero_generation() {
952        let index = Index::from_bits(0x0000_0000_DEAD_BEEF);
953        assert_eq!(index, None);
954    }
955}