From 3a5e0c400604f30a29ddbfe2df972d661efb8dbd Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 17 Jan 2024 21:11:00 +0100 Subject: [PATCH] Add `FxSeededState` & co --- src/lib.rs | 4 ++++ src/seeded_state.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 src/seeded_state.rs diff --git a/src/lib.rs b/src/lib.rs index 139ff73..14b965b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,8 @@ extern crate rand; #[cfg(feature = "rand")] mod random_state; +mod seeded_state; + use core::convert::TryInto; use core::default::Default; #[cfg(feature = "std")] @@ -55,6 +57,8 @@ pub type FxHashSet = HashSet>; #[cfg(feature = "rand")] pub use random_state::{FxHashMapRand, FxHashSetRand, FxRandomState}; +pub use seeded_state::{FxHashMapSeed, FxHashSetSeed, FxSeededState}; + /// A speedy hash algorithm for use within rustc. The hashmap in liballoc /// by default uses SipHash which isn't quite as speedy as we want. In the /// compiler we're not really worried about DOS attempts, so we use a fast diff --git a/src/seeded_state.rs b/src/seeded_state.rs new file mode 100644 index 0000000..8b8c213 --- /dev/null +++ b/src/seeded_state.rs @@ -0,0 +1,56 @@ +use std::collections::{HashMap, HashSet}; + +use crate::FxHasher; + +/// Type alias for a hashmap using the `fx` hash algorithm with [`FxSeededState`]. +pub type FxHashMapSeed = HashMap; + +/// Type alias for a hashmap using the `fx` hash algorithm with [`FxSeededState`]. +pub type FxHashSetSeed = HashSet; + +/// [`FxSetState`] is an alternative state for `HashMap` types, allowing to use [`FxHasher`] with a set seed. +/// +/// ``` +/// # use std::collections::HashMap; +/// use rustc_hash::FxSeededState; +/// +/// let mut map = HashMap::with_hasher(FxSeededState::with_seed(12)); +/// map.insert(15, 610); +/// assert_eq!(map[&15], 610); +/// ``` +pub struct FxSeededState { + seed: usize, +} + +impl FxSeededState { + /// Constructs a new `FxSeededState` that is initialized with a `seed`. + pub fn with_seed(seed: usize) -> FxSeededState { + Self { seed } + } +} + +impl core::hash::BuildHasher for FxSeededState { + type Hasher = FxHasher; + + fn build_hasher(&self) -> Self::Hasher { + FxHasher::with_seed(self.seed) + } +} + +#[cfg(test)] +mod tests { + use core::hash::BuildHasher; + + use crate::{FxHashMapSeed, FxSeededState}; + + #[test] + fn different_states_are_different() { + let a = FxHashMapSeed::<&str, u32>::with_hasher(FxSeededState::with_seed(1)); + let b = FxHashMapSeed::<&str, u32>::with_hasher(FxSeededState::with_seed(2)); + + assert_ne!( + a.hasher().build_hasher().hash, + b.hasher().build_hasher().hash + ); + } +}