agb_hashmap/
lib.rs

1//! A hash map implementation optimised for the Game Boy Advance.
2//!
3//! The main structs are [`HashMap`] and [`HashSet`].
4//!
5//! A lot of the documentation for this module was copied straight out of the rust
6//! standard library. The implementation however is not.
7#![no_std]
8#![cfg_attr(feature = "allocator_api", feature(allocator_api))]
9#![deny(clippy::all)]
10#![deny(clippy::must_use_candidate)]
11#![deny(missing_docs)]
12#![deny(clippy::trivially_copy_pass_by_ref)]
13#![deny(clippy::semicolon_if_nothing_returned)]
14#![deny(clippy::map_unwrap_or)]
15#![deny(clippy::needless_pass_by_value)]
16#![deny(clippy::redundant_closure_for_method_calls)]
17#![deny(clippy::cloned_instead_of_copied)]
18#![deny(rustdoc::broken_intra_doc_links)]
19#![deny(rustdoc::private_intra_doc_links)]
20#![deny(rustdoc::invalid_html_tags)]
21#![deny(unreachable_pub)]
22#![deny(clippy::missing_safety_doc)]
23#![deny(clippy::undocumented_unsafe_blocks)]
24#![deny(clippy::manual_assert)]
25#![deny(clippy::default_trait_access)]
26#![deny(clippy::missing_panics_doc)]
27#![deny(clippy::doc_markdown)]
28#![deny(clippy::return_self_not_must_use)]
29#![deny(clippy::cast_possible_truncation)]
30
31extern crate alloc;
32
33pub(crate) use allocate::{Allocator, Global};
34
35#[cfg(not(feature = "allocator_api"))]
36mod allocate {
37    pub trait Allocator {}
38
39    #[derive(Copy, Clone)]
40    pub struct Global;
41
42    impl Allocator for Global {}
43}
44
45#[cfg(feature = "allocator_api")]
46mod allocate {
47    pub(crate) use alloc::alloc::Global;
48    pub(crate) use core::alloc::Allocator;
49}
50
51#[cfg(feature = "serde")]
52mod serde;
53
54use core::{
55    borrow::Borrow,
56    fmt::Debug,
57    hash::{BuildHasher, BuildHasherDefault, Hash},
58    num::Wrapping,
59    ops::Index,
60};
61
62use rustc_hash::FxHasher;
63
64mod hash_set;
65mod node;
66mod node_storage;
67
68use node::Node;
69use node_storage::NodeStorage;
70
71pub use hash_set::HashSet;
72
73// # Robin Hood Hash Tables
74//
75// The problem with regular hash tables where failing to find a slot for a specific
76// key will result in a linear search for the first free slot is that often these
77// slots can end up being quite far away from the original chosen location in fuller
78// hash tables. In Java, the hash table will resize when it is more than 2 thirds full
79// which is quite wasteful in terms of space. Robin Hood hash tables can be much
80// fuller before needing to resize and also keeps search times lower.
81//
82// The key concept is to keep the distance from the initial bucket chosen for a given
83// key to a minimum. We shall call this distance the "distance to the initial bucket"
84// or DIB for short. With each key - value pair, we store its DIB. When inserting
85// a value into the hash table, we check to see if there is an element in the initial
86// bucket. If there is, we move onto the next value. Then, we check to see if there
87// is already a value there and if there is, we check its DIB. If our DIB is greater
88// than or equal to the DIB of the value that is already there, we swap the working
89// value and the current entry. This continues until an empty slot is found.
90//
91// Using this technique, the average DIB is kept fairly low which decreases search
92// times. As a simple search time optimisation, the maximum DIB is kept track of
93// and so we will only need to search as far as that in order to know whether or
94// not a given element is in the hash table.
95//
96// # Deletion
97//
98// Special mention is given to deletion. Unfortunately, the maximum DIB is not
99// kept track of after deletion, since we would not only need to keep track of
100// the maximum DIB but also the number of elements which have that maximum DIB.
101//
102// In order to delete an element, we search to see if it exists. If it does,
103// we remove that element and then iterate through the array from that point
104// and move each element back one space (updating its DIB). If the DIB of the
105// element we are trying to remove is 0, then we stop this algorithm.
106//
107// This means that deletion will lower the average DIB of the elements and
108// keep searching and insertion fast.
109//
110// # Rehashing
111//
112// Currently, no incremental rehashing takes place. Once the HashMap becomes
113// more than 85% full (this value may change when I do some benchmarking),
114// a new list is allocated with double the capacity and the entire node list
115// is migrated.
116
117/// A hash map implemented very simply using robin hood hashing.
118///
119/// `HashMap` uses `FxHasher` internally, which is a very fast hashing algorithm used
120/// by rustc and firefox in non-adversarial places. It is incredibly fast, and good
121/// enough for most cases.
122///
123/// It is required that the keys implement the [`Eq`] and [`Hash`] traits, although this
124/// can be frequently achieved by using `#[derive(PartialEq, Eq, Hash)]`. If you
125/// implement these yourself, it is important that the following property holds:
126///
127/// `k1 == k2 => hash(k1) == hash(k2)`
128///
129/// It is a logic error for the key to be modified in such a way that the key's hash, as
130/// determined by the [`Hash`] trait, or its equality as determined by the [`Eq`] trait,
131/// changes while it is in the map. The behaviour for such a logic error is not specified,
132/// but will not result in undefined behaviour. This could include panics, incorrect results,
133/// aborts, memory leaks and non-termination.
134///
135/// The API surface provided is incredibly similar to the
136/// [`std::collections::HashMap`](https://doc.rust-lang.org/std/collections/struct.HashMap.html)
137/// implementation with fewer guarantees, and better optimised for the `GameBoy Advance`.
138///
139/// [`Eq`]: https://doc.rust-lang.org/core/cmp/trait.Eq.html
140/// [`Hash`]: https://doc.rust-lang.org/core/hash/trait.Hash.html
141///
142/// # Example
143/// ```
144/// use agb_hashmap::HashMap;
145///
146/// // Type inference lets you omit the type signature (which would be HashMap<String, String> in this example)
147/// let mut game_reviews = HashMap::new();
148///
149/// // Review some games
150/// game_reviews.insert(
151///     "Pokemon Emerald".to_string(),
152///     "Best post-game battle experience of any generation.".to_string(),
153/// );
154/// game_reviews.insert(
155///     "Golden Sun".to_string(),
156///     "Some of the best music on the console".to_string(),
157/// );
158/// game_reviews.insert(
159///     "Super Dodge Ball Advance".to_string(),
160///     "Really great launch title".to_string(),
161/// );
162///
163/// // Check for a specific entry
164/// if !game_reviews.contains_key("Legend of Zelda: The Minish Cap") {
165///     println!("We've got {} reviews, but The Minish Cap ain't one", game_reviews.len());
166/// }
167///
168/// // Iterate over everything
169/// for (game, review) in &game_reviews {
170///     println!("{game}: \"{review}\"");
171/// }
172/// ```
173#[derive(Clone)]
174pub struct HashMap<K, V, ALLOCATOR: Allocator = Global> {
175    nodes: NodeStorage<K, V, ALLOCATOR>,
176
177    hasher: BuildHasherDefault<FxHasher>,
178}
179
180/// Trait for allocators that are cloneable.
181pub trait ClonableAllocator: Allocator + Clone {}
182impl<T: Allocator + Clone> ClonableAllocator for T {}
183
184impl<K, V> HashMap<K, V> {
185    /// Creates a `HashMap`
186    #[must_use]
187    pub const fn new() -> Self {
188        Self::new_in(Global)
189    }
190
191    /// Creates an empty `HashMap` with specified internal size. The size must be a power of 2
192    #[must_use]
193    pub fn with_size(size: usize) -> Self {
194        Self::with_size_in(size, Global)
195    }
196
197    /// Creates an empty `HashMap` which can hold at least `capacity` elements before resizing. The actual
198    /// internal size may be larger as it must be a power of 2
199    #[must_use]
200    pub fn with_capacity(capacity: usize) -> Self {
201        Self::with_capacity_in(capacity, Global)
202    }
203}
204
205impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR> {
206    #[must_use]
207    /// Creates an empty `HashMap` with specified internal size using the
208    /// specified allocator. The size must be a power of 2
209    pub fn with_size_in(size: usize, alloc: ALLOCATOR) -> Self {
210        Self {
211            nodes: NodeStorage::with_size_in(size, alloc),
212            hasher: BuildHasherDefault::new(),
213        }
214    }
215
216    #[must_use]
217    /// Creates a `HashMap` with a specified allocator
218    pub const fn new_in(alloc: ALLOCATOR) -> Self {
219        Self {
220            nodes: NodeStorage::new_in(alloc),
221            hasher: BuildHasherDefault::new(),
222        }
223    }
224
225    /// Returns a reference to the underlying allocator
226    pub fn allocator(&self) -> &ALLOCATOR {
227        self.nodes.allocator()
228    }
229
230    /// Creates an empty `HashMap` which can hold at least `capacity` elements before resizing. The actual
231    /// internal size may be larger as it must be a power of 2
232    ///
233    /// # Panics
234    ///
235    /// Panics if capacity >= 2^31 * 0.6
236    #[must_use]
237    pub fn with_capacity_in(capacity: usize, alloc: ALLOCATOR) -> Self {
238        for i in 0..32 {
239            let attempted_size = 1usize << i;
240            if number_before_resize(attempted_size) > capacity {
241                return Self::with_size_in(attempted_size, alloc);
242            }
243        }
244
245        panic!(
246            "Failed to come up with a size which satisfies capacity {}",
247            capacity
248        );
249    }
250
251    /// Returns the number of elements in the map
252    #[must_use]
253    pub fn len(&self) -> usize {
254        self.nodes.len()
255    }
256
257    /// Returns the number of elements the map can hold
258    #[must_use]
259    pub fn capacity(&self) -> usize {
260        self.nodes.capacity()
261    }
262
263    /// An iterator visiting all keys in an arbitrary order
264    pub fn keys(&self) -> impl Iterator<Item = &'_ K> {
265        self.iter().map(|(k, _)| k)
266    }
267
268    /// An iterator visiting all values in an arbitrary order
269    pub fn values(&self) -> impl Iterator<Item = &'_ V> {
270        self.iter().map(|(_, v)| v)
271    }
272
273    /// An iterator visiting all values in an arbitrary order allowing for mutation
274    pub fn values_mut(&mut self) -> impl Iterator<Item = &'_ mut V> {
275        self.iter_mut().map(|(_, v)| v)
276    }
277
278    /// Removes all elements from the map
279    pub fn clear(&mut self) {
280        self.nodes.clear();
281    }
282
283    /// An iterator visiting all key-value pairs in an arbitrary order
284    pub fn iter(&self) -> impl Iterator<Item = (&'_ K, &'_ V)> {
285        Iter {
286            map: self,
287            at: 0,
288            num_found: 0,
289        }
290    }
291
292    /// An iterator visiting all key-value pairs in an arbitrary order, with mutable references to the values
293    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&'_ K, &'_ mut V)> {
294        self.nodes.iter_mut().filter_map(Node::key_value_mut)
295    }
296
297    /// Retains only the elements specified by the predicate `f`.
298    pub fn retain<F>(&mut self, f: F)
299    where
300        F: FnMut(&K, &mut V) -> bool,
301    {
302        self.nodes.retain(f);
303    }
304
305    /// Returns `true` if the map contains no elements
306    #[must_use]
307    pub fn is_empty(&self) -> bool {
308        self.len() == 0
309    }
310}
311
312impl<K, V> Default for HashMap<K, V> {
313    fn default() -> Self {
314        Self::new()
315    }
316}
317
318impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR>
319where
320    K: Eq + Hash,
321{
322    /// Inserts a key-value pair into the map.
323    ///
324    /// If the map did not have this key present, [`None`] is returned.
325    ///
326    /// If the map did have this key present, the value is updated and the old value
327    /// is returned. The key is not updated, which matters for types that can be `==`
328    /// without being identical.
329    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
330        let hash = self.hash(&key);
331
332        if let Some(location) = self.nodes.location(&key, hash) {
333            Some(
334                // SAFETY: location is valid due to the above
335                unsafe {
336                    self.nodes
337                        .replace_at_location_unchecked(location, key, value)
338                },
339            )
340        } else {
341            self.nodes.insert_new(key, value, hash);
342
343            None
344        }
345    }
346
347    /// # Safety
348    ///
349    /// - `key` must not currently be in the hash map
350    unsafe fn insert_new_and_get(&mut self, key: K, value: V, hash: HashType) -> &'_ mut V {
351        let location = self.nodes.insert_new(key, value, hash);
352
353        // SAFETY: location is always valid
354        unsafe {
355            self.nodes
356                .node_at_unchecked_mut(location)
357                .value_mut_unchecked()
358        }
359    }
360
361    /// Returns `true` if the map contains a value for the specified key.
362    pub fn contains_key<Q>(&self, k: &Q) -> bool
363    where
364        K: Borrow<Q>,
365        Q: Hash + Eq + ?Sized,
366    {
367        let hash = self.hash(k);
368        self.nodes.location(k, hash).is_some()
369    }
370
371    /// Returns the key-value pair corresponding to the supplied key
372    pub fn get_key_value<Q>(&self, key: &Q) -> Option<(&K, &V)>
373    where
374        K: Borrow<Q>,
375        Q: Hash + Eq + ?Sized,
376    {
377        let hash = self.hash(key);
378
379        let location = self.nodes.location(key, hash)?;
380        Some(
381            // SAFETY: we know that a node exists and has a value from the location call above
382            unsafe {
383                self.nodes
384                    .node_at_unchecked(location)
385                    .key_value_ref_unchecked()
386            },
387        )
388    }
389
390    /// Returns a reference to the value corresponding to the key. Returns [`None`] if there is
391    /// no element in the map with the given key.
392    ///
393    /// # Example
394    /// ```
395    /// use agb_hashmap::HashMap;
396    ///
397    /// let mut map = HashMap::new();
398    /// map.insert("a".to_string(), "A");
399    /// assert_eq!(map.get("a"), Some(&"A"));
400    /// assert_eq!(map.get("b"), None);
401    /// ```
402    pub fn get<Q>(&self, key: &Q) -> Option<&V>
403    where
404        K: Borrow<Q>,
405        Q: Hash + Eq + ?Sized,
406    {
407        self.get_key_value(key).map(|(_, v)| v)
408    }
409
410    /// Returns a mutable reference to the value corresponding to the key. Return [`None`] if
411    /// there is no element in the map with the given key.
412    ///
413    /// # Example
414    /// ```
415    /// use agb_hashmap::HashMap;
416    ///
417    /// let mut map = HashMap::new();
418    /// map.insert("a".to_string(), "A");
419    ///
420    /// if let Some(x) = map.get_mut("a") {
421    ///     *x = "b";
422    /// }
423    ///
424    /// assert_eq!(map["a"], "b");
425    /// ```
426    pub fn get_mut<Q>(&mut self, key: &Q) -> Option<&mut V>
427    where
428        K: Borrow<Q>,
429        Q: Hash + Eq + ?Sized,
430    {
431        let hash = self.hash(key);
432
433        let location = self.nodes.location(key, hash)?;
434        Some(
435            // SAFETY: we know that a node exists and has a value from the location call above
436            unsafe {
437                self.nodes
438                    .node_at_unchecked_mut(location)
439                    .value_mut_unchecked()
440            },
441        )
442    }
443
444    /// Removes the given key from the map. Returns the current value if it existed, or [`None`]
445    /// if it did not.
446    ///
447    /// # Example
448    /// ```
449    /// use agb_hashmap::HashMap;
450    ///
451    /// let mut map = HashMap::new();
452    /// map.insert(1, "a");
453    /// assert_eq!(map.remove(&1), Some("a"));
454    /// assert_eq!(map.remove(&1), None);
455    /// ```
456    pub fn remove<Q>(&mut self, key: &Q) -> Option<V>
457    where
458        K: Borrow<Q>,
459        Q: Hash + Eq + ?Sized,
460    {
461        let hash = self.hash(key);
462
463        self.nodes
464            .location(key, hash)
465            .map(|location| self.nodes.remove_from_location(location))
466    }
467}
468
469impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR>
470where
471    K: Hash,
472{
473    fn hash<Q>(&self, key: &Q) -> HashType
474    where
475        K: Borrow<Q>,
476        Q: Hash + ?Sized,
477    {
478        let result = self.hasher.hash_one(key);
479
480        // we want to allow truncation here since we're reducing 64 bits to 32
481        #[allow(clippy::cast_possible_truncation)]
482        let reduced = (result as u32) ^ ((result >> 32) as u32);
483        HashType::bit_mix(reduced)
484    }
485}
486
487/// An iterator over entries of a [`HashMap`]
488///
489/// This struct is created using the `into_iter()` method on [`HashMap`]. See its
490/// documentation for more.
491pub struct Iter<'a, K: 'a, V: 'a, ALLOCATOR: ClonableAllocator> {
492    map: &'a HashMap<K, V, ALLOCATOR>,
493    at: usize,
494    num_found: usize,
495}
496
497impl<'a, K, V, ALLOCATOR: ClonableAllocator> Iterator for Iter<'a, K, V, ALLOCATOR> {
498    type Item = (&'a K, &'a V);
499
500    fn next(&mut self) -> Option<Self::Item> {
501        loop {
502            if self.at >= self.map.nodes.backing_vec_size() || self.num_found == self.map.len() {
503                return None;
504            }
505
506            let node = &self.map.nodes.node_at(self.at);
507            self.at += 1;
508
509            if let Some(key_value) = node.key_value_ref() {
510                self.num_found += 1;
511                return Some(key_value);
512            }
513        }
514    }
515
516    fn size_hint(&self) -> (usize, Option<usize>) {
517        (
518            self.map.len() - self.num_found,
519            Some(self.map.len() - self.num_found),
520        )
521    }
522}
523
524impl<K, V, ALLOCATOR: ClonableAllocator> ExactSizeIterator for Iter<'_, K, V, ALLOCATOR> {}
525
526impl<'a, K, V, ALLOCATOR: ClonableAllocator> IntoIterator for &'a HashMap<K, V, ALLOCATOR> {
527    type Item = (&'a K, &'a V);
528    type IntoIter = Iter<'a, K, V, ALLOCATOR>;
529
530    fn into_iter(self) -> Self::IntoIter {
531        Iter {
532            map: self,
533            at: 0,
534            num_found: 0,
535        }
536    }
537}
538
539/// An iterator over entries of a [`HashMap`]
540///
541/// This struct is created using the `into_iter()` method on [`HashMap`] as part of its implementation
542/// of the `IntoIterator` trait.
543pub struct IterOwned<K, V, ALLOCATOR: Allocator = Global> {
544    map: HashMap<K, V, ALLOCATOR>,
545    at: usize,
546    num_found: usize,
547}
548
549impl<K, V, ALLOCATOR: ClonableAllocator> Iterator for IterOwned<K, V, ALLOCATOR> {
550    type Item = (K, V);
551
552    fn next(&mut self) -> Option<Self::Item> {
553        loop {
554            if self.at >= self.map.nodes.backing_vec_size() || self.num_found == self.map.len() {
555                return None;
556            }
557
558            let maybe_kv = self.map.nodes.node_at_mut(self.at).take_key_value();
559            self.at += 1;
560
561            if let Some((k, v, _)) = maybe_kv {
562                self.num_found += 1;
563                return Some((k, v));
564            }
565        }
566    }
567
568    fn size_hint(&self) -> (usize, Option<usize>) {
569        (
570            self.map.len() - self.num_found,
571            Some(self.map.len() - self.num_found),
572        )
573    }
574}
575
576impl<K, V, ALLOCATOR: ClonableAllocator> ExactSizeIterator for IterOwned<K, V, ALLOCATOR> {}
577
578/// An iterator over entries of a [`HashMap`]
579///
580/// This struct is created using the `into_iter()` method on [`HashMap`] as part of its implementation
581/// of the `IntoIterator` trait.
582impl<K, V, ALLOCATOR: ClonableAllocator> IntoIterator for HashMap<K, V, ALLOCATOR> {
583    type Item = (K, V);
584    type IntoIter = IterOwned<K, V, ALLOCATOR>;
585
586    fn into_iter(self) -> Self::IntoIter {
587        IterOwned {
588            map: self,
589            at: 0,
590            num_found: 0,
591        }
592    }
593}
594
595mod entries {
596    use crate::allocate::Allocator;
597    use core::hash::Hash;
598
599    use super::{ClonableAllocator, HashMap, HashType};
600
601    /// A view into an occupied entry in a `HashMap`. This is part of the [`crate::Entry`] enum.
602    pub struct OccupiedEntry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator> {
603        key: K,
604        map: &'a mut HashMap<K, V, ALLOCATOR>,
605        location: usize,
606    }
607
608    impl<'a, K: 'a, V: 'a, ALLOCATOR: ClonableAllocator> OccupiedEntry<'a, K, V, ALLOCATOR> {
609        /// # Safety
610        ///
611        /// You must call this with a valid location (one where the entry is defined)
612        pub(crate) unsafe fn new(
613            key: K,
614            map: &'a mut HashMap<K, V, ALLOCATOR>,
615            location: usize,
616        ) -> Self {
617            Self { key, map, location }
618        }
619
620        /// Gets a reference to the key in the entry.
621        pub fn key(&self) -> &K {
622            &self.key
623        }
624
625        /// Take the ownership of the key and value from the map.
626        pub fn remove_entry(self) -> (K, V) {
627            let old_value = self.map.nodes.remove_from_location(self.location);
628            (self.key, old_value)
629        }
630
631        /// Gets a reference to the value in the entry.
632        pub fn get(&self) -> &V {
633            // SAFETY: This can only be constructed with valid locations
634            unsafe {
635                self.map
636                    .nodes
637                    .node_at_unchecked(self.location)
638                    .value_ref_unchecked()
639            }
640        }
641
642        /// Gets a mutable reference to the value in the entry.
643        ///
644        /// If you need a reference to the `OccupiedEntry` which may outlive the destruction
645        /// of the `Entry` value, see [`into_mut`].
646        ///
647        /// [`into_mut`]: Self::into_mut
648        pub fn get_mut(&mut self) -> &mut V {
649            // SAFETY: This can only be constructed with valid locations
650            unsafe {
651                self.map
652                    .nodes
653                    .node_at_unchecked_mut(self.location)
654                    .value_mut_unchecked()
655            }
656        }
657
658        /// Converts the `OccupiedEntry` into a mutable reference to the value in the entry with
659        /// a lifetime bound to the map itself.
660        ///
661        /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
662        ///
663        /// [`get_mut`]: Self::get_mut
664        pub fn into_mut(self) -> &'a mut V {
665            // SAFETY: This can only be constructed with valid locations
666            unsafe {
667                self.map
668                    .nodes
669                    .node_at_unchecked_mut(self.location)
670                    .value_mut_unchecked()
671            }
672        }
673
674        /// Sets the value of the entry and returns the entry's old value.
675        pub fn insert(&mut self, value: V) -> V {
676            // SAFETY: This can only be constructed with valid locations
677            unsafe {
678                self.map
679                    .nodes
680                    .node_at_unchecked_mut(self.location)
681                    .replace_value_unchecked(value)
682            }
683        }
684
685        /// Takes the value out of the entry and returns it.
686        pub fn remove(self) -> V {
687            self.map.nodes.remove_from_location(self.location)
688        }
689    }
690
691    /// A view into a vacant entry in a `HashMap`. It is part of the [`crate::Entry`] enum.
692    pub struct VacantEntry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator> {
693        key: K,
694        map: &'a mut HashMap<K, V, ALLOCATOR>,
695        hash: HashType,
696    }
697
698    impl<'a, K: 'a, V: 'a, ALLOCATOR: ClonableAllocator> VacantEntry<'a, K, V, ALLOCATOR> {
699        /// # Safety
700        ///
701        /// - The entry `key` must not exist in the hashmap `map`
702        pub(crate) unsafe fn new(
703            key: K,
704            hash: HashType,
705            map: &'a mut HashMap<K, V, ALLOCATOR>,
706        ) -> Self {
707            Self { key, map, hash }
708        }
709
710        /// Gets a reference to the key that would be used when inserting a value through `VacantEntry`
711        pub fn key(&self) -> &K {
712            &self.key
713        }
714
715        /// Take ownership of the key
716        pub fn into_key(self) -> K {
717            self.key
718        }
719
720        /// Sets the value of the entry with the `VacantEntry`'s key and returns a mutable reference to it.
721        pub fn insert(self, value: V) -> &'a mut V
722        where
723            K: Hash + Eq,
724        {
725            // SAFETY: by construction, this doesn't already exist in the hashmap and we were given the hash and key
726            unsafe { self.map.insert_new_and_get(self.key, value, self.hash) }
727        }
728    }
729}
730
731pub use entries::{OccupiedEntry, VacantEntry};
732
733/// A view into a single entry in a map, which may be vacant or occupied.
734///
735/// This is constructed using the [`entry`] method on [`HashMap`]
736///
737/// [`entry`]: HashMap::entry()
738pub enum Entry<'a, K: 'a, V: 'a, ALLOCATOR: Allocator = Global> {
739    /// An occupied entry
740    Occupied(OccupiedEntry<'a, K, V, ALLOCATOR>),
741    /// A vacant entry
742    Vacant(VacantEntry<'a, K, V, ALLOCATOR>),
743}
744
745impl<'a, K, V, ALLOCATOR: ClonableAllocator> Entry<'a, K, V, ALLOCATOR>
746where
747    K: Hash + Eq,
748{
749    /// Ensures a value is in the entry by inserting the given value, and returns a mutable
750    /// reference to the value in the entry.
751    pub fn or_insert(self, value: V) -> &'a mut V {
752        match self {
753            Entry::Occupied(e) => e.into_mut(),
754            Entry::Vacant(e) => e.insert(value),
755        }
756    }
757
758    /// Ensures a value is in the entry by inserting the result of the function if empty, and
759    /// returns a mutable reference to the value in the entry.
760    pub fn or_insert_with<F>(self, f: F) -> &'a mut V
761    where
762        F: FnOnce() -> V,
763    {
764        match self {
765            Entry::Occupied(e) => e.into_mut(),
766            Entry::Vacant(e) => e.insert(f()),
767        }
768    }
769
770    /// Ensures a value is in the entry by inserting the result of the function if empty, and
771    /// returns a mutable reference to the value in the entry. This method allows for key-derived
772    /// values for insertion by providing the function with a reference to the key.
773    ///
774    /// The reference to the moved key is provided so that cloning or copying the key is unnecessary,
775    /// unlike with `.or_insert_with(|| ...)`.
776    pub fn or_insert_with_key<F>(self, f: F) -> &'a mut V
777    where
778        F: FnOnce(&K) -> V,
779    {
780        match self {
781            Entry::Occupied(e) => e.into_mut(),
782            Entry::Vacant(e) => {
783                let value = f(e.key());
784                e.insert(value)
785            }
786        }
787    }
788
789    /// Provides in-place mutable access to an occupied entry before any potential inserts
790    /// into the map.
791    #[must_use]
792    pub fn and_modify<F>(self, f: F) -> Self
793    where
794        F: FnOnce(&mut V),
795    {
796        match self {
797            Entry::Occupied(mut e) => {
798                f(e.get_mut());
799                Entry::Occupied(e)
800            }
801            Entry::Vacant(e) => Entry::Vacant(e),
802        }
803    }
804
805    /// Ensures a value is in th entry by inserting the default value if empty. Returns a
806    /// mutable reference to the value in the entry.
807    pub fn or_default(self) -> &'a mut V
808    where
809        V: Default,
810    {
811        match self {
812            Entry::Occupied(e) => e.into_mut(),
813            Entry::Vacant(e) => e.insert(Default::default()),
814        }
815    }
816
817    /// Returns a reference to this entry's key.
818    pub fn key(&self) -> &K {
819        match self {
820            Entry::Occupied(e) => e.key(),
821            Entry::Vacant(e) => e.key(),
822        }
823    }
824}
825
826impl<K, V, ALLOCATOR: ClonableAllocator> HashMap<K, V, ALLOCATOR>
827where
828    K: Hash + Eq,
829{
830    /// Gets the given key's corresponding entry in the map for in-place manipulation.
831    pub fn entry(&mut self, key: K) -> Entry<'_, K, V, ALLOCATOR> {
832        let hash = self.hash(&key);
833        let location = self.nodes.location(&key, hash);
834
835        if let Some(location) = location {
836            Entry::Occupied(
837                // SAFETY: location is valid by the call to location above
838                unsafe { OccupiedEntry::new(key, self, location) },
839            )
840        } else {
841            Entry::Vacant(
842                // SAFETY: item doesn't exist yet and the hash is correct here
843                unsafe { VacantEntry::new(key, hash, self) },
844            )
845        }
846    }
847}
848
849impl<K, V> FromIterator<(K, V)> for HashMap<K, V>
850where
851    K: Eq + Hash,
852{
853    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
854        let mut map = HashMap::new();
855        map.extend(iter);
856        map
857    }
858}
859
860impl<K, V> Extend<(K, V)> for HashMap<K, V>
861where
862    K: Eq + Hash,
863{
864    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
865        for (k, v) in iter {
866            self.insert(k, v);
867        }
868    }
869}
870
871impl<K, V, Q, ALLOCATOR: ClonableAllocator> Index<&Q> for HashMap<K, V, ALLOCATOR>
872where
873    K: Eq + Hash + Borrow<Q>,
874    Q: Eq + Hash + ?Sized,
875{
876    type Output = V;
877
878    fn index(&self, key: &Q) -> &V {
879        self.get(key).expect("no entry found for key")
880    }
881}
882
883impl<K, V, ALLOCATOR: ClonableAllocator> PartialEq for HashMap<K, V, ALLOCATOR>
884where
885    K: Eq + Hash,
886    V: PartialEq,
887{
888    fn eq(&self, other: &HashMap<K, V, ALLOCATOR>) -> bool {
889        if self.len() != other.len() {
890            return false;
891        }
892
893        self.iter()
894            .all(|(key, value)| other.get(key).is_some_and(|v| *value == *v))
895    }
896}
897
898impl<K, V, ALLOCATOR: ClonableAllocator> Eq for HashMap<K, V, ALLOCATOR>
899where
900    K: Eq + Hash,
901    V: PartialEq,
902{
903}
904
905impl<K, V, ALLOCATOR: ClonableAllocator> Debug for HashMap<K, V, ALLOCATOR>
906where
907    K: Debug,
908    V: Debug,
909{
910    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
911        f.debug_map().entries(self.iter()).finish()
912    }
913}
914
915const fn number_before_resize(capacity: usize) -> usize {
916    capacity * 3 / 5
917}
918
919#[derive(Clone, Copy, PartialEq, Eq)]
920pub(crate) struct HashType(u32);
921
922impl From<usize> for HashType {
923    fn from(value: usize) -> Self {
924        // we explicitly want to allow truncation
925        #[allow(clippy::cast_possible_truncation)]
926        Self(value as u32)
927    }
928}
929
930impl HashType {
931    pub(crate) const fn new() -> Self {
932        Self(0)
933    }
934
935    // 32 bit mix function from here: https://github.com/skeeto/hash-prospector
936    fn bit_mix(key: u32) -> Self {
937        let mut key = Wrapping(key);
938        key ^= key >> 16;
939        key *= 0x7feb352d;
940        key ^= key >> 15;
941        key *= 0x846ca68b;
942        key ^= key >> 16;
943
944        Self(key.0)
945    }
946
947    pub(crate) fn fast_mod(self, len: usize) -> usize {
948        debug_assert!(len.is_power_of_two(), "Length must be a power of 2");
949        (self.0 as usize) & (len - 1)
950    }
951}
952
953impl core::ops::Add<i32> for HashType {
954    type Output = HashType;
955
956    fn add(self, rhs: i32) -> Self::Output {
957        Self(self.0.wrapping_add_signed(rhs))
958    }
959}
960
961#[cfg(test)]
962mod test {
963    #![allow(clippy::missing_panics_doc)]
964
965    use core::{cell::RefCell, hash::Hasher};
966
967    use alloc::vec::Vec;
968
969    use super::*;
970
971    #[test]
972    fn can_create_with_size() {
973        let map: HashMap<i32, i32, Global> = HashMap::with_size_in(2, Global);
974        assert_eq!(map.len(), 0);
975    }
976
977    #[test]
978    fn can_create_with_capacity() {
979        let map: HashMap<i32, i32, Global> = HashMap::with_capacity_in(0, Global);
980        assert_eq!(map.len(), 0);
981    }
982
983    #[test]
984    #[should_panic]
985    fn cannot_create_with_overflows() {
986        let _ = HashMap::<i32, i32, Global>::with_capacity_in((1 << 31) * 3 / 5, Global);
987    }
988
989    #[test]
990    fn can_store_and_retrieve_8_elements() {
991        let mut map = HashMap::new();
992
993        for i in 0..8 {
994            map.insert(i, i % 4);
995        }
996
997        for i in 0..8 {
998            assert_eq!(map.get(&i), Some(&(i % 4)));
999        }
1000    }
1001
1002    #[test]
1003    fn can_get_the_length() {
1004        let mut map = HashMap::new();
1005
1006        for i in 0..8 {
1007            map.insert(i / 2, true);
1008        }
1009
1010        assert_eq!(map.len(), 4);
1011    }
1012
1013    #[test]
1014    fn returns_none_if_element_does_not_exist() {
1015        let mut map = HashMap::new();
1016
1017        for i in 0..8 {
1018            map.insert(i, i % 3);
1019        }
1020
1021        assert_eq!(map.get(&12), None);
1022    }
1023
1024    #[test]
1025    fn can_delete_entries() {
1026        let mut map = HashMap::new();
1027
1028        for i in 0..8 {
1029            map.insert(i, i % 3);
1030        }
1031
1032        for i in 0..4 {
1033            map.remove(&i);
1034        }
1035
1036        assert_eq!(map.len(), 4);
1037        assert_eq!(map.get(&3), None);
1038        assert_eq!(map.get(&7), Some(&1));
1039    }
1040
1041    #[test]
1042    fn can_iterate_through_all_entries() {
1043        let mut map = HashMap::new();
1044
1045        for i in 0..8 {
1046            map.insert(i, i);
1047        }
1048
1049        let mut max_found = -1;
1050        let mut num_found = 0;
1051
1052        for (_, value) in map {
1053            max_found = max_found.max(value);
1054            num_found += 1;
1055        }
1056
1057        assert_eq!(num_found, 8);
1058        assert_eq!(max_found, 7);
1059    }
1060
1061    #[test]
1062    fn can_insert_more_than_initial_capacity() {
1063        let mut map = HashMap::new();
1064
1065        for i in 0..65 {
1066            map.insert(i, i % 4);
1067        }
1068
1069        for i in 0..65 {
1070            assert_eq!(map.get(&i), Some(&(i % 4)));
1071        }
1072    }
1073
1074    #[test]
1075    fn can_entry_or_insert() {
1076        let mut map = HashMap::new();
1077        map.insert(1, 10);
1078        let v = map.entry(1).or_insert(20);
1079        assert_eq!(*v, 10);
1080    }
1081
1082    #[test]
1083    fn can_entry_or_insert_with() {
1084        let mut map = HashMap::new();
1085        map.insert(3, 15);
1086        let v = map.entry(3).or_insert_with(|| 25);
1087        assert_eq!(*v, 15);
1088    }
1089
1090    #[test]
1091    fn can_entry_or_insert_with_key() {
1092        let mut map = HashMap::new();
1093        map.insert(5, 50);
1094        let v = map.entry(5).or_insert_with_key(|k| k * 10);
1095        assert_eq!(*v, 50);
1096    }
1097
1098    #[test]
1099    fn can_entry_or_default_for_existing_key() {
1100        let mut map = HashMap::new();
1101        map.insert(9, 9);
1102        let v = map.entry(9).or_default();
1103        assert_eq!(*v, 9);
1104    }
1105
1106    #[test]
1107    fn can_entry_or_default_for_missing_key() {
1108        let mut map = HashMap::new();
1109        let v = map.entry(10).or_default();
1110        assert_eq!(*v, 0);
1111        assert_eq!(map.get(&10), Some(&0));
1112    }
1113
1114    struct NoisyDrop {
1115        i: i32,
1116        dropped: bool,
1117    }
1118
1119    impl NoisyDrop {
1120        #[cfg(not(miri))]
1121        fn new(i: i32) -> Self {
1122            Self { i, dropped: false }
1123        }
1124    }
1125
1126    impl PartialEq for NoisyDrop {
1127        fn eq(&self, other: &Self) -> bool {
1128            self.i == other.i
1129        }
1130    }
1131
1132    impl Eq for NoisyDrop {}
1133
1134    impl Hash for NoisyDrop {
1135        fn hash<H: Hasher>(&self, hasher: &mut H) {
1136            hasher.write_i32(self.i);
1137        }
1138    }
1139
1140    impl Drop for NoisyDrop {
1141        fn drop(&mut self) {
1142            assert!(!self.dropped, "NoisyDropped dropped twice");
1143
1144            self.dropped = true;
1145        }
1146    }
1147
1148    trait RngNextI32 {
1149        fn next_i32(&mut self) -> i32;
1150    }
1151
1152    impl<T> RngNextI32 for T
1153    where
1154        T: rand::RngCore,
1155    {
1156        fn next_i32(&mut self) -> i32 {
1157            self.next_u32() as i32
1158        }
1159    }
1160
1161    #[cfg(not(miri))] // takes way too long to run under miri
1162    #[test]
1163    fn extreme_case() {
1164        use rand::SeedableRng;
1165
1166        let mut map = HashMap::new();
1167        let mut rng = rand::rngs::SmallRng::seed_from_u64(20);
1168
1169        let mut answers: [Option<i32>; 512] = [None; 512];
1170
1171        for _ in 0..15_000 {
1172            let command = rng.next_i32().rem_euclid(2);
1173            let key = rng.next_i32().rem_euclid(answers.len().try_into().unwrap());
1174            let value = rng.next_i32();
1175
1176            match command {
1177                0 => {
1178                    // insert
1179                    answers[key as usize] = Some(value);
1180                    map.insert(NoisyDrop::new(key), NoisyDrop::new(value));
1181                }
1182                1 => {
1183                    // remove
1184                    answers[key as usize] = None;
1185                    map.remove(&NoisyDrop::new(key));
1186                }
1187                _ => {}
1188            }
1189
1190            for (i, answer) in answers.iter().enumerate() {
1191                assert_eq!(
1192                    map.get(&NoisyDrop::new(i.try_into().unwrap()))
1193                        .map(|nd| &nd.i),
1194                    answer.as_ref()
1195                );
1196            }
1197
1198            assert!(map.capacity() >= map.len());
1199        }
1200    }
1201
1202    #[derive(Clone)]
1203    struct Droppable<'a> {
1204        id: usize,
1205        drop_registry: &'a DropRegistry,
1206    }
1207
1208    impl Hash for Droppable<'_> {
1209        fn hash<H: Hasher>(&self, hasher: &mut H) {
1210            hasher.write_usize(self.id);
1211        }
1212    }
1213
1214    impl PartialEq for Droppable<'_> {
1215        fn eq(&self, other: &Self) -> bool {
1216            self.id == other.id
1217        }
1218    }
1219
1220    impl Eq for Droppable<'_> {}
1221
1222    impl Drop for Droppable<'_> {
1223        fn drop(&mut self) {
1224            self.drop_registry.dropped(self.id);
1225        }
1226    }
1227
1228    struct DropRegistry {
1229        are_dropped: RefCell<Vec<i32>>,
1230    }
1231
1232    impl DropRegistry {
1233        fn new() -> Self {
1234            Self {
1235                are_dropped: RefCell::default(),
1236            }
1237        }
1238
1239        fn new_droppable(&self) -> Droppable<'_> {
1240            self.are_dropped.borrow_mut().push(0);
1241            Droppable {
1242                id: self.are_dropped.borrow().len() - 1,
1243                drop_registry: self,
1244            }
1245        }
1246
1247        fn dropped(&self, id: usize) {
1248            self.are_dropped.borrow_mut()[id] += 1;
1249        }
1250
1251        fn assert_dropped_once(&self, id: usize) {
1252            assert_eq!(self.are_dropped.borrow()[id], 1);
1253        }
1254
1255        fn assert_not_dropped(&self, id: usize) {
1256            assert_eq!(self.are_dropped.borrow()[id], 0);
1257        }
1258
1259        fn assert_dropped_n_times(&self, id: usize, num_drops: i32) {
1260            assert_eq!(self.are_dropped.borrow()[id], num_drops);
1261        }
1262    }
1263
1264    #[test]
1265    fn correctly_drops_on_remove_and_overall_drop() {
1266        let drop_registry = DropRegistry::new();
1267
1268        let droppable1 = drop_registry.new_droppable();
1269        let droppable2 = drop_registry.new_droppable();
1270
1271        let id1 = droppable1.id;
1272        let id2 = droppable2.id;
1273
1274        {
1275            let mut map = HashMap::new();
1276
1277            map.insert(1, droppable1);
1278            map.insert(2, droppable2);
1279
1280            drop_registry.assert_not_dropped(id1);
1281            drop_registry.assert_not_dropped(id2);
1282
1283            map.remove(&1);
1284            drop_registry.assert_dropped_once(id1);
1285            drop_registry.assert_not_dropped(id2);
1286        }
1287
1288        drop_registry.assert_dropped_once(id2);
1289    }
1290
1291    #[test]
1292    fn correctly_drop_on_override() {
1293        let drop_registry = DropRegistry::new();
1294
1295        let droppable1 = drop_registry.new_droppable();
1296        let droppable2 = drop_registry.new_droppable();
1297
1298        let id1 = droppable1.id;
1299        let id2 = droppable2.id;
1300
1301        {
1302            let mut map = HashMap::new();
1303
1304            map.insert(1, droppable1);
1305            drop_registry.assert_not_dropped(id1);
1306            map.insert(1, droppable2);
1307
1308            drop_registry.assert_dropped_once(id1);
1309            drop_registry.assert_not_dropped(id2);
1310        }
1311
1312        drop_registry.assert_dropped_once(id2);
1313    }
1314
1315    #[test]
1316    fn correctly_drops_key_on_override() {
1317        let drop_registry = DropRegistry::new();
1318
1319        let droppable1 = drop_registry.new_droppable();
1320        let droppable1a = droppable1.clone();
1321
1322        let id1 = droppable1.id;
1323
1324        {
1325            let mut map = HashMap::new();
1326
1327            map.insert(droppable1, 1);
1328            drop_registry.assert_not_dropped(id1);
1329            map.insert(droppable1a, 2);
1330
1331            drop_registry.assert_dropped_once(id1);
1332        }
1333
1334        drop_registry.assert_dropped_n_times(id1, 2);
1335    }
1336
1337    #[test]
1338    fn test_value_mut() {
1339        let mut map = HashMap::new();
1340        map.insert("x", 1);
1341        for v in map.values_mut() {
1342            *v += 1;
1343        }
1344        assert_eq!(map.get(&"x"), Some(&2));
1345    }
1346
1347    #[test]
1348    fn test_iter_mut() {
1349        let mut map = HashMap::new();
1350        map.insert(1, 1);
1351        map.insert(2, 2);
1352        for (k, v) in map.iter_mut() {
1353            *v += *k;
1354        }
1355        assert_eq!(map.get(&1), Some(&2));
1356        assert_eq!(map.get(&2), Some(&4));
1357    }
1358
1359    #[test]
1360    fn test_retain() {
1361        let mut map = HashMap::new();
1362
1363        for i in 0..100 {
1364            map.insert(i, i);
1365        }
1366
1367        map.retain(|k, _| k % 2 == 0);
1368
1369        assert_eq!(map[&2], 2);
1370        assert_eq!(map.get(&3), None);
1371
1372        assert_eq!(map.iter().count(), 50); // force full iteration
1373    }
1374
1375    #[test]
1376    fn test_size_hint_iter() {
1377        let mut map = HashMap::new();
1378
1379        for i in 0..100 {
1380            map.insert(i, i);
1381        }
1382
1383        let mut iter = map.iter();
1384        assert_eq!(iter.size_hint(), (100, Some(100)));
1385
1386        iter.next();
1387
1388        assert_eq!(iter.size_hint(), (99, Some(99)));
1389    }
1390
1391    #[test]
1392    fn test_size_hint_into_iter() {
1393        let mut map = HashMap::new();
1394
1395        for i in 0..100 {
1396            map.insert(i, i);
1397        }
1398
1399        let mut iter = map.into_iter();
1400        assert_eq!(iter.size_hint(), (100, Some(100)));
1401
1402        iter.next();
1403
1404        assert_eq!(iter.size_hint(), (99, Some(99)));
1405    }
1406
1407    #[test]
1408    fn clear_should_empty_hashmap() {
1409        let mut map = HashMap::new();
1410        assert_eq!(map.len(), 0);
1411
1412        assert!(map.is_empty());
1413
1414        map.insert(5, 0);
1415        map.insert(4, 3);
1416
1417        assert_eq!(map.len(), 2);
1418        assert!(!map.is_empty());
1419
1420        map.clear();
1421
1422        assert_eq!(map.len(), 0);
1423        assert!(map.is_empty());
1424
1425        let values = map.values().collect::<Vec<_>>();
1426        assert_eq!(values, Vec::<&i32>::new());
1427    }
1428
1429    #[test]
1430    fn clear_should_not_decrease_capacity() {
1431        let mut map = HashMap::new();
1432
1433        for i in 0..64 {
1434            map.insert(i, i + 1);
1435        }
1436
1437        let before_clear_capacity = map.capacity();
1438        assert!(before_clear_capacity >= 64);
1439
1440        map.clear();
1441        assert!(map.capacity() == before_clear_capacity);
1442    }
1443
1444    // Following test cases copied from the rust source
1445    // https://github.com/rust-lang/rust/blob/master/library/std/src/collections/hash/map/tests.rs
1446    mod rust_std_tests {
1447        use alloc::format;
1448
1449        use crate::{Entry::*, HashMap};
1450
1451        #[test]
1452        fn test_entry() {
1453            let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
1454
1455            let mut map: HashMap<_, _> = xs.iter().copied().collect();
1456
1457            // Existing key (insert)
1458            match map.entry(1) {
1459                Vacant(_) => unreachable!(),
1460                Occupied(mut view) => {
1461                    assert_eq!(view.get(), &10);
1462                    assert_eq!(view.insert(100), 10);
1463                }
1464            }
1465            assert_eq!(map.get(&1).unwrap(), &100);
1466            assert_eq!(map.len(), 6);
1467
1468            // Existing key (update)
1469            match map.entry(2) {
1470                Vacant(_) => unreachable!(),
1471                Occupied(mut view) => {
1472                    let v = view.get_mut();
1473                    let new_v = (*v) * 10;
1474                    *v = new_v;
1475                }
1476            }
1477            assert_eq!(map.get(&2).unwrap(), &200);
1478            assert_eq!(map.len(), 6);
1479
1480            // Existing key (take)
1481            match map.entry(3) {
1482                Vacant(_) => unreachable!(),
1483                Occupied(view) => {
1484                    assert_eq!(view.remove(), 30);
1485                }
1486            }
1487            assert_eq!(map.get(&3), None);
1488            assert_eq!(map.len(), 5);
1489
1490            // Inexistent key (insert)
1491            match map.entry(10) {
1492                Occupied(_) => unreachable!(),
1493                Vacant(view) => {
1494                    assert_eq!(*view.insert(1000), 1000);
1495                }
1496            }
1497            assert_eq!(map.get(&10).unwrap(), &1000);
1498            assert_eq!(map.len(), 6);
1499        }
1500
1501        #[test]
1502        fn test_occupied_entry_key() {
1503            let mut a = HashMap::new();
1504            let key = "hello there";
1505            let value = "value goes here";
1506            assert!(a.is_empty());
1507            a.insert(key, value);
1508            assert_eq!(a.len(), 1);
1509            assert_eq!(a[key], value);
1510
1511            match a.entry(key) {
1512                Vacant(_) => panic!(),
1513                Occupied(e) => assert_eq!(key, *e.key()),
1514            }
1515            assert_eq!(a.len(), 1);
1516            assert_eq!(a[key], value);
1517        }
1518
1519        #[test]
1520        fn test_vacant_entry_key() {
1521            let mut a = HashMap::new();
1522            let key = "hello there";
1523            let value = "value goes here";
1524
1525            assert!(a.is_empty());
1526            match a.entry(key) {
1527                Occupied(_) => panic!(),
1528                Vacant(e) => {
1529                    assert_eq!(key, *e.key());
1530                    e.insert(value);
1531                }
1532            }
1533            assert_eq!(a.len(), 1);
1534            assert_eq!(a[key], value);
1535        }
1536
1537        #[test]
1538        fn test_index() {
1539            let mut map = HashMap::new();
1540
1541            map.insert(1, 2);
1542            map.insert(2, 1);
1543            map.insert(3, 4);
1544
1545            assert_eq!(map[&2], 1);
1546        }
1547
1548        #[test]
1549        fn test_eq() {
1550            let mut m1 = HashMap::new();
1551            m1.insert(1, 2);
1552            m1.insert(2, 3);
1553            m1.insert(3, 4);
1554
1555            let mut m2 = HashMap::new();
1556            m2.insert(1, 2);
1557            m2.insert(2, 3);
1558
1559            assert!(m1 != m2);
1560
1561            m2.insert(3, 4);
1562
1563            assert_eq!(m1, m2);
1564        }
1565
1566        #[test]
1567        fn test_show() {
1568            let mut map = HashMap::new();
1569            let empty: HashMap<i32, i32> = HashMap::new();
1570
1571            map.insert(1, 2);
1572            map.insert(3, 4);
1573
1574            let map_str = format!("{map:?}");
1575
1576            assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
1577            assert_eq!(format!("{empty:?}"), "{}");
1578        }
1579    }
1580
1581    #[test]
1582    fn test_fast_mod() {
1583        let h = HashType(10);
1584        assert_eq!(h.fast_mod(8), 2);
1585    }
1586
1587    #[cfg(not(miri))]
1588    quickcheck::quickcheck! {
1589        fn test_against_btree_map(entries: Vec<(u8, u32)>) -> bool {
1590            let std_hashmap = alloc::collections::BTreeMap::from_iter(entries.clone());
1591            let agb_hashmap = HashMap::from_iter(entries);
1592
1593            if std_hashmap.len() != agb_hashmap.len() {
1594                return false;
1595            }
1596
1597            std_hashmap.iter().all(|(key, value)| agb_hashmap.get(key) == Some(value)) &&
1598            agb_hashmap.iter().all(|(key, value)| std_hashmap.get(key) == Some(value))
1599        }
1600    }
1601}