dense_map/
lib.rs

1// Copyright 2019 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! A densely packed map.
6//!
7//! Defines the [`DenseMap`] data structure: A generic mapped container keyed by
8//! an internally managed pool of identifiers kept densely packed.
9
10#![deny(missing_docs, unreachable_patterns)]
11
12pub mod collection;
13#[cfg(test)]
14mod testutil;
15
16use std::fmt::Debug;
17
18/// [`DenseMap`]s use `usize`s for keys.
19pub type Key = usize;
20
21/// DenseMapEntry where all free blocks are linked together.
22#[derive(PartialEq, Eq, Debug)]
23#[cfg_attr(test, derive(Clone))]
24enum DenseMapEntry<T> {
25    /// The Entry should either be allocated and contains a value...
26    Allocated(AllocatedEntry<T>),
27    /// Or it is not currently used and should be part of a freelist.
28    Free(ListLink),
29}
30
31#[derive(PartialEq, Eq, Debug)]
32#[cfg_attr(test, derive(Clone))]
33struct AllocatedEntry<T> {
34    link: ListLink,
35    item: T,
36}
37
38/// The link of a doubly-linked list.
39#[derive(PartialEq, Eq, Debug, Clone, Copy)]
40struct ListLink {
41    /// The index of the previous free block in the list.
42    prev: Option<usize>,
43    /// The index of the next free block in the list.
44    next: Option<usize>,
45}
46
47impl Default for ListLink {
48    /// By default, an entry is not linked into the list.
49    fn default() -> Self {
50        Self { prev: None, next: None }
51    }
52}
53
54/// Stores positions of the head and tail of a doubly-linked list by
55/// `ListLink`.
56#[derive(PartialEq, Eq, Debug, Clone, Copy)]
57struct List {
58    /// The index of the first free block.
59    head: usize,
60    /// The index of the last free block.
61    tail: usize,
62}
63
64impl List {
65    /// Construct a doubly-linked list with only one element.
66    fn singleton(elem: usize) -> List {
67        List { head: elem, tail: elem }
68    }
69}
70
71#[derive(Copy, Clone, Debug, Eq, PartialEq)]
72enum DenseMapEntryKind {
73    Allocated,
74    Free,
75}
76
77impl<T> DenseMapEntry<T> {
78    fn link(&self) -> (&ListLink, DenseMapEntryKind) {
79        match self {
80            DenseMapEntry::Allocated(entry) => (&entry.link, DenseMapEntryKind::Allocated),
81            DenseMapEntry::Free(link) => (&link, DenseMapEntryKind::Free),
82        }
83    }
84
85    fn link_mut_and_check(&mut self, expected_kind: DenseMapEntryKind) -> &mut ListLink {
86        let (link, got_kind) = match self {
87            DenseMapEntry::Allocated(entry) => (&mut entry.link, DenseMapEntryKind::Allocated),
88            DenseMapEntry::Free(link) => (link, DenseMapEntryKind::Free),
89        };
90        assert_eq!(expected_kind, got_kind);
91        link
92    }
93
94    /// Returns a reference to the freelist link if the entry is free, otherwise None.
95    fn as_free_or_none(&self) -> Option<&ListLink> {
96        match self {
97            DenseMapEntry::Free(link) => Some(link),
98            DenseMapEntry::Allocated(_) => None,
99        }
100    }
101
102    /// Returns a mutable reference to the freelist link if the entry is free, otherwise None.
103    fn as_free_or_none_mut(&mut self) -> Option<&mut ListLink> {
104        match self {
105            DenseMapEntry::Free(link) => Some(link),
106            DenseMapEntry::Allocated(_) => None,
107        }
108    }
109}
110
111/// A generic container for `T` keyed by densely packed integers.
112///
113/// `DenseMap` is a generic container keyed by `usize` that manages its own key
114/// pool. `DenseMap` reuses keys that are free to keep its key pool as dense as
115/// possible.
116///
117/// The main guarantee provided by `DenseMap` is that all `get` operations are
118/// provided in O(1) without the need to hash the keys.
119///
120/// All operations that mutate the `DenseMap` may be O(n) during resizing or
121/// compression but averages at O(1).
122///
123/// `push` will grab the lowest free `id` and assign it to the given value,
124/// returning the assigned `id`. `insert` can be used for assigning a specific
125/// `id` to an object, and returns the previous object at that `id` if any.
126#[derive(Debug)]
127#[cfg_attr(test, derive(Clone))]
128pub struct DenseMap<T> {
129    freelist: Option<List>,
130    allocatedlist: Option<List>,
131    data: Vec<DenseMapEntry<T>>,
132}
133
134impl<T> DenseMap<T> {
135    /// Creates a new empty [`DenseMap`].
136    pub fn new() -> Self {
137        Self { freelist: None, allocatedlist: None, data: Vec::new() }
138    }
139
140    /// Returns `true` if there are no items in [`DenseMap`].
141    pub fn is_empty(&self) -> bool {
142        // Because of `compress`, our map is empty if and only if the underlying
143        // vector is empty. If the underlying vector is not empty but our map is
144        // empty, it must be the case where the underlying vector contains
145        // nothing but free entries, and all these entries should be reclaimed
146        // when the last allocated entry is removed.
147        self.data.is_empty()
148    }
149
150    /// Returns a reference to the item indexed by `key`, or `None` if the `key`
151    /// doesn't exist.
152    pub fn get(&self, key: Key) -> Option<&T> {
153        self.data.get(key).and_then(|v| match v {
154            DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) => Some(item),
155            DenseMapEntry::Free(_) => None,
156        })
157    }
158
159    /// Returns a mutable reference to the item indexed by `key`, or `None` if
160    /// the `key` doesn't exist.
161    pub fn get_mut(&mut self, key: Key) -> Option<&mut T> {
162        self.data.get_mut(key).and_then(|v| match v {
163            DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) => Some(item),
164            DenseMapEntry::Free(_) => None,
165        })
166    }
167
168    /// Removes item indexed by `key` from the container.
169    ///
170    /// Returns the removed item if it exists, or `None` otherwise.
171    ///
172    /// Note: the worst case complexity of `remove` is O(key) if the backing
173    /// data structure of the [`DenseMap`] is too sparse.
174    pub fn remove(&mut self, key: Key) -> Option<T> {
175        let r = self.remove_inner(key);
176        if r.is_some() {
177            self.compress();
178        }
179        r
180    }
181
182    fn remove_inner(&mut self, key: Key) -> Option<T> {
183        let r = self.data.get_mut(key).and_then(|v| {
184            match v {
185                DenseMapEntry::Allocated(_) => {
186                    let old_head = self.freelist.map(|l| l.head);
187                    let new_link = DenseMapEntry::Free(ListLink { prev: None, next: old_head });
188                    match core::mem::replace(v, new_link) {
189                        DenseMapEntry::Allocated(entry) => Some(entry),
190                        DenseMapEntry::Free(_) => unreachable!("already matched"),
191                    }
192                }
193                // If it is currently free, we don't want to unlink the entry and
194                // link it back at the head again.
195                DenseMapEntry::Free(_) => None,
196            }
197        });
198        r.map(|AllocatedEntry { link, item }| {
199            self.unlink_entry_inner(DenseMapEntryKind::Allocated, link);
200            // If it was allocated, we add the removed entry to the head of the
201            // free-list.
202            match self.freelist.as_mut() {
203                Some(List { head, .. }) => {
204                    self.data[*head]
205                        .as_free_or_none_mut()
206                        .unwrap_or_else(|| panic!("freelist head node {} is not free", head))
207                        .prev = Some(key);
208                    *head = key;
209                }
210                None => self.freelist = Some(List::singleton(key)),
211            }
212
213            item
214        })
215    }
216
217    fn allocated_link(
218        allocatedlist: &mut Option<List>,
219        data: &mut [DenseMapEntry<T>],
220        key: Key,
221    ) -> ListLink {
222        // Add the key to the tail of the allocated list. There are four cases
223        // to consider. In all cases however, we update the list's tail to point
224        // to `key` and create a `ListLink` with a previous pointer that points
225        // to the current allocate list's tail and no next pointer.
226        //
227        //  1) The allocated list is empty.
228        //  2) `key` points to a free entry
229        //  3) `key` is the (non-empty) allocated list's tail.
230        //  4) `key` is in the middle of the (non-empty) allocated list.
231        if let Some(List { head: _, tail }) = allocatedlist {
232            match data[*tail] {
233                DenseMapEntry::Allocated(ref mut entry) => {
234                    assert_eq!(None, core::mem::replace(&mut entry.link.next, Some(key)));
235                    ListLink { next: None, prev: Some(core::mem::replace(tail, key)) }
236                }
237                DenseMapEntry::Free(_) => unreachable!(
238                    "allocated list tail entry is free; key = {}; tail = {}",
239                    key, tail,
240                ),
241            }
242        } else {
243            *allocatedlist = Some(List { head: key, tail: key });
244
245            ListLink { next: None, prev: None }
246        }
247    }
248
249    /// Inserts `item` at `key`.
250    ///
251    /// If the [`DenseMap`] already contained an item indexed by `key`, `insert`
252    /// returns it, or `None` otherwise.
253    ///
254    /// Note: The worst case complexity of `insert` is O(key) if `key` is larger
255    /// than the number of items currently held by the [`DenseMap`].
256    pub fn insert(&mut self, key: Key, item: T) -> Option<T> {
257        if key < self.data.len() {
258            // Remove the entry from whatever list it may be in
259            self.unlink_entry(key);
260            // Add the key to the allocated list.
261            let link = Self::allocated_link(&mut self.allocatedlist, &mut self.data, key);
262
263            let prev = core::mem::replace(
264                &mut self.data[key],
265                DenseMapEntry::Allocated(AllocatedEntry { link, item }),
266            );
267            // We don't need to do anything with the `ListLink` since we removed
268            // the entry from the list.
269            match prev {
270                DenseMapEntry::Free(ListLink { .. }) => None,
271                DenseMapEntry::Allocated(AllocatedEntry { link: ListLink { .. }, item }) => {
272                    Some(item)
273                }
274            }
275        } else {
276            let start_len = self.data.len();
277            // Fill the gap `start_len .. key` with free entries. Currently, the
278            // free entries introduced by `insert` is linked at the end of the
279            // free list so that hopefully these free entries near the end will
280            // get less likely to be allocated than those near the beginning,
281            // this may help reduce the memory footprint because we have
282            // increased the chance for the underlying vector to be compressed.
283            // TODO: explore whether we can reorder the list on the fly to
284            // further increase the chance for compressing.
285            for idx in start_len..key {
286                // These new free entries will be linked to each other, except:
287                // - the first entry's prev should point to the old tail.
288                // - the last entry's next should be None.
289                self.data.push(DenseMapEntry::Free(ListLink {
290                    prev: if idx == start_len {
291                        self.freelist.map(|l| l.tail)
292                    } else {
293                        Some(idx - 1)
294                    },
295                    next: if idx == key - 1 { None } else { Some(idx + 1) },
296                }));
297            }
298            // If `key > start_len`, we have inserted at least one free entry,
299            // so we have to update our freelist.
300            if key > start_len {
301                let new_tail = key - 1;
302                match self.freelist.as_mut() {
303                    Some(List { tail, .. }) => {
304                        self.data[*tail]
305                            .as_free_or_none_mut()
306                            .unwrap_or_else(|| panic!("freelist tail node {} is not free", tail))
307                            .next = Some(start_len);
308                        *tail = new_tail;
309                    }
310                    None => {
311                        self.freelist = Some(List { head: start_len, tail: new_tail });
312                    }
313                }
314            }
315            // And finally we insert our item into the map.
316            let link = Self::allocated_link(&mut self.allocatedlist, &mut self.data, key);
317            self.data.push(DenseMapEntry::Allocated(AllocatedEntry { link, item }));
318            None
319        }
320    }
321
322    /// Inserts `item` into the [`DenseMap`].
323    ///
324    /// `push` inserts a new `item` into the [`DenseMap`] and returns the key value
325    /// allocated for `item`. `push` will allocate *any* key that is currently
326    /// free in the internal structure, so it may return a key that was used
327    /// previously but has since been removed.
328    ///
329    /// Note: The worst case complexity of `push` is O(n) where n is the number
330    /// of items held by the [`DenseMap`]. This can happen if the internal
331    /// structure gets fragmented.
332    pub fn push(&mut self, item: T) -> Key {
333        *self.push_entry(item).key()
334    }
335
336    /// Inserts `item` into the [`DenseMap`] and returns an [`OccupiedEntry`] for
337    /// it.
338    ///
339    /// Like [`DenseMap::push`] except that it returns an entry instead of an
340    /// index.
341    pub fn push_entry(&mut self, item: T) -> OccupiedEntry<'_, usize, T> {
342        self.push_with(|_: usize| item)
343    }
344
345    /// Creates an `item` in the `DenseMap` via functor.
346    ///
347    /// Like [`DenseMap::push`] except that the item is constructed by the provided
348    /// function, which is passed its index.
349    pub fn push_with(&mut self, make_item: impl FnOnce(Key) -> T) -> OccupiedEntry<'_, usize, T> {
350        let Self { freelist, allocatedlist, data } = self;
351        if let Some(List { head, .. }) = freelist.as_mut() {
352            let ret = *head;
353            let link = Self::allocated_link(allocatedlist, data, ret);
354            let old = core::mem::replace(
355                data.get_mut(ret).unwrap(),
356                DenseMapEntry::Allocated(AllocatedEntry { link, item: make_item(ret) }),
357            );
358            let old_link = old
359                .as_free_or_none()
360                .unwrap_or_else(|| panic!("freelist head node {} is not free", head));
361            // Update the head of the freelist.
362            match old_link.next {
363                Some(new_head) => {
364                    *head = new_head;
365                    data[new_head]
366                        .as_free_or_none_mut()
367                        .unwrap_or_else(|| panic!("new free list head {} is not free", new_head))
368                        .prev = None;
369                }
370                None => *freelist = None,
371            }
372            OccupiedEntry { key: ret, id_map: self }
373        } else {
374            // If we run out of freelist, we simply push a new entry into the
375            // underlying vector.
376            let key = data.len();
377            let link = Self::allocated_link(allocatedlist, data, key);
378            data.push(DenseMapEntry::Allocated(AllocatedEntry { link, item: make_item(key) }));
379            OccupiedEntry { key, id_map: self }
380        }
381    }
382
383    /// Compresses the tail of the internal `Vec`.
384    ///
385    /// `compress` removes all trailing elements in `data` that are `None`,
386    /// shrinking the internal `Vec`.
387    fn compress(&mut self) {
388        // First, find the last non-free entry.
389        if let Some(idx) = self.data.iter().enumerate().rev().find_map(|(k, v)| match v {
390            DenseMapEntry::Allocated(_) => Some(k),
391            DenseMapEntry::Free(_) => None,
392        }) {
393            // Remove all the trailing free entries.
394            for i in idx + 1..self.data.len() {
395                let link = *self.data[i].as_free_or_none().expect("already confirmed as free");
396                self.unlink_entry_inner(DenseMapEntryKind::Free, link);
397            }
398            self.data.truncate(idx + 1);
399        } else {
400            // There is nothing left in the vector.
401            self.data.clear();
402            self.freelist = None;
403        }
404    }
405
406    /// Creates an iterator over the containing items and their associated keys.
407    ///
408    /// The iterator will return items in insertion order.
409    pub fn insertion_ordered_iter(&self) -> InsertionOrderedIter<'_, T> {
410        let Self { data, freelist: _, allocatedlist } = self;
411        let next_idx = allocatedlist.map(|l| l.head);
412        InsertionOrderedIter { next_idx, map: data.as_ref() }
413    }
414
415    /// Creates an iterator over the containing items and their associated keys.
416    ///
417    /// The iterator will return items in key order.
418    pub fn key_ordered_iter(&self) -> KeyOrderedIter<'_, T> {
419        IntoIterator::into_iter(self)
420    }
421
422    /// Creates a mutable iterator over the containing items and their
423    /// associated keys.
424    ///
425    /// The iterator will return items in key order.
426    pub fn key_ordered_iter_mut(&mut self) -> KeyOrderedIterMut<'_, T> {
427        IntoIterator::into_iter(self)
428    }
429
430    /// Consumes the `DenseMap` and returns an iterator over the contained items
431    /// and their associated keys.
432    ///
433    /// The iterator will return items in key order.
434    pub fn key_ordered_into_iter(self) -> IntoKeyOrderedIter<T> {
435        IntoIterator::into_iter(self)
436    }
437
438    /// Gets the given key's corresponding entry in the map for in-place
439    /// manipulation.
440    pub fn entry(&mut self, key: usize) -> Entry<'_, usize, T> {
441        if let Some(DenseMapEntry::Allocated(_)) = self.data.get(key) {
442            Entry::Occupied(OccupiedEntry { key, id_map: self })
443        } else {
444            Entry::Vacant(VacantEntry { key, id_map: self })
445        }
446    }
447
448    /// Retains only the elements specified by the predicate.
449    ///
450    /// In other words, remove all elements e for which f(&e) returns false. The
451    /// elements are visited in ascending key order.
452    pub fn key_ordered_retain<F: FnMut(&T) -> bool>(&mut self, mut should_retain: F) {
453        (0..self.data.len()).for_each(|k| {
454            if let DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) =
455                self.data.get_mut(k).unwrap()
456            {
457                if !should_retain(item) {
458                    // Note the use of `remove_inner` rather than `remove`
459                    // here. `remove` calls `self.compress()`, which is an
460                    // O(n) operation. Instead, we postpone that operation
461                    // and perform it once during the last iteration so that
462                    // the overall complexity is O(n) rather than O(n^2).
463                    //
464                    // TODO(joshlf): Could we improve the performance here
465                    // by doing something smarter than just calling
466                    // `remove_inner`? E.g., perhaps we could build up a
467                    // separate linked list that we only insert into the
468                    // existing free list once at the end? That there is a
469                    // performance issue here at all is pure speculation,
470                    // and will need to be measured to determine whether
471                    // such an optimization is worth it.
472                    let _: T = self.remove_inner(k).unwrap();
473                }
474            }
475        });
476
477        self.compress();
478    }
479
480    fn unlink_entry_inner(&mut self, kind: DenseMapEntryKind, link: ListLink) {
481        let ListLink { next, prev } = link;
482
483        let list = match kind {
484            DenseMapEntryKind::Allocated => &mut self.allocatedlist,
485            DenseMapEntryKind::Free => &mut self.freelist,
486        };
487
488        match (prev, next) {
489            (Some(prev), Some(next)) => {
490                // A normal node in the middle of a list.
491                self.data[prev].link_mut_and_check(kind).next = Some(next);
492                self.data[next].link_mut_and_check(kind).prev = Some(prev);
493            }
494            (Some(prev), None) => {
495                // The node at the tail.
496                self.data[prev].link_mut_and_check(kind).next = next;
497                list.as_mut().unwrap().tail = prev;
498            }
499            (None, Some(next)) => {
500                // The node at the head.
501                self.data[next].link_mut_and_check(kind).prev = prev;
502                list.as_mut().unwrap().head = next;
503            }
504            (None, None) => {
505                // We are the last node.
506                *list = None;
507            }
508        }
509    }
510
511    fn unlink_entry(&mut self, i: Key) {
512        let (link, kind) = self.data[i].link();
513        self.unlink_entry_inner(kind, *link);
514    }
515}
516
517impl<T> Default for DenseMap<T> {
518    fn default() -> Self {
519        Self::new()
520    }
521}
522
523/// An iterator over the keys and values stored in an [`DenseMap`].
524///
525/// This iterator returns items in insertion order.
526pub struct InsertionOrderedIter<'s, T> {
527    next_idx: Option<usize>,
528    map: &'s [DenseMapEntry<T>],
529}
530
531impl<'a, T> Iterator for InsertionOrderedIter<'a, T> {
532    type Item = (Key, &'a T);
533
534    fn next(&mut self) -> Option<Self::Item> {
535        let Self { next_idx, map } = self;
536        let k = (*next_idx)?;
537        match &map[k] {
538            DenseMapEntry::Allocated(AllocatedEntry { link: ListLink { next, prev: _ }, item }) => {
539                *next_idx = *next;
540                Some((k, item))
541            }
542            DenseMapEntry::Free(_) => {
543                unreachable!("free entry found in allocated list @ idx={}", k)
544            }
545        }
546    }
547}
548
549/// An iterator over the keys and values stored in an [`DenseMap`].
550///
551/// This iterator returns items in key order.
552pub struct IntoKeyOrderedIter<T>(core::iter::Enumerate<std::vec::IntoIter<DenseMapEntry<T>>>);
553
554impl<T> Iterator for IntoKeyOrderedIter<T> {
555    type Item = (Key, T);
556    fn next(&mut self) -> Option<Self::Item> {
557        let Self(it) = self;
558        it.filter_map(|(k, v)| match v {
559            DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) => Some((k, item)),
560            DenseMapEntry::Free(_) => None,
561        })
562        .next()
563    }
564}
565
566impl<T> IntoIterator for DenseMap<T> {
567    type Item = (Key, T);
568    type IntoIter = IntoKeyOrderedIter<T>;
569
570    fn into_iter(self) -> Self::IntoIter {
571        IntoKeyOrderedIter(self.data.into_iter().enumerate())
572    }
573}
574
575/// An iterator over the keys and values stored in an [`DenseMap`].
576///
577/// This iterator returns items in key order.
578pub struct KeyOrderedIter<'s, T>(core::iter::Enumerate<core::slice::Iter<'s, DenseMapEntry<T>>>);
579
580impl<'a, T> Iterator for KeyOrderedIter<'a, T> {
581    type Item = (Key, &'a T);
582
583    fn next(&mut self) -> Option<Self::Item> {
584        let Self(it) = self;
585        it.filter_map(|(k, v)| match v {
586            DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) => Some((k, item)),
587            DenseMapEntry::Free(_) => None,
588        })
589        .next()
590    }
591}
592
593impl<'a, T> IntoIterator for &'a DenseMap<T> {
594    type Item = (Key, &'a T);
595    type IntoIter = KeyOrderedIter<'a, T>;
596
597    fn into_iter(self) -> Self::IntoIter {
598        KeyOrderedIter(self.data.iter().enumerate())
599    }
600}
601
602/// An iterator over the keys and mutable values stored in an [`DenseMap`].
603///
604/// This iterator returns items in key order.
605pub struct KeyOrderedIterMut<'s, T>(
606    core::iter::Enumerate<core::slice::IterMut<'s, DenseMapEntry<T>>>,
607);
608
609impl<'a, T> Iterator for KeyOrderedIterMut<'a, T> {
610    type Item = (Key, &'a mut T);
611
612    fn next(&mut self) -> Option<Self::Item> {
613        let Self(it) = self;
614        it.filter_map(|(k, v)| match v {
615            DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) => Some((k, item)),
616            DenseMapEntry::Free(_) => None,
617        })
618        .next()
619    }
620}
621
622impl<'a, T> IntoIterator for &'a mut DenseMap<T> {
623    type Item = (Key, &'a mut T);
624    type IntoIter = KeyOrderedIterMut<'a, T>;
625
626    fn into_iter(self) -> Self::IntoIter {
627        KeyOrderedIterMut(self.data.iter_mut().enumerate())
628    }
629}
630
631/// A key providing an index into an [`DenseMap`].
632pub trait EntryKey {
633    /// Returns the index for this key.
634    fn get_key_index(&self) -> usize;
635}
636
637impl EntryKey for usize {
638    fn get_key_index(&self) -> usize {
639        *self
640    }
641}
642
643/// A view into a vacant entry in a map. It is part of the [`Entry`] enum.
644pub struct VacantEntry<'a, K, T> {
645    key: K,
646    id_map: &'a mut DenseMap<T>,
647}
648
649impl<'a, K, T> VacantEntry<'a, K, T> {
650    /// Sets the value of the entry with the VacantEntry's key, and returns a
651    /// mutable reference to it.
652    pub fn insert(self, value: T) -> &'a mut T
653    where
654        K: EntryKey,
655    {
656        assert!(self.id_map.insert(self.key.get_key_index(), value).is_none());
657        match &mut self.id_map.data[self.key.get_key_index()] {
658            DenseMapEntry::Allocated(AllocatedEntry { link: _, item }) => item,
659            DenseMapEntry::Free(_) => unreachable!("entry is known to be vacant"),
660        }
661    }
662
663    /// Gets a reference to the key that would be used when inserting a value
664    /// through the `VacantEntry`.
665    pub fn key(&self) -> &K {
666        &self.key
667    }
668
669    /// Take ownership of the key.
670    pub fn into_key(self) -> K {
671        self.key
672    }
673
674    /// Changes the key type of this `VacantEntry` to another key `X` that still
675    /// maps to the same index in an `DenseMap`.
676    ///
677    /// # Panics
678    ///
679    /// Panics if the resulting mapped key from `f` does not return the same
680    /// value for [`EntryKey::get_key_index`] as the old key did.
681    pub(crate) fn map_key<X, F>(self, f: F) -> VacantEntry<'a, X, T>
682    where
683        K: EntryKey,
684        X: EntryKey,
685        F: FnOnce(K) -> X,
686    {
687        let idx = self.key.get_key_index();
688        let key = f(self.key);
689        assert_eq!(idx, key.get_key_index());
690        VacantEntry { key, id_map: self.id_map }
691    }
692}
693
694/// A view into an occupied entry in a map. It is part of the [`Entry`] enum.
695pub struct OccupiedEntry<'a, K, T> {
696    key: K,
697    id_map: &'a mut DenseMap<T>,
698}
699
700impl<'a, K: EntryKey, T> OccupiedEntry<'a, K, T> {
701    /// Gets a reference to the key in the entry.
702    pub fn key(&self) -> &K {
703        &self.key
704    }
705
706    /// Leaves the value in the map and returns the key.
707    pub fn into_key(self) -> K {
708        self.key
709    }
710
711    /// Gets a reference to the value in the entry.
712    pub fn get(&self) -> &T {
713        // We can unwrap because value is always Some for OccupiedEntry.
714        self.id_map.get(self.key.get_key_index()).unwrap()
715    }
716
717    /// Gets a mutable reference to the value in the entry.
718    ///
719    /// If you need a reference to the `OccupiedEntry` which may outlive the
720    /// destruction of the entry value, see [`OccupiedEntry::into_mut`].
721    pub fn get_mut(&mut self) -> &mut T {
722        // We can unwrap because value is always Some for OccupiedEntry.
723        self.id_map.get_mut(self.key.get_key_index()).unwrap()
724    }
725
726    /// Converts the `OccupiedEntry` into a mutable reference to the value in
727    /// the entry with a lifetime bound to the map itself.
728    ///
729    /// If you need multiple references to the `OccupiedEntry`, see
730    /// [`OccupiedEntry::get_mut`].
731    pub fn into_mut(self) -> &'a mut T {
732        // We can unwrap because value is always Some for OccupiedEntry.
733        self.id_map.get_mut(self.key.get_key_index()).unwrap()
734    }
735
736    /// Sets the value of the entry, and returns the entry's old value.
737    pub fn insert(&mut self, value: T) -> T {
738        // We can unwrap because value is always Some for OccupiedEntry.
739        self.id_map.insert(self.key.get_key_index(), value).unwrap()
740    }
741
742    /// Takes the value out of the entry, and returns it.
743    pub fn remove(self) -> T {
744        // We can unwrap because value is always Some for OccupiedEntry.
745        self.id_map.remove(self.key.get_key_index()).unwrap()
746    }
747
748    /// Changes the key type of this `OccupiedEntry` to another key `X` that
749    /// still maps to the same index in an `DenseMap`.
750    ///
751    /// # Panics
752    ///
753    /// Panics if the resulting mapped key from `f` does not return the same
754    /// value for [`EntryKey::get_key_index`] as the old key did.
755    pub(crate) fn map_key<X, F>(self, f: F) -> OccupiedEntry<'a, X, T>
756    where
757        K: EntryKey,
758        X: EntryKey,
759        F: FnOnce(K) -> X,
760    {
761        let idx = self.key.get_key_index();
762        let key = f(self.key);
763        assert_eq!(idx, key.get_key_index());
764        OccupiedEntry { key, id_map: self.id_map }
765    }
766}
767
768impl<'a, K: Debug, T> Debug for OccupiedEntry<'a, K, T> {
769    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
770        let Self { key, id_map: _ } = self;
771        f.debug_struct("OccupiedEntry").field("key", key).field("id_map", &"_").finish()
772    }
773}
774
775/// A view into an in-place entry in a map that can be vacant or occupied.
776pub enum Entry<'a, K, T> {
777    /// A vacant entry.
778    Vacant(VacantEntry<'a, K, T>),
779    /// An occupied entry.
780    Occupied(OccupiedEntry<'a, K, T>),
781}
782
783impl<'a, K: EntryKey, T> Entry<'a, K, T> {
784    /// Returns a reference to this entry's key.
785    pub fn key(&self) -> &K {
786        match self {
787            Entry::Vacant(e) => e.key(),
788            Entry::Occupied(e) => e.key(),
789        }
790    }
791
792    /// Ensures a value is in the entry by inserting `default` if empty, and
793    /// returns a mutable reference to the value in the entry.
794    pub fn or_insert(self, default: T) -> &'a mut T
795    where
796        K: EntryKey,
797    {
798        match self {
799            Entry::Vacant(e) => e.insert(default),
800            Entry::Occupied(e) => e.into_mut(),
801        }
802    }
803
804    /// Ensures a value is in the entry by inserting the result of the function
805    /// `f` if empty, and returns a mutable reference to the value in the entry.
806    pub fn or_insert_with<F: FnOnce() -> T>(self, f: F) -> &'a mut T
807    where
808        K: EntryKey,
809    {
810        match self {
811            Entry::Vacant(e) => e.insert(f()),
812            Entry::Occupied(e) => e.into_mut(),
813        }
814    }
815
816    /// Ensures a value is in the entry by inserting the default value if empty,
817    /// and returns a mutable reference to the value in the entry.
818    pub fn or_default(self) -> &'a mut T
819    where
820        T: Default,
821        K: EntryKey,
822    {
823        self.or_insert_with(<T as Default>::default)
824    }
825
826    /// Provides in-place mutable access to an occupied entry before any
827    /// potential inserts into the map.
828    pub fn and_modify<F: FnOnce(&mut T)>(self, f: F) -> Self {
829        match self {
830            Entry::Vacant(e) => Entry::Vacant(e),
831            Entry::Occupied(mut e) => {
832                f(e.get_mut());
833                Entry::Occupied(e)
834            }
835        }
836    }
837
838    /// Remove the entry from [`DenseMap`].
839    pub fn remove(self) -> Option<T> {
840        match self {
841            Entry::Vacant(_) => None,
842            Entry::Occupied(e) => Some(e.remove()),
843        }
844    }
845}
846
847#[cfg(test)]
848mod tests {
849    use std::collections::HashMap;
850
851    use rand::seq::SliceRandom as _;
852
853    use crate::testutil::assert_empty;
854    use crate::DenseMapEntry::{Allocated, Free};
855    use crate::*;
856
857    // Smart constructors
858    fn free<T>(prev: usize, next: usize) -> DenseMapEntry<T> {
859        Free(ListLink { prev: Some(prev), next: Some(next) })
860    }
861
862    fn free_head<T>(next: usize) -> DenseMapEntry<T> {
863        Free(ListLink { prev: None, next: Some(next) })
864    }
865
866    fn free_tail<T>(prev: usize) -> DenseMapEntry<T> {
867        Free(ListLink { prev: Some(prev), next: None })
868    }
869
870    fn free_none<T>() -> DenseMapEntry<T> {
871        Free(ListLink::default())
872    }
873
874    #[test]
875    fn test_push() {
876        let mut map = DenseMap::new();
877        assert_eq!(map.insert(1, 2), None);
878        let DenseMap { data, freelist, allocatedlist } = &map;
879        assert_eq!(
880            data,
881            &vec![
882                free_none(),
883                Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 2 })
884            ]
885        );
886        assert_eq!(freelist, &Some(List::singleton(0)));
887        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 1 }));
888        assert_eq!(map.push(1), 0);
889        let DenseMap { data, freelist, allocatedlist } = &map;
890        assert_eq!(
891            data,
892            &vec![
893                Allocated(AllocatedEntry { link: ListLink { prev: Some(1), next: None }, item: 1 }),
894                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(0) }, item: 2 })
895            ]
896        );
897        assert_eq!(freelist, &None);
898        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 0 }));
899        assert_eq!(map.push(3), 2);
900        let DenseMap { data, freelist, allocatedlist } = &map;
901        assert_eq!(
902            data,
903            &vec![
904                Allocated(AllocatedEntry {
905                    link: ListLink { prev: Some(1), next: Some(2) },
906                    item: 1
907                }),
908                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(0) }, item: 2 }),
909                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 3 })
910            ]
911        );
912        assert_eq!(freelist, &None);
913        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 2 }));
914    }
915
916    #[test]
917    fn test_get() {
918        let mut map = DenseMap::new();
919        assert_eq!(map.push(1), 0);
920        assert_eq!(map.insert(2, 3), None);
921        let DenseMap { data, freelist, allocatedlist } = &map;
922        assert_eq!(
923            data,
924            &vec![
925                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(2) }, item: 1 }),
926                free_none(),
927                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 3 })
928            ]
929        );
930        assert_eq!(freelist, &Some(List::singleton(1)));
931        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 2 }));
932        assert_eq!(*map.get(0).unwrap(), 1);
933        assert_eq!(map.get(1), None);
934        assert_eq!(*map.get(2).unwrap(), 3);
935        assert_eq!(map.get(3), None);
936    }
937
938    #[test]
939    fn test_get_mut() {
940        let mut map = DenseMap::new();
941        assert_eq!(map.push(1), 0);
942        assert_eq!(map.insert(2, 3), None);
943        let DenseMap { data, freelist, allocatedlist } = &map;
944        assert_eq!(
945            data,
946            &vec![
947                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(2) }, item: 1 }),
948                free_none(),
949                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 3 })
950            ]
951        );
952        assert_eq!(freelist, &Some(List::singleton(1)));
953        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 2 }));
954        *map.get_mut(2).unwrap() = 10;
955        assert_eq!(*map.get(0).unwrap(), 1);
956        assert_eq!(*map.get(2).unwrap(), 10);
957
958        assert_eq!(map.get_mut(1), None);
959        assert_eq!(map.get_mut(3), None);
960    }
961
962    #[test]
963    fn test_is_empty() {
964        let mut map = DenseMap::<i32>::new();
965        assert!(map.is_empty());
966        assert_eq!(map.push(1), 0);
967        assert!(!map.is_empty());
968    }
969
970    #[test]
971    fn test_remove() {
972        let mut map = DenseMap::new();
973        assert_eq!(map.push(1), 0);
974        assert_eq!(map.push(2), 1);
975        assert_eq!(map.push(3), 2);
976        let DenseMap { data, freelist, allocatedlist } = &map;
977        assert_eq!(
978            data,
979            &vec![
980                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(1) }, item: 1 }),
981                Allocated(AllocatedEntry {
982                    link: ListLink { prev: Some(0), next: Some(2) },
983                    item: 2
984                }),
985                Allocated(AllocatedEntry { link: ListLink { prev: Some(1), next: None }, item: 3 })
986            ]
987        );
988        assert_eq!(freelist, &None);
989        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 2 }));
990        assert_eq!(map.remove(1).unwrap(), 2);
991
992        assert_eq!(map.remove(1), None);
993        let DenseMap { data, freelist, allocatedlist } = &map;
994        assert_eq!(
995            data,
996            &vec![
997                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(2) }, item: 1 }),
998                free_none(),
999                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 3 })
1000            ]
1001        );
1002        assert_eq!(freelist, &Some(List::singleton(1)));
1003        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 2 }));
1004    }
1005
1006    #[test]
1007    fn test_remove_compress() {
1008        let mut map = DenseMap::new();
1009        assert_eq!(map.insert(0, 1), None);
1010        assert_eq!(map.insert(2, 3), None);
1011        let DenseMap { data, freelist, allocatedlist } = &map;
1012        assert_eq!(
1013            data,
1014            &vec![
1015                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(2) }, item: 1 }),
1016                free_none(),
1017                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 3 })
1018            ]
1019        );
1020        assert_eq!(freelist, &Some(List::singleton(1)));
1021        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 2 }));
1022        assert_eq!(map.remove(2).unwrap(), 3);
1023        let DenseMap { data, freelist, allocatedlist } = &map;
1024        assert_eq!(
1025            data,
1026            &vec![Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 1 })]
1027        );
1028        assert_eq!(freelist, &None);
1029        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 0 }));
1030        assert_eq!(map.remove(0).unwrap(), 1);
1031        let DenseMap { data, freelist, allocatedlist } = &map;
1032        assert_empty(data);
1033        assert_eq!(freelist, &None);
1034        assert_eq!(allocatedlist, &None);
1035    }
1036
1037    #[test]
1038    fn test_insert() {
1039        let mut map = DenseMap::new();
1040        assert_eq!(map.insert(1, 2), None);
1041        let DenseMap { data, freelist, allocatedlist } = &map;
1042        assert_eq!(
1043            data,
1044            &vec![
1045                free_none(),
1046                Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 2 })
1047            ]
1048        );
1049        assert_eq!(freelist, &Some(List::singleton(0)));
1050        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 1 }));
1051        assert_eq!(map.insert(3, 4), None);
1052        let DenseMap { data, freelist, allocatedlist } = &map;
1053        assert_eq!(
1054            data,
1055            &vec![
1056                free_head(2),
1057                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 2 }),
1058                free_tail(0),
1059                Allocated(AllocatedEntry { link: ListLink { prev: Some(1), next: None }, item: 4 })
1060            ]
1061        );
1062        assert_eq!(freelist, &Some(List { head: 0, tail: 2 }));
1063        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 3 }));
1064        assert_eq!(map.insert(0, 1), None);
1065        let DenseMap { data, freelist, allocatedlist } = &map;
1066        assert_eq!(
1067            data,
1068            &vec![
1069                Allocated(AllocatedEntry { link: ListLink { prev: Some(3), next: None }, item: 1 }),
1070                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 2 }),
1071                free_none(),
1072                Allocated(AllocatedEntry {
1073                    link: ListLink { prev: Some(1), next: Some(0) },
1074                    item: 4
1075                })
1076            ]
1077        );
1078        assert_eq!(freelist, &Some(List::singleton(2)));
1079        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 0 }));
1080        assert_eq!(map.insert(3, 5).unwrap(), 4);
1081        let DenseMap { data, freelist, allocatedlist } = &map;
1082        assert_eq!(
1083            data,
1084            &vec![
1085                Allocated(AllocatedEntry {
1086                    link: ListLink { prev: Some(1), next: Some(3) },
1087                    item: 1
1088                }),
1089                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(0) }, item: 2 }),
1090                free_none(),
1091                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 5 })
1092            ]
1093        );
1094        assert_eq!(freelist, &Some(List::singleton(2)));
1095        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 3 }));
1096    }
1097
1098    #[test]
1099    fn test_insert_gap() {
1100        // Regression test for https://fxbug.dev/42171085: a sequence of inserts that creates a run of
1101        // free elements with size > 1 followed by removes can result in `freelist` = None even
1102        // though `data` contains ListLink entries.
1103        let mut map = DenseMap::new();
1104        assert_eq!(map.insert(0, 0), None);
1105        assert_eq!(map.insert(3, 5), None);
1106        let DenseMap { data, freelist, allocatedlist } = &map;
1107        assert_eq!(
1108            data,
1109            &vec![
1110                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 0 }),
1111                free_head(2),
1112                free_tail(1),
1113                Allocated(AllocatedEntry { link: ListLink { prev: Some(0), next: None }, item: 5 })
1114            ]
1115        );
1116        assert_eq!(freelist, &Some(List { head: 1, tail: 2 }));
1117        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 3 }));
1118
1119        assert_eq!(map.push(6), 1);
1120        assert_eq!(map.remove(1), Some(6));
1121        assert_eq!(map.remove(3), Some(5));
1122
1123        // The remove() call compresses the list, which leaves just the 0 element.
1124        let DenseMap { data, freelist, allocatedlist } = &map;
1125        assert_eq!(
1126            data,
1127            &vec![Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 0 })]
1128        );
1129        assert_eq!(freelist, &None);
1130        assert_eq!(allocatedlist, &Some(List { head: 0, tail: 0 }));
1131    }
1132
1133    #[test]
1134    fn test_key_ordered_iter() {
1135        let mut map = DenseMap::new();
1136        assert_eq!(map.insert(1, 0), None);
1137        assert_eq!(map.insert(3, 1), None);
1138        assert_eq!(map.insert(6, 2), None);
1139        let DenseMap { data, freelist, allocatedlist } = &map;
1140        assert_eq!(
1141            data,
1142            &vec![
1143                free_head(2),
1144                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 0 }),
1145                free(0, 4),
1146                Allocated(AllocatedEntry {
1147                    link: ListLink { prev: Some(1), next: Some(6) },
1148                    item: 1
1149                }),
1150                free(2, 5),
1151                free_tail(4),
1152                Allocated(AllocatedEntry { link: ListLink { prev: Some(3), next: None }, item: 2 }),
1153            ]
1154        );
1155        assert_eq!(freelist, &Some(List { head: 0, tail: 5 }));
1156        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 6 }));
1157        let mut c = 0;
1158        let mut last_k = None;
1159        for (i, (k, v)) in map.key_ordered_iter().enumerate() {
1160            assert_eq!(i, *v as usize);
1161            assert_eq!(map.get(k).unwrap(), v);
1162            assert!(last_k < Some(k));
1163            last_k = Some(k);
1164            c += 1;
1165        }
1166        assert_eq!(c, 3);
1167    }
1168
1169    #[test]
1170    fn test_insertion_ordered_iter() {
1171        let mut map = DenseMap::new();
1172        assert_eq!(map.insert(6, 0), None);
1173        assert_eq!(map.insert(3, 2), None);
1174        assert_eq!(map.push(1), 0);
1175        assert_eq!(map.insertion_ordered_iter().collect::<Vec<_>>(), [(6, &0), (3, &2), (0, &1)]);
1176
1177        assert_eq!(map.insert(3, 0), Some(2));
1178        assert_eq!(map.insertion_ordered_iter().collect::<Vec<_>>(), [(6, &0), (0, &1), (3, &0)]);
1179    }
1180
1181    #[test]
1182    fn test_iter_mut() {
1183        let mut map = DenseMap::new();
1184        assert_eq!(map.insert(1, 0), None);
1185        assert_eq!(map.insert(3, 1), None);
1186        assert_eq!(map.insert(6, 2), None);
1187        let DenseMap { data, freelist, allocatedlist } = &map;
1188        assert_eq!(
1189            data,
1190            &vec![
1191                free_head(2),
1192                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 0 }),
1193                free(0, 4),
1194                Allocated(AllocatedEntry {
1195                    link: ListLink { prev: Some(1), next: Some(6) },
1196                    item: 1
1197                }),
1198                free(2, 5),
1199                free_tail(4),
1200                Allocated(AllocatedEntry { link: ListLink { prev: Some(3), next: None }, item: 2 }),
1201            ]
1202        );
1203        assert_eq!(freelist, &Some(List { head: 0, tail: 5 }));
1204        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 6 }));
1205        let mut last_k = None;
1206        for (k, v) in map.key_ordered_iter_mut() {
1207            *v += k as u32;
1208            assert!(last_k < Some(k));
1209            last_k = Some(k);
1210        }
1211        let DenseMap { data, freelist, allocatedlist } = &map;
1212        assert_eq!(
1213            data,
1214            &vec![
1215                free_head(2),
1216                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 1 }),
1217                free(0, 4),
1218                Allocated(AllocatedEntry {
1219                    link: ListLink { prev: Some(1), next: Some(6) },
1220                    item: 4
1221                }),
1222                free(2, 5),
1223                free_tail(4),
1224                Allocated(AllocatedEntry { link: ListLink { prev: Some(3), next: None }, item: 8 }),
1225            ]
1226        );
1227        assert_eq!(freelist, &Some(List { head: 0, tail: 5 }));
1228        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 6 }));
1229    }
1230
1231    #[test]
1232    fn test_into_iter() {
1233        let mut map = DenseMap::new();
1234        assert_eq!(map.insert(1, 0), None);
1235        assert_eq!(map.insert(3, 1), None);
1236        assert_eq!(map.insert(6, 2), None);
1237        assert_eq!(map.into_iter().collect::<Vec<_>>(), &[(1, 0), (3, 1), (6, 2)]);
1238    }
1239
1240    #[test]
1241    fn test_key_ordered_retain() {
1242        // First, test that removed entries are actually removed, and that the
1243        // remaining entries are actually left there.
1244
1245        let mut map = DenseMap::new();
1246        for i in 0..8 {
1247            assert_eq!(map.push(i), i);
1248        }
1249
1250        // Keep only the odd entries.
1251        map.key_ordered_retain(|x: &usize| *x % 2 != 0);
1252        let remaining: Vec<_> =
1253            map.key_ordered_iter().map(|(key, entry)| (key, entry.clone())).collect();
1254        assert_eq!(remaining.as_slice(), [(1, 1), (3, 3), (5, 5), (7, 7)]);
1255
1256        let DenseMap { data, freelist, allocatedlist } = &map;
1257        assert_eq!(
1258            data,
1259            &[
1260                free_tail(2),
1261                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 1 }),
1262                free(4, 0),
1263                Allocated(AllocatedEntry {
1264                    link: ListLink { prev: Some(1), next: Some(5) },
1265                    item: 3
1266                }),
1267                free(6, 2),
1268                Allocated(AllocatedEntry {
1269                    link: ListLink { prev: Some(3), next: Some(7) },
1270                    item: 5
1271                }),
1272                free_head(4),
1273                Allocated(AllocatedEntry { link: ListLink { prev: Some(5), next: None }, item: 7 }),
1274            ]
1275        );
1276        assert_eq!(freelist, &Some(List { head: 6, tail: 0 }));
1277        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 7 }));
1278
1279        // Make sure that the underlying vector gets compressed.
1280        map.key_ordered_retain(|x| *x < 5);
1281        let DenseMap { data, freelist, allocatedlist } = &map;
1282        assert_eq!(
1283            data,
1284            &[
1285                free_tail(2),
1286                Allocated(AllocatedEntry { link: ListLink { prev: None, next: Some(3) }, item: 1 }),
1287                free_head(0),
1288                Allocated(AllocatedEntry { link: ListLink { prev: Some(1), next: None }, item: 3 }),
1289            ]
1290        );
1291        assert_eq!(freelist, &Some(List { head: 2, tail: 0 }));
1292        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 3 }));
1293    }
1294
1295    #[test]
1296    fn test_entry() {
1297        let mut map = DenseMap::new();
1298        assert_eq!(*map.entry(1).or_insert(2), 2);
1299        let DenseMap { data, freelist, allocatedlist } = &map;
1300        assert_eq!(
1301            data,
1302            &vec![
1303                free_none(),
1304                Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 2 })
1305            ]
1306        );
1307        assert_eq!(freelist, &Some(List::singleton(0)));
1308        assert_eq!(allocatedlist, &Some(List::singleton(1)));
1309        assert_eq!(
1310            *map.entry(1)
1311                .and_modify(|v| {
1312                    *v = 10;
1313                })
1314                .or_insert(5),
1315            10
1316        );
1317        let DenseMap { data, freelist, allocatedlist } = &map;
1318        assert_eq!(
1319            data,
1320            &vec![
1321                free_none(),
1322                Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 10 })
1323            ]
1324        );
1325        assert_eq!(freelist, &Some(List::singleton(0)));
1326        assert_eq!(allocatedlist, &Some(List::singleton(1)));
1327        assert_eq!(
1328            *map.entry(2)
1329                .and_modify(|v| {
1330                    *v = 10;
1331                })
1332                .or_insert(5),
1333            5
1334        );
1335        let DenseMap { data, freelist, allocatedlist } = &map;
1336        assert_eq!(
1337            data,
1338            &vec![
1339                free_none(),
1340                Allocated(AllocatedEntry {
1341                    link: ListLink { prev: None, next: Some(2) },
1342                    item: 10
1343                }),
1344                Allocated(AllocatedEntry { link: ListLink { prev: Some(1), next: None }, item: 5 }),
1345            ]
1346        );
1347        assert_eq!(freelist, &Some(List::singleton(0)));
1348        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 2 }));
1349        assert_eq!(*map.entry(4).or_default(), 0);
1350        let DenseMap { data, freelist, allocatedlist } = &map;
1351        assert_eq!(
1352            data,
1353            &vec![
1354                free_head(3),
1355                Allocated(AllocatedEntry {
1356                    link: ListLink { prev: None, next: Some(2) },
1357                    item: 10
1358                }),
1359                Allocated(AllocatedEntry {
1360                    link: ListLink { prev: Some(1), next: Some(4) },
1361                    item: 5
1362                }),
1363                free_tail(0),
1364                Allocated(AllocatedEntry { link: ListLink { prev: Some(2), next: None }, item: 0 })
1365            ]
1366        );
1367        assert_eq!(freelist, &Some(List { head: 0, tail: 3 }));
1368        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 4 }));
1369        assert_eq!(*map.entry(3).or_insert_with(|| 7), 7);
1370        let DenseMap { data, freelist, allocatedlist } = &map;
1371        assert_eq!(
1372            data,
1373            &vec![
1374                free_none(),
1375                Allocated(AllocatedEntry {
1376                    link: ListLink { prev: None, next: Some(2) },
1377                    item: 10
1378                }),
1379                Allocated(AllocatedEntry {
1380                    link: ListLink { prev: Some(1), next: Some(4) },
1381                    item: 5
1382                }),
1383                Allocated(AllocatedEntry { link: ListLink { prev: Some(4), next: None }, item: 7 }),
1384                Allocated(AllocatedEntry {
1385                    link: ListLink { prev: Some(2), next: Some(3) },
1386                    item: 0
1387                })
1388            ]
1389        );
1390        assert_eq!(freelist, &Some(List::singleton(0)));
1391        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 3 }));
1392        assert_eq!(*map.entry(0).or_insert(1), 1);
1393        let DenseMap { data, freelist, allocatedlist } = &map;
1394        assert_eq!(
1395            data,
1396            &vec![
1397                Allocated(AllocatedEntry { link: ListLink { prev: Some(3), next: None }, item: 1 }),
1398                Allocated(AllocatedEntry {
1399                    link: ListLink { prev: None, next: Some(2) },
1400                    item: 10
1401                }),
1402                Allocated(AllocatedEntry {
1403                    link: ListLink { prev: Some(1), next: Some(4) },
1404                    item: 5
1405                }),
1406                Allocated(AllocatedEntry {
1407                    link: ListLink { prev: Some(4), next: Some(0) },
1408                    item: 7
1409                }),
1410                Allocated(AllocatedEntry {
1411                    link: ListLink { prev: Some(2), next: Some(3) },
1412                    item: 0
1413                })
1414            ]
1415        );
1416        assert_eq!(freelist, &None);
1417        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 0 }));
1418        match map.entry(0) {
1419            Entry::Occupied(mut e) => {
1420                assert_eq!(*e.key(), 0);
1421                assert_eq!(*e.get(), 1);
1422                *e.get_mut() = 2;
1423                assert_eq!(*e.get(), 2);
1424                assert_eq!(e.remove(), 2);
1425            }
1426            _ => panic!("Wrong entry type, should be occupied"),
1427        }
1428        let DenseMap { data, freelist, allocatedlist } = &map;
1429        assert_eq!(
1430            data,
1431            &vec![
1432                free_none(),
1433                Allocated(AllocatedEntry {
1434                    link: ListLink { prev: None, next: Some(2) },
1435                    item: 10
1436                }),
1437                Allocated(AllocatedEntry {
1438                    link: ListLink { prev: Some(1), next: Some(4) },
1439                    item: 5
1440                }),
1441                Allocated(AllocatedEntry { link: ListLink { prev: Some(4), next: None }, item: 7 }),
1442                Allocated(AllocatedEntry {
1443                    link: ListLink { prev: Some(2), next: Some(3) },
1444                    item: 0
1445                })
1446            ]
1447        );
1448        assert_eq!(freelist, &Some(List::singleton(0)));
1449        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 3 }));
1450
1451        match map.entry(0) {
1452            Entry::Vacant(e) => {
1453                assert_eq!(*e.key(), 0);
1454                assert_eq!(*e.insert(4), 4);
1455            }
1456            _ => panic!("Wrong entry type, should be vacant"),
1457        }
1458        let DenseMap { data, freelist, allocatedlist } = &map;
1459        assert_eq!(
1460            data,
1461            &vec![
1462                Allocated(AllocatedEntry { link: ListLink { prev: Some(3), next: None }, item: 4 }),
1463                Allocated(AllocatedEntry {
1464                    link: ListLink { prev: None, next: Some(2) },
1465                    item: 10
1466                }),
1467                Allocated(AllocatedEntry {
1468                    link: ListLink { prev: Some(1), next: Some(4) },
1469                    item: 5
1470                }),
1471                Allocated(AllocatedEntry {
1472                    link: ListLink { prev: Some(4), next: Some(0) },
1473                    item: 7
1474                }),
1475                Allocated(AllocatedEntry {
1476                    link: ListLink { prev: Some(2), next: Some(3) },
1477                    item: 0
1478                })
1479            ]
1480        );
1481        assert_eq!(freelist, &None);
1482        assert_eq!(allocatedlist, &Some(List { head: 1, tail: 0 }));
1483    }
1484
1485    #[test]
1486    fn test_freelist_order() {
1487        let mut rng = crate::testutil::new_rng(1234981);
1488        const NELEMS: usize = 1_000;
1489        for _ in 0..1_000 {
1490            let mut map = DenseMap::new();
1491            for i in 0..NELEMS {
1492                assert_eq!(map.push(i), i);
1493            }
1494            // Don't remove the last one to prevent compressing.
1495            let mut remove_seq: Vec<usize> = (0..NELEMS - 1).collect();
1496            remove_seq.shuffle(&mut rng);
1497            for i in &remove_seq {
1498                assert_ne!(map.remove(*i), None);
1499            }
1500            for i in remove_seq.iter().rev() {
1501                // We should be able to push into the array in the same order.
1502                assert_eq!(map.push(*i), *i);
1503            }
1504            assert_ne!(map.remove(NELEMS - 1), None);
1505            for i in &remove_seq {
1506                assert_ne!(map.remove(*i), None);
1507            }
1508            assert_empty(map.key_ordered_iter());
1509        }
1510    }
1511
1512    #[test]
1513    fn test_compress_freelist() {
1514        let mut map = DenseMap::new();
1515        for i in 0..100 {
1516            assert_eq!(map.push(0), i);
1517        }
1518        for i in 0..100 {
1519            assert_eq!(map.remove(i), Some(0));
1520        }
1521        let DenseMap { data, freelist, allocatedlist } = &map;
1522        assert_empty(data.iter());
1523        assert_eq!(freelist, &None);
1524        assert_eq!(allocatedlist, &None);
1525    }
1526
1527    #[test]
1528    fn test_insert_beyond_end_freelist() {
1529        let mut map = DenseMap::new();
1530        for i in 0..10 {
1531            assert_eq!(map.insert(2 * i + 1, 0), None);
1532        }
1533        for i in 0..10 {
1534            assert_eq!(map.push(1), 2 * i);
1535        }
1536    }
1537
1538    #[test]
1539    fn test_double_free() {
1540        const MAX_KEY: usize = 100;
1541        let mut map1 = DenseMap::new();
1542        assert_eq!(map1.insert(MAX_KEY, 2), None);
1543        let mut map2 = DenseMap::new();
1544        assert_eq!(map2.insert(MAX_KEY, 2), None);
1545        for i in 0..MAX_KEY {
1546            assert_eq!(map1.remove(i), None);
1547            // Removing an already free entry should be a no-op.
1548            assert_eq!(map1.data, map2.data);
1549            assert_eq!(map1.freelist, map2.freelist);
1550        }
1551    }
1552
1553    #[derive(Debug)]
1554    enum Operation<K, V> {
1555        Get { key: K },
1556        Insert { key: K, value: V },
1557        Remove { key: K },
1558        Push { value: V },
1559    }
1560
1561    impl<V> Operation<usize, V>
1562    where
1563        V: Copy + core::cmp::PartialEq + core::fmt::Debug,
1564    {
1565        fn apply(self, map: &mut DenseMap<V>, source_of_truth: &mut HashMap<usize, V>) {
1566            match self {
1567                Self::Get { key } => {
1568                    assert_eq!(
1569                        map.get(key),
1570                        source_of_truth.get(&key),
1571                        "key={} map.get == truth.get",
1572                        key
1573                    );
1574                }
1575                Self::Insert { key, value } => {
1576                    assert_eq!(
1577                        map.insert(key, value),
1578                        source_of_truth.insert(key, value),
1579                        "key={}, map.insert == truth.insert",
1580                        key
1581                    );
1582                }
1583                Self::Remove { key } => {
1584                    assert_eq!(
1585                        map.remove(key),
1586                        source_of_truth.remove(&key),
1587                        "key={} map.remove == truth.remove",
1588                        key,
1589                    );
1590                }
1591                Self::Push { value } => {
1592                    let key = map.push(value);
1593                    assert_eq!(
1594                        source_of_truth.insert(key, value),
1595                        None,
1596                        "pushed key={}, value={:?}",
1597                        key,
1598                        value
1599                    );
1600                }
1601            }
1602        }
1603    }
1604
1605    use proptest::strategy::Strategy;
1606
1607    fn operation_strategy() -> impl Strategy<Value = Operation<usize, i32>> {
1608        let key_strategy = || 0..20usize;
1609        // Use a small range for values since we don't do anything fancy with them
1610        // so a larger range probably won't expose additional issues.
1611        let value_strategy = || 0..10i32;
1612
1613        proptest::prop_oneof![
1614            key_strategy().prop_map(|key| Operation::Get { key }),
1615            (key_strategy(), value_strategy())
1616                .prop_map(|(key, value)| Operation::Insert { key, value }),
1617            key_strategy().prop_map(|key| Operation::Remove { key }),
1618            value_strategy().prop_map(|value| Operation::Push { value }),
1619        ]
1620    }
1621
1622    fn find_elements<T>(
1623        data: &[DenseMapEntry<T>],
1624        get_link: impl Fn(&DenseMapEntry<T>) -> Option<&ListLink>,
1625    ) -> Vec<usize> {
1626        let head = data.iter().enumerate().find_map(|(i, e)| {
1627            let link = get_link(e)?;
1628            let ListLink { prev, next: _ } = link;
1629            if prev == &None {
1630                Some((i, *link))
1631            } else {
1632                None
1633            }
1634        });
1635        let mut found = Vec::new();
1636        let mut next = head;
1637
1638        // Traverse the free list, collecting all indices into `found`.
1639        while let Some((index, link)) = next {
1640            found.push(index);
1641            next = link.next.map(|next_i| {
1642                let next_entry =
1643                    *get_link(&data[next_i]).expect("entry should match target link type");
1644                assert_eq!(Some(index), next_entry.prev, "data[{}] and data[{}]", index, next_i);
1645                (next_i, next_entry)
1646            })
1647        }
1648
1649        // The freelist should contain all of the free data elements.
1650        data.iter().enumerate().for_each(|(i, e)| {
1651            assert_eq!(
1652                found.contains(&i),
1653                get_link(e).is_some(),
1654                "data[{}] should be in found list if link type matches",
1655                i,
1656            )
1657        });
1658        found
1659    }
1660
1661    /// Searches through the given data entries to identify the free list. Returns the indices of
1662    /// elements in the free list in order, panicking if there is any inconsistency in the list.
1663    fn find_free_elements<T>(data: &[DenseMapEntry<T>]) -> Vec<usize> {
1664        find_elements(data, |entry| match entry {
1665            DenseMapEntry::Free(link) => Some(link),
1666            DenseMapEntry::Allocated(_) => None,
1667        })
1668    }
1669
1670    /// Searches through the given data entries to identify the allocated list. Returns the indices of
1671    /// elements in the allocated list in order, panicking if there is any inconsistency in the list.
1672    fn find_allocated_elements<T>(data: &[DenseMapEntry<T>]) -> Vec<usize> {
1673        find_elements(data, |entry| match entry {
1674            DenseMapEntry::Allocated(AllocatedEntry { item: _, link }) => Some(link),
1675            DenseMapEntry::Free(_) => None,
1676        })
1677    }
1678
1679    #[test]
1680    fn test_find_free_elements() {
1681        let data = vec![
1682            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 1 }),
1683            free_tail(2),
1684            free(3, 1),
1685            free_head(2),
1686        ];
1687        assert_eq!(find_free_elements(&data), vec![3, 2, 1]);
1688    }
1689
1690    #[test]
1691    fn test_find_free_elements_none_free() {
1692        let data = vec![
1693            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 1 }),
1694            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 2 }),
1695            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 3 }),
1696            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 2 }),
1697        ];
1698        assert_eq!(find_free_elements(&data), vec![]);
1699    }
1700
1701    #[test]
1702    #[should_panic(expected = "entry should match target link type")]
1703    fn test_find_free_elements_includes_allocated() {
1704        let data = vec![
1705            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 1 }),
1706            free_head(0),
1707            free_tail(0),
1708        ];
1709        let _ = find_free_elements(&data);
1710    }
1711
1712    #[test]
1713    #[should_panic(expected = "should be in found list if link type matches")]
1714    fn test_find_free_elements_in_cycle() {
1715        let data = vec![
1716            free(2, 1),
1717            free(0, 2),
1718            free(1, 0),
1719            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 5 }),
1720        ];
1721        let _ = find_free_elements(&data);
1722    }
1723
1724    #[test]
1725    #[should_panic(expected = "should be in found list if link type matches")]
1726    fn test_find_free_elements_multiple_lists() {
1727        let data = vec![
1728            free_head(1),
1729            free_tail(0),
1730            Allocated(AllocatedEntry { link: ListLink { prev: None, next: None }, item: 13 }),
1731            free_head(4),
1732            free_tail(3),
1733        ];
1734        let _ = find_free_elements(&data);
1735    }
1736
1737    proptest::proptest! {
1738        #![proptest_config(proptest::test_runner::Config {
1739            // Add all failed seeds here.
1740            failure_persistence: proptest_support::failed_seeds!(),
1741            ..proptest::test_runner::Config::default()
1742        })]
1743
1744        #[test]
1745        fn test_arbitrary_operations(operations in proptest::collection::vec(operation_strategy(), 10)) {
1746            let mut map = DenseMap::new();
1747            let mut reference = HashMap::new();
1748            for op in operations {
1749                op.apply(&mut map, &mut reference);
1750
1751                // Now check the invariants that the map should be guaranteeing.
1752                let DenseMap { data, freelist, allocatedlist } = &map;
1753
1754                match freelist {
1755                    None => {
1756                        // No freelist means all nodes are allocated.
1757                        data.iter().enumerate().for_each(|(i, d)| match d {
1758                            DenseMapEntry::Free(_) => panic!("no freelist but data[{}] is free", i),
1759                            DenseMapEntry::Allocated(_) => (),
1760                        })
1761                    },
1762                    Some(List {head, tail}) => {
1763                        let free = find_free_elements(data);
1764                        assert_eq!(free.first(), Some(head));
1765                        assert_eq!(free.last(), Some(tail));
1766                    }
1767                }
1768
1769                match allocatedlist {
1770                    None => {
1771                        // No allocatedlist means all nodes are free.
1772                        data.iter().enumerate().for_each(|(i, d)| match d {
1773                            DenseMapEntry::Allocated(_) => panic!("no allocatedlist but data[{}] is allocated", i),
1774                            DenseMapEntry::Free(_) => (),
1775                        })
1776                    },
1777                    Some(List {head, tail}) => {
1778                        let allocated = find_allocated_elements(data);
1779                        assert_eq!(allocated.first(), Some(head));
1780                        assert_eq!(allocated.last(), Some(tail));
1781                    }
1782                }
1783            }
1784
1785            // After all operations have completed, the contents of the map should match the source of truth.
1786            let elements : HashMap<_, i32> = map.key_ordered_iter().map(|(a, b)| (a, *b)).collect();
1787            assert_eq!(elements, reference);
1788        }
1789    }
1790}