Skip to main content

axhash_core/hash/
build.rs

1use core::hash::BuildHasher;
2
3use crate::constants::SECRET;
4
5use super::AxHasher;
6
7// A [`BuildHasher`] that constructs [`AxHasher`] instances.
8//
9// Use this type as the hasher factory for `HashMap`, `HashSet`, and any
10// other collection that accepts a custom `BuildHasher`.
11//
12// # Seeding
13//
14// [`AxBuildHasher::new`] uses an internal constant as the seed. For
15// hash-flooding resistance supply your own seed with
16// [`AxBuildHasher::with_seed`].
17//
18// # Example
19//
20// ```rust
21// use std::collections::HashMap;
22// use axhash_core::AxBuildHasher;
23//
24// // Fixed seed — deterministic across runs.
25// let mut map: HashMap<&str, u32, AxBuildHasher> =
26//     HashMap::with_hasher(AxBuildHasher::with_seed(0xfeed_beef));
27// map.insert("alpha", 1);
28// map.insert("beta",  2);
29// assert_eq!(map["alpha"], 1);
30// ```
31#[derive(Clone, Copy, Default)]
32pub struct AxBuildHasher {
33    pub(crate) prepared_seed: u64,
34}
35
36impl AxBuildHasher {
37    // Creates an `AxBuildHasher` using the library's built-in default seed.
38    //
39    // The output is deterministic for a given input but the seed value itself
40    // is an internal constant and may change between crate versions.
41    #[inline(always)]
42    pub const fn new() -> Self {
43        Self {
44            prepared_seed: SECRET[0],
45        }
46    }
47
48    // Creates an `AxBuildHasher` with a caller-supplied `seed`.
49    //
50    // Use a random 64-bit value (e.g. from `rand` or OS entropy) to achieve
51    // per-process hash randomisation and resist hash-flooding attacks.
52    //
53    // # Example
54    //
55    // ```rust
56    // use axhash_core::AxBuildHasher;
57    //
58    // let bh = AxBuildHasher::with_seed(0x0123_4567_89ab_cdef);
59    // ```
60    #[inline(always)]
61    pub const fn with_seed(seed: u64) -> Self {
62        Self {
63            prepared_seed: seed ^ SECRET[0],
64        }
65    }
66}
67
68impl BuildHasher for AxBuildHasher {
69    type Hasher = AxHasher;
70
71    #[inline(always)]
72    fn build_hasher(&self) -> Self::Hasher {
73        AxHasher {
74            acc: self.prepared_seed,
75            sponge: 0,
76            sponge_bits: 0,
77        }
78    }
79}