Coverage Report

Created: 2025-12-31 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/foldhash-0.1.5/src/quality.rs
Line
Count
Source
1
//! The foldhash implementation optimized for quality.
2
3
use core::hash::{BuildHasher, Hasher};
4
5
use crate::seed::SharedSeed;
6
7
use crate::{fast, folded_multiply, ARBITRARY0, ARBITRARY8};
8
9
/// A [`Hasher`] instance implementing foldhash, optimized for quality.
10
///
11
/// While you can create one directly with [`FoldHasher::with_seed`], you
12
/// most likely want to use [`RandomState`], [`SeedableRandomState`] or
13
/// [`FixedState`] to create [`FoldHasher`]s.
14
#[derive(Clone)]
15
pub struct FoldHasher {
16
    pub(crate) inner: fast::FoldHasher,
17
}
18
19
impl FoldHasher {
20
    /// Initializes this [`FoldHasher`] with the given per-hasher seed and
21
    /// [`SharedSeed`].
22
    #[inline(always)]
23
0
    pub fn with_seed(per_hasher_seed: u64, shared_seed: &SharedSeed) -> FoldHasher {
24
0
        FoldHasher {
25
0
            inner: fast::FoldHasher::with_seed(per_hasher_seed, shared_seed),
26
0
        }
27
0
    }
28
}
29
30
impl Hasher for FoldHasher {
31
    #[inline(always)]
32
0
    fn write(&mut self, bytes: &[u8]) {
33
0
        self.inner.write(bytes);
34
0
    }
35
36
    #[inline(always)]
37
0
    fn write_u8(&mut self, i: u8) {
38
0
        self.inner.write_u8(i);
39
0
    }
40
41
    #[inline(always)]
42
0
    fn write_u16(&mut self, i: u16) {
43
0
        self.inner.write_u16(i);
44
0
    }
45
46
    #[inline(always)]
47
0
    fn write_u32(&mut self, i: u32) {
48
0
        self.inner.write_u32(i);
49
0
    }
50
51
    #[inline(always)]
52
0
    fn write_u64(&mut self, i: u64) {
53
0
        self.inner.write_u64(i);
54
0
    }
55
56
    #[inline(always)]
57
0
    fn write_u128(&mut self, i: u128) {
58
0
        self.inner.write_u128(i);
59
0
    }
60
61
    #[inline(always)]
62
0
    fn write_usize(&mut self, i: usize) {
63
0
        self.inner.write_usize(i);
64
0
    }
65
66
    #[inline(always)]
67
0
    fn finish(&self) -> u64 {
68
0
        folded_multiply(self.inner.finish(), ARBITRARY0)
69
0
    }
70
}
71
72
/// A [`BuildHasher`] for [`quality::FoldHasher`](FoldHasher) that is randomly initialized.
73
#[derive(Copy, Clone, Default, Debug)]
74
pub struct RandomState {
75
    inner: fast::RandomState,
76
}
77
78
impl BuildHasher for RandomState {
79
    type Hasher = FoldHasher;
80
81
    #[inline(always)]
82
0
    fn build_hasher(&self) -> FoldHasher {
83
0
        FoldHasher {
84
0
            inner: self.inner.build_hasher(),
85
0
        }
86
0
    }
87
}
88
89
/// A [`BuildHasher`] for [`quality::FoldHasher`](FoldHasher) that is randomly
90
/// initialized by default, but can also be initialized with a specific seed.
91
///
92
/// This can be useful for e.g. testing, but the downside is that this type
93
/// has a size of 16 bytes rather than the 8 bytes [`RandomState`] is.
94
#[derive(Copy, Clone, Default, Debug)]
95
pub struct SeedableRandomState {
96
    inner: fast::SeedableRandomState,
97
}
98
99
impl SeedableRandomState {
100
    /// Generates a random [`SeedableRandomState`], similar to [`RandomState`].
101
    #[inline(always)]
102
0
    pub fn random() -> Self {
103
0
        Self {
104
0
            inner: fast::SeedableRandomState::random(),
105
0
        }
106
0
    }
107
108
    /// Generates a fixed [`SeedableRandomState`], similar to [`FixedState`].
109
    #[inline(always)]
110
0
    pub fn fixed() -> Self {
111
0
        Self {
112
0
            inner: fast::SeedableRandomState::fixed(),
113
0
        }
114
0
    }
115
116
    /// Generates a [`SeedableRandomState`] with the given per-hasher seed
117
    /// and [`SharedSeed`].
118
    #[inline(always)]
119
0
    pub fn with_seed(per_hasher_seed: u64, shared_seed: &'static SharedSeed) -> Self {
120
0
        Self {
121
0
            // We do an additional folded multiply with the seed here for
122
0
            // the quality hash to ensure better independence between seed
123
0
            // and hash.
124
0
            inner: fast::SeedableRandomState::with_seed(
125
0
                folded_multiply(per_hasher_seed, ARBITRARY8),
126
0
                shared_seed,
127
0
            ),
128
0
        }
129
0
    }
130
}
131
132
impl BuildHasher for SeedableRandomState {
133
    type Hasher = FoldHasher;
134
135
    #[inline(always)]
136
0
    fn build_hasher(&self) -> FoldHasher {
137
0
        FoldHasher {
138
0
            inner: self.inner.build_hasher(),
139
0
        }
140
0
    }
141
}
142
143
/// A [`BuildHasher`] for [`quality::FoldHasher`](FoldHasher) that always has the same fixed seed.
144
///
145
/// Not recommended unless you absolutely need determinism.
146
#[derive(Copy, Clone, Default, Debug)]
147
pub struct FixedState {
148
    inner: fast::FixedState,
149
}
150
151
impl FixedState {
152
    /// Creates a [`FixedState`] with the given per-hasher seed.
153
    #[inline(always)]
154
0
    pub const fn with_seed(per_hasher_seed: u64) -> Self {
155
0
        Self {
156
0
            // We do an additional folded multiply with the seed here for
157
0
            // the quality hash to ensure better independence between seed
158
0
            // and hash. If the seed is zero the folded multiply is zero,
159
0
            // preserving with_seed(0) == default().
160
0
            inner: fast::FixedState::with_seed(folded_multiply(per_hasher_seed, ARBITRARY8)),
161
0
        }
162
0
    }
163
}
164
165
impl BuildHasher for FixedState {
166
    type Hasher = FoldHasher;
167
168
    #[inline(always)]
169
0
    fn build_hasher(&self) -> FoldHasher {
170
0
        FoldHasher {
171
0
            inner: self.inner.build_hasher(),
172
0
        }
173
0
    }
174
}