alloy-primitives 1.5.7

Ethereum primitive types
Documentation
//! Re-exports of map types and utilities.
//!
//! This module exports the following types:
//! - [`HashMap`] and [`HashSet`] from the standard library or `hashbrown` crate. The
//!   "map-hashbrown" feature can be used to force the use of `hashbrown`, and is required in
//!   `no_std` environments.
//! - [`IndexMap`] and [`IndexSet`] from the `indexmap` crate, if the "map-indexmap" feature is
//!   enabled.
//! - The previously-listed hash map types prefixed with `Fb`. These are type aliases with
//!   [`FixedBytes<N>`][fb] as the key, and [`FbBuildHasher`] as the hasher builder. This hasher is
//!   optimized for hashing fixed-size byte arrays.
//! - The previously-listed hash map types prefixed with [`Selector`], [`Address`], and [`B256`].
//!   These use [`FbBuildHasher`] with the respective fixed-size byte array as the key. See the
//!   previous point for more information.
//!
//! Unless specified otherwise, the default hasher builder used by these types is
//! [`DefaultHashBuilder`]. This hasher prioritizes speed over security. Users who require HashDoS
//! resistance should enable the "rand" feature so that the hasher is initialized using a random
//! seed.
//!
//! Note that using the types provided in this module may require using different APIs than the
//! standard library as they might not be generic over the hasher state, such as using
//! `HashMap::default()` instead of `HashMap::new()`.
//!
//! [fb]: crate::FixedBytes
//! [`Selector`]: crate::Selector
//! [`Address`]: crate::Address
//! [`B256`]: crate::B256

use cfg_if::cfg_if;

mod hasher;
pub use hasher::*;

mod fixed;
pub use fixed::*;

// The `HashMap` implementation.
// Use `hashbrown` if requested with "map-hashbrown" or required by `no_std`.
cfg_if! {
    if #[cfg(any(feature = "map-hashbrown", not(feature = "std")))] {
        use hashbrown as imp;

        /// A view into a single entry in a map, which may either be vacant or occupied.
        ///
        /// See [`Entry`](imp::hash_map::Entry) for more information.
        pub type Entry<'a, K, V, S = DefaultHashBuilder> = imp::hash_map::Entry<'a, K, V, S>;
        /// A view into an occupied entry in a `HashMap`. It is part of the [`Entry`] enum.
        ///
        /// See [`OccupiedEntry`](imp::hash_map::OccupiedEntry) for more information.
        pub type OccupiedEntry<'a, K, V, S = DefaultHashBuilder> = imp::hash_map::OccupiedEntry<'a, K, V, S>;
        /// A view into a vacant entry in a `HashMap`. It is part of the [`Entry`] enum.
        ///
        /// See [`VacantEntry`](imp::hash_map::VacantEntry) for more information.
        pub type VacantEntry<'a, K, V, S = DefaultHashBuilder> = imp::hash_map::VacantEntry<'a, K, V, S>;
    } else {
        use hashbrown as _;
        use std::collections as imp;
        #[doc(no_inline)]
        pub use imp::hash_map::{Entry, OccupiedEntry, VacantEntry};
    }
}

#[doc(no_inline)]
pub use imp::{hash_map, hash_set};

/// A [`HashMap`](imp::HashMap) using the [default hasher](DefaultHasher).
///
/// See [`HashMap`](imp::HashMap) for more information.
pub type HashMap<K, V, S = DefaultHashBuilder> = imp::HashMap<K, V, S>;
/// A [`HashSet`](imp::HashSet) using the [default hasher](DefaultHasher).
///
/// See [`HashSet`](imp::HashSet) for more information.
pub type HashSet<V, S = DefaultHashBuilder> = imp::HashSet<V, S>;

// `indexmap` re-exports.
cfg_if! {
    if #[cfg(feature = "map-indexmap")] {
        #[doc(no_inline)]
        pub use indexmap::{self, map::Entry as IndexEntry};

        /// [`IndexMap`](indexmap::IndexMap) using the [default hasher](DefaultHasher).
        ///
        /// See [`IndexMap`](indexmap::IndexMap) for more information.
        pub type IndexMap<K, V, S = DefaultHashBuilder> = indexmap::IndexMap<K, V, S>;
        /// [`IndexSet`](indexmap::IndexSet) using the [default hasher](DefaultHasher).
        ///
        /// See [`IndexSet`](indexmap::IndexSet) for more information.
        pub type IndexSet<V, S = DefaultHashBuilder> = indexmap::IndexSet<V, S>;
    }
}

/// This module contains the rayon parallel iterator types for hash maps (HashMap<K, V>).
///
/// You will rarely need to interact with it directly unless you have need to name one
/// of the iterator types.
#[cfg(feature = "rayon")]
pub mod rayon {
    use super::*;

    cfg_if! {
        if #[cfg(any(feature = "map-hashbrown", not(feature = "std")))] {
            pub use hashbrown::hash_map::rayon::{
                IntoParIter as IntoIter,
                ParDrain as Drain,
                ParIter as Iter,
                ParIterMut as IterMut,
                ParKeys as Keys,
                ParValues as Values,
                ParValuesMut as ValuesMut
            };
            use ::rayon as _;
        } else {
            pub use ::rayon::collections::hash_map::*;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn default_hasher_builder_traits() {
        let hash_builder = <DefaultHashBuilder as Default>::default();
        let _hash_builder2 = <DefaultHashBuilder as Clone>::clone(&hash_builder);
        let mut hasher =
            <DefaultHashBuilder as core::hash::BuildHasher>::build_hasher(&hash_builder);

        <DefaultHasher as core::hash::Hasher>::write_u8(&mut hasher, 0);
        let _hasher2 = <DefaultHasher as Clone>::clone(&hasher);
    }

    // Check that the `Entry` types are correct.
    fn use_entry(e: Entry<'_, u32, u64>) -> u64 {
        match e {
            Entry::Occupied(o) => {
                let o: OccupiedEntry<'_, u32, u64> = o;
                *o.get()
            }
            Entry::Vacant(v) => {
                let v: VacantEntry<'_, u32, u64> = v;
                *v.insert(0)
            }
        }
    }

    #[test]
    fn test_entry() {
        let mut map = HashMap::<u32, u64>::default();
        map.insert(1, 1);
        assert_eq!(use_entry(map.entry(0)), 0);
        assert_eq!(use_entry(map.entry(1)), 1);
        assert_eq!(use_entry(map.entry(2)), 0);
    }
}