//! This module exists to isolate [`RandomState`] and [`DefaultHasher`] outside of the //! [`collections`] module without actually publicly exporting them, so that parts of that //! implementation can more easily be moved to the [`alloc`] crate. //! //! Although its items are public and contain stability attributes, they can't actually be accessed //! outside this crate. //! //! [`collections`]: crate::collections #[allow(deprecated)] use super::{BuildHasher, Hasher, SipHasher13}; use crate::cell::Cell; use crate::fmt; use crate::sys; /// `RandomState` is the default state for [`HashMap`] types. /// /// A particular instance `RandomState` will create the same instances of /// [`Hasher`], but the hashers created by two different `RandomState` /// instances are unlikely to produce the same result for the same values. /// /// [`HashMap`]: crate::collections::HashMap /// /// # Examples /// /// ``` /// use std::collections::HashMap; /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// let mut map = HashMap::with_hasher(s); /// map.insert(1, 2); /// ``` #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] #[derive(Clone)] pub struct RandomState { k0: u64, k1: u64, } impl RandomState { /// Constructs a new `RandomState` that is initialized with random keys. /// /// # Examples /// /// ``` /// use std::hash::RandomState; /// /// let s = RandomState::new(); /// ``` #[inline] #[allow(deprecated)] // rand #[must_use] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn new() -> RandomState { // Historically this function did not cache keys from the OS and instead // simply always called `rand::thread_rng().gen()` twice. In #31356 it // was discovered, however, that because we re-seed the thread-local RNG // from the OS periodically that this can cause excessive slowdown when // many hash maps are created on a thread. To solve this performance // trap we cache the first set of randomly generated keys per-thread. // // Later in #36481 it was discovered that exposing a deterministic // iteration order allows a form of DOS attack. To counter that we // increment one of the seeds on every RandomState creation, giving // every corresponding HashMap a different iteration order. thread_local!(static KEYS: Cell<(u64, u64)> = { Cell::new(sys::hashmap_random_keys()) }); KEYS.with(|keys| { let (k0, k1) = keys.get(); keys.set((k0.wrapping_add(1), k1)); RandomState { k0, k1 } }) } } #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] impl BuildHasher for RandomState { type Hasher = DefaultHasher; #[inline] #[allow(deprecated)] fn build_hasher(&self) -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(self.k0, self.k1)) } } /// The default [`Hasher`] used by [`RandomState`]. /// /// The internal algorithm is not specified, and so it and its hashes should /// not be relied upon over releases. #[allow(deprecated)] #[derive(Clone, Debug)] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub struct DefaultHasher(SipHasher13); impl DefaultHasher { /// Creates a new `DefaultHasher`. /// /// This hasher is not guaranteed to be the same as all other /// `DefaultHasher` instances, but is the same as all other `DefaultHasher` /// instances created through `new` or `default`. #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] #[inline] #[allow(deprecated)] #[rustc_const_unstable(feature = "const_hash", issue = "104061")] #[must_use] pub const fn new() -> DefaultHasher { DefaultHasher(SipHasher13::new_with_keys(0, 0)) } } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] impl Default for DefaultHasher { /// Creates a new `DefaultHasher` using [`new`]. /// See its documentation for more. /// /// [`new`]: DefaultHasher::new #[inline] fn default() -> DefaultHasher { DefaultHasher::new() } } #[stable(feature = "hashmap_default_hasher", since = "1.13.0")] impl Hasher for DefaultHasher { // The underlying `SipHasher13` doesn't override the other // `write_*` methods, so it's ok not to forward them here. #[inline] fn write(&mut self, msg: &[u8]) { self.0.write(msg) } #[inline] fn write_str(&mut self, s: &str) { self.0.write_str(s); } #[inline] fn finish(&self) -> u64 { self.0.finish() } } #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] impl Default for RandomState { /// Constructs a new `RandomState`. #[inline] fn default() -> RandomState { RandomState::new() } } #[stable(feature = "std_debug", since = "1.16.0")] impl fmt::Debug for RandomState { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("RandomState").finish_non_exhaustive() } }