dense_map/
collection.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 collection of [`DenseMap`]s.
6//!
7//! Defines [`DenseMapCollection`], which is a generic map collection that can be
8//! keyed on [`DenseMapCollectionKey`], which is a two-level key structure.
9
10use alloc::vec::Vec;
11use core::num::NonZeroUsize;
12
13use crate::{DenseMap, EntryKey};
14
15/// A key that can index items in [`DenseMapCollection`].
16///
17/// A `DenseMapCollectionKey` is a key with two levels: `variant` and `id`. The
18/// number of `variant`s must be fixed and known at compile time, and is
19/// typically mapped to a number of `enum` variants (nested or not).
20pub trait DenseMapCollectionKey {
21    /// The number of variants this key supports.
22    const VARIANT_COUNT: NonZeroUsize;
23
24    /// Get the variant index for this key.
25    ///
26    /// # Panics
27    ///
28    /// Callers may assume that `get_variant` returns a value in the range `[0,
29    /// VARIANT_COUNT)`, and may panic if that assumption is violated.
30    fn get_variant(&self) -> usize;
31
32    /// Get the id index for this key.
33    fn get_id(&self) -> usize;
34}
35
36impl<O> EntryKey for O
37where
38    O: DenseMapCollectionKey,
39{
40    fn get_key_index(&self) -> usize {
41        <O as DenseMapCollectionKey>::get_id(self)
42    }
43}
44
45/// A vacant entry from a [`DenseMapCollection`].
46pub struct VacantEntry<'a, K, T> {
47    entry: crate::VacantEntry<'a, K, T>,
48    count: &'a mut usize,
49}
50
51impl<'a, K, T> VacantEntry<'a, K, T> {
52    /// Sets the value of the entry with the VacantEntry's key, and returns a
53    /// mutable reference to it.
54    pub fn insert(self, value: T) -> &'a mut T
55    where
56        K: EntryKey,
57    {
58        let Self { entry, count } = self;
59        *count += 1;
60        entry.insert(value)
61    }
62
63    /// Gets a reference to the key that would be used when inserting a value
64    /// through the `VacantEntry`.
65    pub fn key(&self) -> &K {
66        self.entry.key()
67    }
68
69    /// Take ownership of the key.
70    pub fn into_key(self) -> K {
71        self.entry.into_key()
72    }
73
74    /// Changes the key type of this `VacantEntry` to another key `X` that still
75    /// maps to the same index in a `DenseMap`.
76    ///
77    /// # Panics
78    ///
79    /// Panics if the resulting mapped key from `f` does not return the same
80    /// value for [`EntryKey::get_key_index`] as the old key did.
81    pub(crate) fn map_key<X, F>(self, f: F) -> VacantEntry<'a, X, T>
82    where
83        K: EntryKey,
84        X: EntryKey,
85        F: FnOnce(K) -> X,
86    {
87        let Self { entry, count } = self;
88        VacantEntry { entry: entry.map_key(f), count }
89    }
90}
91
92/// An occupied entry from a [`DenseMapCollection`].
93#[derive(Debug)]
94pub struct OccupiedEntry<'a, K, T> {
95    entry: crate::OccupiedEntry<'a, K, T>,
96    count: &'a mut usize,
97}
98
99impl<'a, K: EntryKey, T> OccupiedEntry<'a, K, T> {
100    /// Gets a reference to the key in the entry.
101    pub fn key(&self) -> &K {
102        self.entry.key()
103    }
104
105    /// Leaves the value in the map and produces the key.
106    pub fn into_key(self) -> K {
107        self.entry.into_key()
108    }
109
110    /// Gets a reference to the value in the entry.
111    pub fn get(&self) -> &T {
112        self.entry.get()
113    }
114
115    /// Gets a mutable reference to the value in the entry.
116    ///
117    /// If you need a reference to the `OccupiedEntry` which may outlive the
118    /// destruction of the entry value, see [`OccupiedEntry::into_mut`].
119    pub fn get_mut(&mut self) -> &mut T {
120        self.entry.get_mut()
121    }
122
123    /// Converts the `OccupiedEntry` into a mutable reference to the value in
124    /// the entry with a lifetime bound to the map itself.
125    ///
126    /// If you need multiple references to the `OccupiedEntry`, see
127    /// [`OccupiedEntry::get_mut`].
128    pub fn into_mut(self) -> &'a mut T {
129        self.entry.into_mut()
130    }
131
132    /// Sets the value of the entry, and returns the entry's old value.
133    pub fn insert(&mut self, value: T) -> T {
134        self.entry.insert(value)
135    }
136
137    /// Takes the value out of the entry, and returns it.
138    pub fn remove(self) -> T {
139        let Self { entry, count } = self;
140        *count -= 1;
141        entry.remove()
142    }
143
144    /// Changes the key type of this `OccupiedEntry` to another key `X` that
145    /// still maps to the same value.
146    ///
147    /// # Panics
148    ///
149    /// Panics if the resulting mapped key from `f` does not return the same
150    /// value for [`EntryKey::get_key_index`] as the old key did.
151    pub(crate) fn map_key<X, F>(self, f: F) -> OccupiedEntry<'a, X, T>
152    where
153        K: EntryKey,
154        X: EntryKey,
155        F: FnOnce(K) -> X,
156    {
157        let Self { entry, count } = self;
158        OccupiedEntry { entry: entry.map_key(f), count }
159    }
160}
161
162/// A view into an in-place entry in a map that can be vacant or occupied.
163pub enum Entry<'a, K, T> {
164    /// A vacant entry.
165    Vacant(VacantEntry<'a, K, T>),
166    /// An occupied entry.
167    Occupied(OccupiedEntry<'a, K, T>),
168}
169
170impl<'a, K: EntryKey, T> Entry<'a, K, T> {
171    /// Returns a reference to this entry's key.
172    pub fn key(&self) -> &K {
173        match self {
174            Entry::Occupied(e) => e.key(),
175            Entry::Vacant(e) => e.key(),
176        }
177    }
178
179    /// Ensures a value is in the entry by inserting `default` if empty, and
180    /// returns a mutable reference to the value in the entry.
181    pub fn or_insert(self, default: T) -> &'a mut T
182    where
183        K: EntryKey,
184    {
185        self.or_insert_with(|| default)
186    }
187
188    /// Ensures a value is in the entry by inserting the result of the function
189    /// `f` if empty, and returns a mutable reference to the value in the entry.
190    pub fn or_insert_with<F: FnOnce() -> T>(self, f: F) -> &'a mut T {
191        match self {
192            Entry::Occupied(e) => e.into_mut(),
193            Entry::Vacant(e) => e.insert(f()),
194        }
195    }
196
197    /// Ensures a value is in the entry by inserting the default value if empty,
198    /// and returns a mutable reference to the value in the entry.
199    pub fn or_default(self) -> &'a mut T
200    where
201        T: Default,
202        K: EntryKey,
203    {
204        self.or_insert_with(<T as Default>::default)
205    }
206
207    /// Provides in-place mutable access to an occupied entry before any
208    /// potential inserts into the map.
209    pub fn and_modify<F: FnOnce(&mut T)>(self, f: F) -> Self {
210        match self {
211            Entry::Occupied(mut e) => {
212                f(e.get_mut());
213                Entry::Occupied(e)
214            }
215            Entry::Vacant(e) => Entry::Vacant(e),
216        }
217    }
218
219    /// Removes the entry from the [`DenseMapCollection`].
220    ///
221    /// Returns [`Some`] if the entry was occupied, otherwise [`None`].
222    pub fn remove(self) -> Option<T> {
223        match self {
224            Entry::Vacant(_) => None,
225            Entry::Occupied(e) => Some(e.remove()),
226        }
227    }
228}
229
230/// An iterator wrapper used to implement ExactSizeIterator.
231///
232/// Wraps an iterator of type `I`, keeping track of the number of elements it
233/// is expected to produce.
234struct SizeAugmentedIterator<I> {
235    wrapped: I,
236    remaining: usize,
237}
238
239impl<I: Iterator> Iterator for SizeAugmentedIterator<I> {
240    type Item = I::Item;
241
242    fn next(&mut self) -> Option<Self::Item> {
243        let Self { wrapped, remaining } = self;
244        match wrapped.next() {
245            Some(v) => {
246                *remaining -= 1;
247                Some(v)
248            }
249            None => {
250                assert_eq!(remaining, &0);
251                None
252            }
253        }
254    }
255
256    fn size_hint(&self) -> (usize, Option<usize>) {
257        (self.remaining, Some(self.remaining))
258    }
259}
260
261impl<I: Iterator> ExactSizeIterator for SizeAugmentedIterator<I> {}
262
263/// A generic collection indexed by a [`DenseMapCollectionKey`].
264///
265/// `DenseMapCollection` provides the same performance guarantees as [`DenseMap`], but
266/// provides a two-level keying scheme that matches the pattern used in
267/// [`crate::DeviceDense`].
268pub struct DenseMapCollection<K: DenseMapCollectionKey, T> {
269    // TODO(brunodalbo): we define a vector container here because we can't just
270    // define a fixed array length based on an associated const in
271    // DenseMapCollectionKey. When rust issue #43408 gets resolved we can switch
272    // this to use the associated const and just have a fixed length array.
273    data: Vec<DenseMap<T>>,
274    count: usize,
275    _marker: core::marker::PhantomData<K>,
276}
277
278impl<K: DenseMapCollectionKey, T> DenseMapCollection<K, T> {
279    /// Creates a new empty `DenseMapCollection`.
280    pub fn new() -> Self {
281        let mut data = Vec::new();
282        data.resize_with(K::VARIANT_COUNT.get(), DenseMap::default);
283        Self { data, count: 0, _marker: core::marker::PhantomData }
284    }
285
286    fn get_map(&self, key: &K) -> &DenseMap<T> {
287        &self.data[key.get_variant()]
288    }
289
290    fn get_entry(&mut self, key: &K) -> Entry<'_, usize, T> {
291        let Self { data, count, _marker } = self;
292        match data[key.get_variant()].entry(key.get_id()) {
293            crate::Entry::Occupied(entry) => Entry::Occupied(OccupiedEntry { entry, count }),
294            crate::Entry::Vacant(entry) => Entry::Vacant(VacantEntry { entry, count }),
295        }
296    }
297
298    /// Returns `true` if the `DenseMapCollection` holds no items.
299    pub fn is_empty(&self) -> bool {
300        let Self { count, data: _, _marker } = self;
301        *count == 0
302    }
303
304    /// Returns a reference to the item indexed by `key`, or `None` if the `key`
305    /// doesn't exist.
306    pub fn get(&self, key: &K) -> Option<&T> {
307        self.get_map(key).get(key.get_id())
308    }
309
310    /// Returns a mutable reference to the item indexed by `key`, or `None` if
311    /// the `key` doesn't exist.
312    pub fn get_mut(&mut self, key: &K) -> Option<&mut T> {
313        match self.get_entry(key) {
314            Entry::Occupied(e) => Some(e.into_mut()),
315            Entry::Vacant(_) => None,
316        }
317    }
318
319    /// Removes item indexed by `key` from the container.
320    ///
321    /// Returns the removed item if it exists, or `None` otherwise.
322    pub fn remove(&mut self, key: &K) -> Option<T> {
323        match self.get_entry(key) {
324            Entry::Occupied(e) => Some(e.remove()),
325            Entry::Vacant(_) => None,
326        }
327    }
328
329    /// Inserts `item` at `key`.
330    ///
331    /// If the [`DenseMapCollection`] already contained an item indexed by `key`,
332    /// `insert` returns it, or `None` otherwise.
333    pub fn insert(&mut self, key: &K, item: T) -> Option<T> {
334        match self.get_entry(key) {
335            Entry::Occupied(mut e) => Some(e.insert(item)),
336            Entry::Vacant(e) => {
337                let _: &mut T = e.insert(item);
338                None
339            }
340        }
341    }
342
343    /// Creates an iterator over the containing items.
344    pub fn iter(&self) -> impl ExactSizeIterator<Item = &T> {
345        let Self { data, count, _marker } = self;
346        SizeAugmentedIterator {
347            wrapped: data.iter().flat_map(|m| m.key_ordered_iter()).map(|(_, v)| v),
348            remaining: *count,
349        }
350    }
351
352    /// Creates a mutable iterator over the containing items.
353    pub fn iter_mut(&mut self) -> impl ExactSizeIterator<Item = &mut T> {
354        let Self { data, count, _marker } = self;
355        SizeAugmentedIterator {
356            wrapped: data.iter_mut().flat_map(|m| m.key_ordered_iter_mut()).map(|(_, v)| v),
357            remaining: *count,
358        }
359    }
360
361    /// Creates an iterator over the maps in variant order.
362    pub fn iter_maps(&self) -> impl Iterator<Item = &DenseMap<T>> {
363        let Self { data, count: _, _marker } = self;
364        data.iter()
365    }
366
367    /// Gets the given key's corresponding entry in the map for in-place
368    /// manipulation.
369    pub fn entry(&mut self, key: K) -> Entry<'_, K, T> {
370        match self.get_entry(&key) {
371            Entry::Occupied(e) => Entry::Occupied(e.map_key(|_| key)),
372            Entry::Vacant(e) => Entry::Vacant(e.map_key(|_| key)),
373        }
374    }
375
376    /// Inserts a new entry, constructing a key with the provided function.
377    ///
378    /// # Panics
379    ///
380    /// The `make_key` function _must_ always construct keys of the same
381    /// variant, otherwise this method will panic.
382    pub fn push_entry(&mut self, make_key: fn(usize) -> K, value: T) -> OccupiedEntry<'_, K, T> {
383        let Self { count, data, _marker } = self;
384        let variant = make_key(0).get_variant();
385        let entry = data[variant].push_entry(value);
386        *count += 1;
387
388        let entry = entry.map_key(make_key);
389
390        let entry_variant = entry.key().get_variant();
391        assert_eq!(
392            entry_variant, variant,
393            "key variant is inconsistent; got both {variant} and {entry_variant}"
394        );
395        OccupiedEntry { entry, count }
396    }
397}
398
399impl<K: DenseMapCollectionKey, T> Default for DenseMapCollection<K, T> {
400    fn default() -> Self {
401        Self::new()
402    }
403}
404
405#[cfg(test)]
406mod tests {
407    use alloc::collections::HashSet;
408
409    use super::*;
410    use crate::testutil::assert_empty;
411
412    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
413    enum FakeVariants {
414        A,
415        B,
416        C,
417    }
418
419    #[derive(Copy, Clone, Eq, PartialEq, Debug)]
420    struct FakeKey {
421        id: usize,
422        var: FakeVariants,
423    }
424
425    impl FakeKey {
426        const fn new(id: usize, var: FakeVariants) -> Self {
427            Self { id, var }
428        }
429    }
430
431    impl DenseMapCollectionKey for FakeKey {
432        const VARIANT_COUNT: NonZeroUsize = NonZeroUsize::new(3).unwrap();
433
434        fn get_variant(&self) -> usize {
435            match self.var {
436                FakeVariants::A => 0,
437                FakeVariants::B => 1,
438                FakeVariants::C => 2,
439            }
440        }
441
442        fn get_id(&self) -> usize {
443            self.id
444        }
445    }
446
447    type TestCollection = DenseMapCollection<FakeKey, i32>;
448
449    const KEY_A: FakeKey = FakeKey::new(0, FakeVariants::A);
450    const KEY_B: FakeKey = FakeKey::new(2, FakeVariants::B);
451    const KEY_C: FakeKey = FakeKey::new(4, FakeVariants::C);
452
453    #[test]
454    fn test_insert_and_get() {
455        let mut t = TestCollection::new();
456        let DenseMapCollection { data, count, _marker } = &t;
457        assert_empty(data[0].key_ordered_iter());
458        assert_empty(data[1].key_ordered_iter());
459        assert_empty(data[2].key_ordered_iter());
460        assert_eq!(count, &0);
461
462        assert_eq!(t.insert(&KEY_A, 1), None);
463        let DenseMapCollection { data, count, _marker } = &t;
464        assert!(!data[0].is_empty());
465        assert_eq!(count, &1);
466
467        assert_eq!(t.insert(&KEY_B, 2), None);
468        let DenseMapCollection { data, count, _marker } = &t;
469        assert!(!data[1].is_empty());
470        assert_eq!(count, &2);
471
472        assert_eq!(*t.get(&KEY_A).unwrap(), 1);
473        assert_eq!(t.get(&KEY_C), None);
474
475        *t.get_mut(&KEY_B).unwrap() = 3;
476        assert_eq!(*t.get(&KEY_B).unwrap(), 3);
477    }
478
479    #[test]
480    fn test_remove() {
481        let mut t = TestCollection::new();
482        assert_eq!(t.insert(&KEY_B, 15), None);
483        assert_eq!(t.remove(&KEY_B).unwrap(), 15);
484        let DenseMapCollection { data: _, count, _marker } = &t;
485        assert_eq!(count, &0);
486
487        assert_eq!(t.remove(&KEY_B), None);
488    }
489
490    #[test]
491    fn test_iter() {
492        let mut t = TestCollection::new();
493        assert_eq!(t.insert(&KEY_A, 15), None);
494        assert_eq!(t.insert(&KEY_B, -5), None);
495        assert_eq!(t.insert(&KEY_C, -10), None);
496        let mut c = 0;
497        let mut sum = 0;
498        for i in t.iter() {
499            c += 1;
500            sum += *i;
501        }
502        assert_eq!(c, 3);
503        assert_eq!(sum, 0);
504    }
505
506    #[test]
507    fn test_iter_len() {
508        let mut t = TestCollection::new();
509        assert_eq!(t.insert(&KEY_A, 1), None);
510        assert_eq!(t.insert(&KEY_B, 1), None);
511        assert_eq!(t.insert(&KEY_C, 1), None);
512        assert_eq!(t.iter().len(), 3);
513        assert_eq!(t.remove(&KEY_A), Some(1));
514        assert_eq!(t.iter().len(), 2);
515    }
516
517    #[test]
518    fn test_is_empty() {
519        let mut t = TestCollection::new();
520        assert!(t.is_empty());
521        assert_eq!(t.insert(&KEY_B, 15), None);
522        assert!(!t.is_empty());
523    }
524
525    #[test]
526    fn test_iter_mut() {
527        let mut t = TestCollection::new();
528        assert_eq!(t.insert(&KEY_A, 15), None);
529        assert_eq!(t.insert(&KEY_B, -5), None);
530        assert_eq!(t.insert(&KEY_C, -10), None);
531        for i in t.iter_mut() {
532            *i *= 2;
533        }
534        assert_eq!(*t.get(&KEY_A).unwrap(), 30);
535        assert_eq!(*t.get(&KEY_B).unwrap(), -10);
536        assert_eq!(*t.get(&KEY_C).unwrap(), -20);
537        assert_eq!(t.iter_mut().len(), 3);
538    }
539
540    #[test]
541    fn test_entry() {
542        let mut t = TestCollection::new();
543        assert_eq!(*t.entry(KEY_A).or_insert(2), 2);
544        assert_eq!(
545            *t.entry(KEY_A)
546                .and_modify(|v| {
547                    *v = 10;
548                })
549                .or_insert(5),
550            10
551        );
552        assert_eq!(
553            *t.entry(KEY_B)
554                .and_modify(|v| {
555                    *v = 10;
556                })
557                .or_insert(5),
558            5
559        );
560        assert_eq!(*t.entry(KEY_C).or_insert_with(|| 7), 7);
561
562        assert_eq!(*t.entry(KEY_C).key(), KEY_C);
563        assert_eq!(*t.get(&KEY_A).unwrap(), 10);
564        assert_eq!(*t.get(&KEY_B).unwrap(), 5);
565        assert_eq!(*t.get(&KEY_C).unwrap(), 7);
566    }
567
568    #[test]
569    fn push_entry_valid() {
570        let mut t = TestCollection::new();
571        assert_eq!(t.insert(&KEY_A, 0), None);
572        assert_eq!(t.insert(&KEY_B, 1), None);
573        assert_eq!(t.insert(&KEY_C, 2), None);
574
575        let make_key = |index| FakeKey { id: index, var: FakeVariants::A };
576
577        {
578            let entry = t.push_entry(make_key, 30);
579            assert_eq!(entry.key(), &FakeKey { id: 1, var: FakeVariants::A });
580            assert_eq!(entry.get(), &30);
581        }
582
583        {
584            let entry = t.push_entry(make_key, 20);
585            assert_eq!(entry.key(), &FakeKey { id: 2, var: FakeVariants::A });
586            assert_eq!(entry.get(), &20);
587        }
588
589        assert_eq!(t.iter().collect::<HashSet<_>>(), HashSet::from([&0, &1, &2, &30, &20]));
590    }
591
592    #[test]
593    #[should_panic(expected = "variant is inconsistent")]
594    fn push_entry_invalid_key_fn() {
595        let mut t = TestCollection::new();
596        assert_eq!(t.insert(&KEY_A, 0), None);
597
598        let bad_make_key = |index| FakeKey {
599            id: index,
600            var: if index % 2 == 0 { FakeVariants::A } else { FakeVariants::B },
601        };
602
603        let _ = t.push_entry(bad_make_key, 1);
604        let _ = t.push_entry(bad_make_key, 2);
605    }
606}