use std::cell::Cell;
use std::hash::BuildHasher;
use crate::{rapidrng_fast, RapidHasher};
#[derive(Copy, Clone, Eq, PartialEq)]
pub struct RapidRandomState {
seed: u64,
}
impl RapidRandomState {
pub fn new() -> Self {
#[cfg(feature = "rand")]
thread_local! {
static RANDOM_SEED: Cell<u64> = {
Cell::new(rand::random())
}
}
#[cfg(all(feature = "std", not(feature = "rand")))]
thread_local! {
static RANDOM_SEED: Cell<u64> = {
let mut seed = crate::RAPID_SEED;
Cell::new(crate::rapidrng_time(&mut seed))
}
}
let mut seed = RANDOM_SEED.with(|cell| {
let seed = cell.get();
cell.set(seed.wrapping_add(1));
seed
});
Self {
seed: rapidrng_fast(&mut seed),
}
}
}
impl Default for RapidRandomState {
fn default() -> Self {
Self::new()
}
}
impl BuildHasher for RapidRandomState {
type Hasher = RapidHasher;
fn build_hasher(&self) -> Self::Hasher {
RapidHasher::new(self.seed)
}
}
#[cfg(test)]
mod tests {
use std::hash::{BuildHasher, Hasher, RandomState};
#[test]
fn test_random_state() {
let state1 = RandomState::new();
let mut hash1a = state1.build_hasher();
let mut hash1b = state1.build_hasher();
let state2 = RandomState::new();
let mut hash2a = state2.build_hasher();
hash1a.write(b"hello");
hash1b.write(b"hello");
hash2a.write(b"hello");
let finish1a = hash1a.finish();
let finish1b = hash1b.finish();
let finish2a = hash2a.finish();
assert_eq!(finish1a, finish1b);
assert_ne!(finish1a, finish2a);
}
}