Coverage Report

Created: 2025-07-01 06:37

/rust/registry/src/index.crates.io-6f17d22bba15001f/twox-hash-2.1.1/src/xxhash32.rs
Line
Count
Source (jump to first uncovered line)
1
//! The implementation of XXH32.
2
3
use core::{
4
    fmt,
5
    hash::{self, BuildHasher},
6
    mem,
7
};
8
9
use crate::{IntoU32, IntoU64};
10
11
// Keeping these constants in this form to match the C code.
12
const PRIME32_1: u32 = 0x9E3779B1;
13
const PRIME32_2: u32 = 0x85EBCA77;
14
const PRIME32_3: u32 = 0xC2B2AE3D;
15
const PRIME32_4: u32 = 0x27D4EB2F;
16
const PRIME32_5: u32 = 0x165667B1;
17
18
type Lane = u32;
19
type Lanes = [Lane; 4];
20
type Bytes = [u8; 16];
21
22
const BYTES_IN_LANE: usize = mem::size_of::<Bytes>();
23
24
#[derive(Clone, PartialEq)]
25
struct BufferData(Lanes);
26
27
impl BufferData {
28
150M
    const fn new() -> Self {
29
150M
        Self([0; 4])
30
150M
    }
31
32
150M
    const fn bytes(&self) -> &Bytes {
33
        const _: () = assert!(mem::align_of::<u8>() <= mem::align_of::<Lane>());
34
        // SAFETY[bytes]: The alignment of `u32` is at least that of
35
        // `u8` and all the values are initialized.
36
150M
        unsafe { &*self.0.as_ptr().cast() }
37
150M
    }
38
39
511M
    fn bytes_mut(&mut self) -> &mut Bytes {
40
511M
        // SAFETY: See SAFETY[bytes]
41
511M
        unsafe { &mut *self.0.as_mut_ptr().cast() }
42
511M
    }
43
}
44
45
impl fmt::Debug for BufferData {
46
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47
0
        f.debug_list().entries(self.0.iter()).finish()
48
0
    }
49
}
50
51
#[derive(Debug, Clone, PartialEq)]
52
struct Buffer {
53
    offset: usize,
54
    data: BufferData,
55
}
56
57
impl Buffer {
58
150M
    const fn new() -> Self {
59
150M
        Self {
60
150M
            offset: 0,
61
150M
            data: BufferData::new(),
62
150M
        }
63
150M
    }
64
65
    // RATIONALE: See RATIONALE[inline]
66
    #[inline]
67
452M
    fn extend<'d>(&mut self, data: &'d [u8]) -> (Option<&Lanes>, &'d [u8]) {
68
452M
        // Most of the slice methods we use here have `_unchecked` variants, but
69
452M
        //
70
452M
        // 1. this method is called one time per `Hasher::write` call
71
452M
        // 2. this method early exits if we don't have anything in the buffer
72
452M
        //
73
452M
        // Because of this, removing the panics via `unsafe` doesn't
74
452M
        // have much benefit other than reducing code size by a tiny
75
452M
        // bit.
76
452M
77
452M
        if self.offset == 0 {
78
210M
            return (None, data);
79
242M
        };
80
242M
81
242M
        let bytes = self.data.bytes_mut();
82
242M
        debug_assert!(self.offset <= bytes.len());
83
84
242M
        let empty = &mut bytes[self.offset..];
85
242M
        let n_to_copy = usize::min(empty.len(), data.len());
86
242M
87
242M
        let dst = &mut empty[..n_to_copy];
88
242M
89
242M
        let (src, rest) = data.split_at(n_to_copy);
90
242M
91
242M
        dst.copy_from_slice(src);
92
242M
        self.offset += n_to_copy;
93
242M
94
242M
        debug_assert!(self.offset <= bytes.len());
95
96
242M
        if self.offset == bytes.len() {
97
121M
            self.offset = 0;
98
121M
            (Some(&self.data.0), rest)
99
        } else {
100
120M
            (None, rest)
101
        }
102
452M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Buffer>::extend
<twox_hash::xxhash32::Buffer>::extend
Line
Count
Source
67
452M
    fn extend<'d>(&mut self, data: &'d [u8]) -> (Option<&Lanes>, &'d [u8]) {
68
452M
        // Most of the slice methods we use here have `_unchecked` variants, but
69
452M
        //
70
452M
        // 1. this method is called one time per `Hasher::write` call
71
452M
        // 2. this method early exits if we don't have anything in the buffer
72
452M
        //
73
452M
        // Because of this, removing the panics via `unsafe` doesn't
74
452M
        // have much benefit other than reducing code size by a tiny
75
452M
        // bit.
76
452M
77
452M
        if self.offset == 0 {
78
210M
            return (None, data);
79
242M
        };
80
242M
81
242M
        let bytes = self.data.bytes_mut();
82
242M
        debug_assert!(self.offset <= bytes.len());
83
84
242M
        let empty = &mut bytes[self.offset..];
85
242M
        let n_to_copy = usize::min(empty.len(), data.len());
86
242M
87
242M
        let dst = &mut empty[..n_to_copy];
88
242M
89
242M
        let (src, rest) = data.split_at(n_to_copy);
90
242M
91
242M
        dst.copy_from_slice(src);
92
242M
        self.offset += n_to_copy;
93
242M
94
242M
        debug_assert!(self.offset <= bytes.len());
95
96
242M
        if self.offset == bytes.len() {
97
121M
            self.offset = 0;
98
121M
            (Some(&self.data.0), rest)
99
        } else {
100
120M
            (None, rest)
101
        }
102
452M
    }
<twox_hash::xxhash32::Buffer>::extend
Line
Count
Source
67
60.5k
    fn extend<'d>(&mut self, data: &'d [u8]) -> (Option<&Lanes>, &'d [u8]) {
68
60.5k
        // Most of the slice methods we use here have `_unchecked` variants, but
69
60.5k
        //
70
60.5k
        // 1. this method is called one time per `Hasher::write` call
71
60.5k
        // 2. this method early exits if we don't have anything in the buffer
72
60.5k
        //
73
60.5k
        // Because of this, removing the panics via `unsafe` doesn't
74
60.5k
        // have much benefit other than reducing code size by a tiny
75
60.5k
        // bit.
76
60.5k
77
60.5k
        if self.offset == 0 {
78
60.5k
            return (None, data);
79
0
        };
80
0
81
0
        let bytes = self.data.bytes_mut();
82
0
        debug_assert!(self.offset <= bytes.len());
83
84
0
        let empty = &mut bytes[self.offset..];
85
0
        let n_to_copy = usize::min(empty.len(), data.len());
86
0
87
0
        let dst = &mut empty[..n_to_copy];
88
0
89
0
        let (src, rest) = data.split_at(n_to_copy);
90
0
91
0
        dst.copy_from_slice(src);
92
0
        self.offset += n_to_copy;
93
0
94
0
        debug_assert!(self.offset <= bytes.len());
95
96
0
        if self.offset == bytes.len() {
97
0
            self.offset = 0;
98
0
            (Some(&self.data.0), rest)
99
        } else {
100
0
            (None, rest)
101
        }
102
60.5k
    }
<twox_hash::xxhash32::Buffer>::extend
Line
Count
Source
67
27.3k
    fn extend<'d>(&mut self, data: &'d [u8]) -> (Option<&Lanes>, &'d [u8]) {
68
27.3k
        // Most of the slice methods we use here have `_unchecked` variants, but
69
27.3k
        //
70
27.3k
        // 1. this method is called one time per `Hasher::write` call
71
27.3k
        // 2. this method early exits if we don't have anything in the buffer
72
27.3k
        //
73
27.3k
        // Because of this, removing the panics via `unsafe` doesn't
74
27.3k
        // have much benefit other than reducing code size by a tiny
75
27.3k
        // bit.
76
27.3k
77
27.3k
        if self.offset == 0 {
78
4.21k
            return (None, data);
79
23.1k
        };
80
23.1k
81
23.1k
        let bytes = self.data.bytes_mut();
82
23.1k
        debug_assert!(self.offset <= bytes.len());
83
84
23.1k
        let empty = &mut bytes[self.offset..];
85
23.1k
        let n_to_copy = usize::min(empty.len(), data.len());
86
23.1k
87
23.1k
        let dst = &mut empty[..n_to_copy];
88
23.1k
89
23.1k
        let (src, rest) = data.split_at(n_to_copy);
90
23.1k
91
23.1k
        dst.copy_from_slice(src);
92
23.1k
        self.offset += n_to_copy;
93
23.1k
94
23.1k
        debug_assert!(self.offset <= bytes.len());
95
96
23.1k
        if self.offset == bytes.len() {
97
5.33k
            self.offset = 0;
98
5.33k
            (Some(&self.data.0), rest)
99
        } else {
100
17.7k
            (None, rest)
101
        }
102
27.3k
    }
103
104
    // RATIONALE: See RATIONALE[inline]
105
    #[inline]
106
452M
    fn set(&mut self, data: &[u8]) {
107
452M
        if data.is_empty() {
108
183M
            return;
109
269M
        }
110
269M
111
269M
        debug_assert_eq!(self.offset, 0);
112
113
269M
        let n_to_copy = data.len();
114
269M
115
269M
        let bytes = self.data.bytes_mut();
116
269M
        debug_assert!(n_to_copy < bytes.len());
117
118
269M
        bytes[..n_to_copy].copy_from_slice(data);
119
269M
        self.offset = data.len();
120
452M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Buffer>::set
<twox_hash::xxhash32::Buffer>::set
Line
Count
Source
106
452M
    fn set(&mut self, data: &[u8]) {
107
452M
        if data.is_empty() {
108
183M
            return;
109
269M
        }
110
269M
111
269M
        debug_assert_eq!(self.offset, 0);
112
113
269M
        let n_to_copy = data.len();
114
269M
115
269M
        let bytes = self.data.bytes_mut();
116
269M
        debug_assert!(n_to_copy < bytes.len());
117
118
269M
        bytes[..n_to_copy].copy_from_slice(data);
119
269M
        self.offset = data.len();
120
452M
    }
<twox_hash::xxhash32::Buffer>::set
Line
Count
Source
106
60.5k
    fn set(&mut self, data: &[u8]) {
107
60.5k
        if data.is_empty() {
108
0
            return;
109
60.5k
        }
110
60.5k
111
60.5k
        debug_assert_eq!(self.offset, 0);
112
113
60.5k
        let n_to_copy = data.len();
114
60.5k
115
60.5k
        let bytes = self.data.bytes_mut();
116
60.5k
        debug_assert!(n_to_copy < bytes.len());
117
118
60.5k
        bytes[..n_to_copy].copy_from_slice(data);
119
60.5k
        self.offset = data.len();
120
60.5k
    }
<twox_hash::xxhash32::Buffer>::set
Line
Count
Source
106
27.3k
    fn set(&mut self, data: &[u8]) {
107
27.3k
        if data.is_empty() {
108
19.6k
            return;
109
7.67k
        }
110
7.67k
111
7.67k
        debug_assert_eq!(self.offset, 0);
112
113
7.67k
        let n_to_copy = data.len();
114
7.67k
115
7.67k
        let bytes = self.data.bytes_mut();
116
7.67k
        debug_assert!(n_to_copy < bytes.len());
117
118
7.67k
        bytes[..n_to_copy].copy_from_slice(data);
119
7.67k
        self.offset = data.len();
120
27.3k
    }
121
122
    // RATIONALE: See RATIONALE[inline]
123
    #[inline]
124
150M
    fn remaining(&self) -> &[u8] {
125
150M
        &self.data.bytes()[..self.offset]
126
150M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Buffer>::remaining
<twox_hash::xxhash32::Buffer>::remaining
Line
Count
Source
124
150M
    fn remaining(&self) -> &[u8] {
125
150M
        &self.data.bytes()[..self.offset]
126
150M
    }
<twox_hash::xxhash32::Buffer>::remaining
Line
Count
Source
124
60.5k
    fn remaining(&self) -> &[u8] {
125
60.5k
        &self.data.bytes()[..self.offset]
126
60.5k
    }
<twox_hash::xxhash32::Buffer>::remaining
Line
Count
Source
124
2.21k
    fn remaining(&self) -> &[u8] {
125
2.21k
        &self.data.bytes()[..self.offset]
126
2.21k
    }
127
}
128
129
#[derive(Clone, PartialEq)]
130
struct Accumulators(Lanes);
131
132
impl Accumulators {
133
301M
    const fn new(seed: u32) -> Self {
134
301M
        Self([
135
301M
            seed.wrapping_add(PRIME32_1).wrapping_add(PRIME32_2),
136
301M
            seed.wrapping_add(PRIME32_2),
137
301M
            seed,
138
301M
            seed.wrapping_sub(PRIME32_1),
139
301M
        ])
140
301M
    }
141
142
    // RATIONALE: See RATIONALE[inline]
143
    #[inline]
144
1.09G
    fn write(&mut self, lanes: Lanes) {
145
1.09G
        let [acc1, acc2, acc3, acc4] = &mut self.0;
146
1.09G
        let [lane1, lane2, lane3, lane4] = lanes;
147
1.09G
148
1.09G
        *acc1 = round(*acc1, lane1.to_le());
149
1.09G
        *acc2 = round(*acc2, lane2.to_le());
150
1.09G
        *acc3 = round(*acc3, lane3.to_le());
151
1.09G
        *acc4 = round(*acc4, lane4.to_le());
152
1.09G
    }
Unexecuted instantiation: <twox_hash::xxhash32::Accumulators>::write
<twox_hash::xxhash32::Accumulators>::write
Line
Count
Source
144
1.09G
    fn write(&mut self, lanes: Lanes) {
145
1.09G
        let [acc1, acc2, acc3, acc4] = &mut self.0;
146
1.09G
        let [lane1, lane2, lane3, lane4] = lanes;
147
1.09G
148
1.09G
        *acc1 = round(*acc1, lane1.to_le());
149
1.09G
        *acc2 = round(*acc2, lane2.to_le());
150
1.09G
        *acc3 = round(*acc3, lane3.to_le());
151
1.09G
        *acc4 = round(*acc4, lane4.to_le());
152
1.09G
    }
Unexecuted instantiation: <twox_hash::xxhash32::Accumulators>::write
<twox_hash::xxhash32::Accumulators>::write
Line
Count
Source
144
4.63M
    fn write(&mut self, lanes: Lanes) {
145
4.63M
        let [acc1, acc2, acc3, acc4] = &mut self.0;
146
4.63M
        let [lane1, lane2, lane3, lane4] = lanes;
147
4.63M
148
4.63M
        *acc1 = round(*acc1, lane1.to_le());
149
4.63M
        *acc2 = round(*acc2, lane2.to_le());
150
4.63M
        *acc3 = round(*acc3, lane3.to_le());
151
4.63M
        *acc4 = round(*acc4, lane4.to_le());
152
4.63M
    }
153
154
    // RATIONALE: See RATIONALE[inline]
155
    #[inline]
156
603M
    fn write_many<'d>(&mut self, mut data: &'d [u8]) -> &'d [u8] {
157
1.57G
        while let Some((chunk, rest)) = data.split_first_chunk::<BYTES_IN_LANE>() {
158
975M
            // SAFETY: We have the right number of bytes and are
159
975M
            // handling the unaligned case.
160
975M
            let lanes = unsafe { chunk.as_ptr().cast::<Lanes>().read_unaligned() };
161
975M
            self.write(lanes);
162
975M
            data = rest;
163
975M
        }
164
603M
        data
165
603M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Accumulators>::write_many
<twox_hash::xxhash32::Accumulators>::write_many
Line
Count
Source
156
603M
    fn write_many<'d>(&mut self, mut data: &'d [u8]) -> &'d [u8] {
157
1.57G
        while let Some((chunk, rest)) = data.split_first_chunk::<BYTES_IN_LANE>() {
158
970M
            // SAFETY: We have the right number of bytes and are
159
970M
            // handling the unaligned case.
160
970M
            let lanes = unsafe { chunk.as_ptr().cast::<Lanes>().read_unaligned() };
161
970M
            self.write(lanes);
162
970M
            data = rest;
163
970M
        }
164
603M
        data
165
603M
    }
<twox_hash::xxhash32::Accumulators>::write_many
Line
Count
Source
156
60.5k
    fn write_many<'d>(&mut self, mut data: &'d [u8]) -> &'d [u8] {
157
60.5k
        while let Some((chunk, rest)) = data.split_first_chunk::<BYTES_IN_LANE>() {
158
0
            // SAFETY: We have the right number of bytes and are
159
0
            // handling the unaligned case.
160
0
            let lanes = unsafe { chunk.as_ptr().cast::<Lanes>().read_unaligned() };
161
0
            self.write(lanes);
162
0
            data = rest;
163
0
        }
164
60.5k
        data
165
60.5k
    }
<twox_hash::xxhash32::Accumulators>::write_many
Line
Count
Source
156
27.3k
    fn write_many<'d>(&mut self, mut data: &'d [u8]) -> &'d [u8] {
157
4.65M
        while let Some((chunk, rest)) = data.split_first_chunk::<BYTES_IN_LANE>() {
158
4.62M
            // SAFETY: We have the right number of bytes and are
159
4.62M
            // handling the unaligned case.
160
4.62M
            let lanes = unsafe { chunk.as_ptr().cast::<Lanes>().read_unaligned() };
161
4.62M
            self.write(lanes);
162
4.62M
            data = rest;
163
4.62M
        }
164
27.3k
        data
165
27.3k
    }
166
167
    // RATIONALE: See RATIONALE[inline]
168
    #[inline]
169
26.2M
    const fn finish(&self) -> u32 {
170
26.2M
        let [acc1, acc2, acc3, acc4] = self.0;
171
26.2M
172
26.2M
        let acc1 = acc1.rotate_left(1);
173
26.2M
        let acc2 = acc2.rotate_left(7);
174
26.2M
        let acc3 = acc3.rotate_left(12);
175
26.2M
        let acc4 = acc4.rotate_left(18);
176
26.2M
177
26.2M
        acc1.wrapping_add(acc2)
178
26.2M
            .wrapping_add(acc3)
179
26.2M
            .wrapping_add(acc4)
180
26.2M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Accumulators>::finish
<twox_hash::xxhash32::Accumulators>::finish
Line
Count
Source
169
26.2M
    const fn finish(&self) -> u32 {
170
26.2M
        let [acc1, acc2, acc3, acc4] = self.0;
171
26.2M
172
26.2M
        let acc1 = acc1.rotate_left(1);
173
26.2M
        let acc2 = acc2.rotate_left(7);
174
26.2M
        let acc3 = acc3.rotate_left(12);
175
26.2M
        let acc4 = acc4.rotate_left(18);
176
26.2M
177
26.2M
        acc1.wrapping_add(acc2)
178
26.2M
            .wrapping_add(acc3)
179
26.2M
            .wrapping_add(acc4)
180
26.2M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Accumulators>::finish
<twox_hash::xxhash32::Accumulators>::finish
Line
Count
Source
169
787
    const fn finish(&self) -> u32 {
170
787
        let [acc1, acc2, acc3, acc4] = self.0;
171
787
172
787
        let acc1 = acc1.rotate_left(1);
173
787
        let acc2 = acc2.rotate_left(7);
174
787
        let acc3 = acc3.rotate_left(12);
175
787
        let acc4 = acc4.rotate_left(18);
176
787
177
787
        acc1.wrapping_add(acc2)
178
787
            .wrapping_add(acc3)
179
787
            .wrapping_add(acc4)
180
787
    }
181
}
182
183
impl fmt::Debug for Accumulators {
184
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185
0
        let [acc1, acc2, acc3, acc4] = self.0;
186
0
        f.debug_struct("Accumulators")
187
0
            .field("acc1", &acc1)
188
0
            .field("acc2", &acc2)
189
0
            .field("acc3", &acc3)
190
0
            .field("acc4", &acc4)
191
0
            .finish()
192
0
    }
193
}
194
195
/// Calculates the 32-bit hash.
196
///
197
/// ### Caution
198
///
199
/// Although this struct implements [`hash::Hasher`][], it only calculates a
200
/// 32-bit number, leaving the upper bits as 0. This means it is
201
/// unlikely to be correct to use this in places like a [`HashMap`][std::collections::HashMap].
202
#[derive(Debug, Clone, PartialEq)]
203
pub struct Hasher {
204
    seed: u32,
205
    accumulators: Accumulators,
206
    buffer: Buffer,
207
    length: u64,
208
}
209
210
impl Default for Hasher {
211
0
    fn default() -> Self {
212
0
        Self::with_seed(0)
213
0
    }
214
}
215
216
impl Hasher {
217
    /// Hash all data at once. If you can use this function, you may
218
    /// see noticable speed gains for certain types of input.
219
    #[must_use]
220
    // RATIONALE[inline]: Keeping parallel to the 64-bit
221
    // implementation, even though the performance gains for the
222
    // 32-bit version haven't been tested.
223
    #[inline]
224
150M
    pub fn oneshot(seed: u32, data: &[u8]) -> u32 {
225
150M
        let len = data.len();
226
150M
227
150M
        // Since we know that there's no more data coming, we don't
228
150M
        // need to construct the intermediate buffers or copy data to
229
150M
        // or from the buffers.
230
150M
231
150M
        let mut accumulators = Accumulators::new(seed);
232
150M
233
150M
        let data = accumulators.write_many(data);
234
150M
235
150M
        Self::finish_with(seed, len.into_u64(), &accumulators, data)
236
150M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Hasher>::oneshot
<twox_hash::xxhash32::Hasher>::oneshot
Line
Count
Source
224
150M
    pub fn oneshot(seed: u32, data: &[u8]) -> u32 {
225
150M
        let len = data.len();
226
150M
227
150M
        // Since we know that there's no more data coming, we don't
228
150M
        // need to construct the intermediate buffers or copy data to
229
150M
        // or from the buffers.
230
150M
231
150M
        let mut accumulators = Accumulators::new(seed);
232
150M
233
150M
        let data = accumulators.write_many(data);
234
150M
235
150M
        Self::finish_with(seed, len.into_u64(), &accumulators, data)
236
150M
    }
237
238
    /// Constructs the hasher with an initial seed.
239
    #[must_use]
240
150M
    pub const fn with_seed(seed: u32) -> Self {
241
150M
        // Step 1. Initialize internal accumulators
242
150M
        Self {
243
150M
            seed,
244
150M
            accumulators: Accumulators::new(seed),
245
150M
            buffer: Buffer::new(),
246
150M
            length: 0,
247
150M
        }
248
150M
    }
249
250
    /// The seed this hasher was created with.
251
0
    pub const fn seed(&self) -> u32 {
252
0
        self.seed
253
0
    }
254
255
    /// The total number of bytes hashed.
256
0
    pub const fn total_len(&self) -> u64 {
257
0
        self.length
258
0
    }
259
260
    /// The total number of bytes hashed, truncated to 32 bits.
261
    ///
262
    /// For the full 64-bit byte count, use [`total_len`](Self::total_len).
263
0
    pub const fn total_len_32(&self) -> u32 {
264
0
        self.length as u32
265
0
    }
266
267
    /// Returns the hash value for the values written so far. Unlike
268
    /// [`hash::Hasher::finish`][], this method returns the actual 32-bit
269
    /// value calculated, not a 64-bit value.
270
    #[must_use]
271
    // RATIONALE: See RATIONALE[inline]
272
    #[inline]
273
150M
    pub fn finish_32(&self) -> u32 {
274
150M
        Self::finish_with(
275
150M
            self.seed,
276
150M
            self.length,
277
150M
            &self.accumulators,
278
150M
            self.buffer.remaining(),
279
150M
        )
280
150M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Hasher>::finish_32
<twox_hash::xxhash32::Hasher>::finish_32
Line
Count
Source
273
150M
    pub fn finish_32(&self) -> u32 {
274
150M
        Self::finish_with(
275
150M
            self.seed,
276
150M
            self.length,
277
150M
            &self.accumulators,
278
150M
            self.buffer.remaining(),
279
150M
        )
280
150M
    }
<twox_hash::xxhash32::Hasher>::finish_32
Line
Count
Source
273
60.5k
    pub fn finish_32(&self) -> u32 {
274
60.5k
        Self::finish_with(
275
60.5k
            self.seed,
276
60.5k
            self.length,
277
60.5k
            &self.accumulators,
278
60.5k
            self.buffer.remaining(),
279
60.5k
        )
280
60.5k
    }
<twox_hash::xxhash32::Hasher>::finish_32
Line
Count
Source
273
2.21k
    pub fn finish_32(&self) -> u32 {
274
2.21k
        Self::finish_with(
275
2.21k
            self.seed,
276
2.21k
            self.length,
277
2.21k
            &self.accumulators,
278
2.21k
            self.buffer.remaining(),
279
2.21k
        )
280
2.21k
    }
281
282
    #[must_use]
283
    // RATIONALE: See RATIONALE[inline]
284
    #[inline]
285
301M
    fn finish_with(seed: u32, len: u64, accumulators: &Accumulators, mut remaining: &[u8]) -> u32 {
286
        // Step 3. Accumulator convergence
287
301M
        let mut acc = if len < BYTES_IN_LANE.into_u64() {
288
275M
            seed.wrapping_add(PRIME32_5)
289
        } else {
290
26.2M
            accumulators.finish()
291
        };
292
293
        // Step 4. Add input length
294
        //
295
        // "Note that, if input length is so large that it requires
296
        // more than 32-bits, only the lower 32-bits are added to the
297
        // accumulator."
298
301M
        acc += len as u32;
299
300
        // Step 5. Consume remaining input
301
645M
        while let Some((chunk, rest)) = remaining.split_first_chunk() {
302
343M
            let lane = u32::from_ne_bytes(*chunk).to_le();
303
343M
304
343M
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_3));
305
343M
            acc = acc.rotate_left(17).wrapping_mul(PRIME32_4);
306
343M
307
343M
            remaining = rest;
308
343M
        }
309
310
752M
        for &byte in remaining {
311
450M
            let lane = byte.into_u32();
312
450M
313
450M
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_5));
314
450M
            acc = acc.rotate_left(11).wrapping_mul(PRIME32_1);
315
450M
        }
316
317
        // Step 6. Final mix (avalanche)
318
301M
        acc ^= acc >> 15;
319
301M
        acc = acc.wrapping_mul(PRIME32_2);
320
301M
        acc ^= acc >> 13;
321
301M
        acc = acc.wrapping_mul(PRIME32_3);
322
301M
        acc ^= acc >> 16;
323
301M
324
301M
        acc
325
301M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Hasher>::finish_with
<twox_hash::xxhash32::Hasher>::finish_with
Line
Count
Source
285
301M
    fn finish_with(seed: u32, len: u64, accumulators: &Accumulators, mut remaining: &[u8]) -> u32 {
286
        // Step 3. Accumulator convergence
287
301M
        let mut acc = if len < BYTES_IN_LANE.into_u64() {
288
275M
            seed.wrapping_add(PRIME32_5)
289
        } else {
290
26.2M
            accumulators.finish()
291
        };
292
293
        // Step 4. Add input length
294
        //
295
        // "Note that, if input length is so large that it requires
296
        // more than 32-bits, only the lower 32-bits are added to the
297
        // accumulator."
298
301M
        acc += len as u32;
299
300
        // Step 5. Consume remaining input
301
644M
        while let Some((chunk, rest)) = remaining.split_first_chunk() {
302
343M
            let lane = u32::from_ne_bytes(*chunk).to_le();
303
343M
304
343M
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_3));
305
343M
            acc = acc.rotate_left(17).wrapping_mul(PRIME32_4);
306
343M
307
343M
            remaining = rest;
308
343M
        }
309
310
752M
        for &byte in remaining {
311
450M
            let lane = byte.into_u32();
312
450M
313
450M
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_5));
314
450M
            acc = acc.rotate_left(11).wrapping_mul(PRIME32_1);
315
450M
        }
316
317
        // Step 6. Final mix (avalanche)
318
301M
        acc ^= acc >> 15;
319
301M
        acc = acc.wrapping_mul(PRIME32_2);
320
301M
        acc ^= acc >> 13;
321
301M
        acc = acc.wrapping_mul(PRIME32_3);
322
301M
        acc ^= acc >> 16;
323
301M
324
301M
        acc
325
301M
    }
<twox_hash::xxhash32::Hasher>::finish_with
Line
Count
Source
285
60.5k
    fn finish_with(seed: u32, len: u64, accumulators: &Accumulators, mut remaining: &[u8]) -> u32 {
286
        // Step 3. Accumulator convergence
287
60.5k
        let mut acc = if len < BYTES_IN_LANE.into_u64() {
288
60.5k
            seed.wrapping_add(PRIME32_5)
289
        } else {
290
0
            accumulators.finish()
291
        };
292
293
        // Step 4. Add input length
294
        //
295
        // "Note that, if input length is so large that it requires
296
        // more than 32-bits, only the lower 32-bits are added to the
297
        // accumulator."
298
60.5k
        acc += len as u32;
299
300
        // Step 5. Consume remaining input
301
61.2k
        while let Some((chunk, rest)) = remaining.split_first_chunk() {
302
754
            let lane = u32::from_ne_bytes(*chunk).to_le();
303
754
304
754
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_3));
305
754
            acc = acc.rotate_left(17).wrapping_mul(PRIME32_4);
306
754
307
754
            remaining = rest;
308
754
        }
309
310
181k
        for &byte in remaining {
311
121k
            let lane = byte.into_u32();
312
121k
313
121k
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_5));
314
121k
            acc = acc.rotate_left(11).wrapping_mul(PRIME32_1);
315
121k
        }
316
317
        // Step 6. Final mix (avalanche)
318
60.5k
        acc ^= acc >> 15;
319
60.5k
        acc = acc.wrapping_mul(PRIME32_2);
320
60.5k
        acc ^= acc >> 13;
321
60.5k
        acc = acc.wrapping_mul(PRIME32_3);
322
60.5k
        acc ^= acc >> 16;
323
60.5k
324
60.5k
        acc
325
60.5k
    }
<twox_hash::xxhash32::Hasher>::finish_with
Line
Count
Source
285
2.21k
    fn finish_with(seed: u32, len: u64, accumulators: &Accumulators, mut remaining: &[u8]) -> u32 {
286
        // Step 3. Accumulator convergence
287
2.21k
        let mut acc = if len < BYTES_IN_LANE.into_u64() {
288
1.42k
            seed.wrapping_add(PRIME32_5)
289
        } else {
290
787
            accumulators.finish()
291
        };
292
293
        // Step 4. Add input length
294
        //
295
        // "Note that, if input length is so large that it requires
296
        // more than 32-bits, only the lower 32-bits are added to the
297
        // accumulator."
298
2.21k
        acc += len as u32;
299
300
        // Step 5. Consume remaining input
301
2.83k
        while let Some((chunk, rest)) = remaining.split_first_chunk() {
302
624
            let lane = u32::from_ne_bytes(*chunk).to_le();
303
624
304
624
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_3));
305
624
            acc = acc.rotate_left(17).wrapping_mul(PRIME32_4);
306
624
307
624
            remaining = rest;
308
624
        }
309
310
5.57k
        for &byte in remaining {
311
3.36k
            let lane = byte.into_u32();
312
3.36k
313
3.36k
            acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_5));
314
3.36k
            acc = acc.rotate_left(11).wrapping_mul(PRIME32_1);
315
3.36k
        }
316
317
        // Step 6. Final mix (avalanche)
318
2.21k
        acc ^= acc >> 15;
319
2.21k
        acc = acc.wrapping_mul(PRIME32_2);
320
2.21k
        acc ^= acc >> 13;
321
2.21k
        acc = acc.wrapping_mul(PRIME32_3);
322
2.21k
        acc ^= acc >> 16;
323
2.21k
324
2.21k
        acc
325
2.21k
    }
326
}
327
328
impl hash::Hasher for Hasher {
329
    // RATIONALE: See RATIONALE[inline]
330
    #[inline]
331
452M
    fn write(&mut self, data: &[u8]) {
332
452M
        let len = data.len();
333
452M
334
452M
        // Step 2. Process stripes
335
452M
        let (buffered_lanes, data) = self.buffer.extend(data);
336
337
452M
        if let Some(&lanes) = buffered_lanes {
338
121M
            self.accumulators.write(lanes);
339
330M
        }
340
341
452M
        let data = self.accumulators.write_many(data);
342
452M
343
452M
        self.buffer.set(data);
344
452M
345
452M
        self.length += len.into_u64();
346
452M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Hasher as core::hash::Hasher>::write
<twox_hash::xxhash32::Hasher as core::hash::Hasher>::write
Line
Count
Source
331
452M
    fn write(&mut self, data: &[u8]) {
332
452M
        let len = data.len();
333
452M
334
452M
        // Step 2. Process stripes
335
452M
        let (buffered_lanes, data) = self.buffer.extend(data);
336
337
452M
        if let Some(&lanes) = buffered_lanes {
338
121M
            self.accumulators.write(lanes);
339
330M
        }
340
341
452M
        let data = self.accumulators.write_many(data);
342
452M
343
452M
        self.buffer.set(data);
344
452M
345
452M
        self.length += len.into_u64();
346
452M
    }
<twox_hash::xxhash32::Hasher as core::hash::Hasher>::write
Line
Count
Source
331
60.5k
    fn write(&mut self, data: &[u8]) {
332
60.5k
        let len = data.len();
333
60.5k
334
60.5k
        // Step 2. Process stripes
335
60.5k
        let (buffered_lanes, data) = self.buffer.extend(data);
336
337
60.5k
        if let Some(&lanes) = buffered_lanes {
338
0
            self.accumulators.write(lanes);
339
60.5k
        }
340
341
60.5k
        let data = self.accumulators.write_many(data);
342
60.5k
343
60.5k
        self.buffer.set(data);
344
60.5k
345
60.5k
        self.length += len.into_u64();
346
60.5k
    }
<twox_hash::xxhash32::Hasher as core::hash::Hasher>::write
Line
Count
Source
331
27.3k
    fn write(&mut self, data: &[u8]) {
332
27.3k
        let len = data.len();
333
27.3k
334
27.3k
        // Step 2. Process stripes
335
27.3k
        let (buffered_lanes, data) = self.buffer.extend(data);
336
337
27.3k
        if let Some(&lanes) = buffered_lanes {
338
5.33k
            self.accumulators.write(lanes);
339
22.0k
        }
340
341
27.3k
        let data = self.accumulators.write_many(data);
342
27.3k
343
27.3k
        self.buffer.set(data);
344
27.3k
345
27.3k
        self.length += len.into_u64();
346
27.3k
    }
347
348
    // RATIONALE: See RATIONALE[inline]
349
    #[inline]
350
150M
    fn finish(&self) -> u64 {
351
150M
        Hasher::finish_32(self).into()
352
150M
    }
Unexecuted instantiation: <twox_hash::xxhash32::Hasher as core::hash::Hasher>::finish
<twox_hash::xxhash32::Hasher as core::hash::Hasher>::finish
Line
Count
Source
350
150M
    fn finish(&self) -> u64 {
351
150M
        Hasher::finish_32(self).into()
352
150M
    }
<twox_hash::xxhash32::Hasher as core::hash::Hasher>::finish
Line
Count
Source
350
60.5k
    fn finish(&self) -> u64 {
351
60.5k
        Hasher::finish_32(self).into()
352
60.5k
    }
<twox_hash::xxhash32::Hasher as core::hash::Hasher>::finish
Line
Count
Source
350
2.21k
    fn finish(&self) -> u64 {
351
2.21k
        Hasher::finish_32(self).into()
352
2.21k
    }
353
}
354
355
// RATIONALE: See RATIONALE[inline]
356
#[inline]
357
4.38G
const fn round(mut acc: u32, lane: u32) -> u32 {
358
4.38G
    acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_2));
359
4.38G
    acc = acc.rotate_left(13);
360
4.38G
    acc.wrapping_mul(PRIME32_1)
361
4.38G
}
Unexecuted instantiation: twox_hash::xxhash32::round
twox_hash::xxhash32::round
Line
Count
Source
357
4.36G
const fn round(mut acc: u32, lane: u32) -> u32 {
358
4.36G
    acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_2));
359
4.36G
    acc = acc.rotate_left(13);
360
4.36G
    acc.wrapping_mul(PRIME32_1)
361
4.36G
}
Unexecuted instantiation: twox_hash::xxhash32::round
twox_hash::xxhash32::round
Line
Count
Source
357
18.5M
const fn round(mut acc: u32, lane: u32) -> u32 {
358
18.5M
    acc = acc.wrapping_add(lane.wrapping_mul(PRIME32_2));
359
18.5M
    acc = acc.rotate_left(13);
360
18.5M
    acc.wrapping_mul(PRIME32_1)
361
18.5M
}
362
363
/// Constructs [`Hasher`][] for multiple hasher instances. See
364
/// the [usage warning][Hasher#caution].
365
#[derive(Clone)]
366
pub struct State(u32);
367
368
impl State {
369
    /// Constructs the hasher with an initial seed.
370
0
    pub fn with_seed(seed: u32) -> Self {
371
0
        Self(seed)
372
0
    }
373
}
374
375
impl BuildHasher for State {
376
    type Hasher = Hasher;
377
378
0
    fn build_hasher(&self) -> Self::Hasher {
379
0
        Hasher::with_seed(self.0)
380
0
    }
381
}
382
383
#[cfg(test)]
384
mod test {
385
    use core::{
386
        array,
387
        hash::{BuildHasherDefault, Hasher as _},
388
    };
389
    use std::collections::HashMap;
390
391
    use super::*;
392
393
    const _TRAITS: () = {
394
        const fn is_clone<T: Clone>() {}
395
        is_clone::<Hasher>();
396
        is_clone::<State>();
397
    };
398
399
    const EMPTY_BYTES: [u8; 0] = [];
400
401
    #[test]
402
    fn ingesting_byte_by_byte_is_equivalent_to_large_chunks() {
403
        let bytes = [0; 32];
404
405
        let mut byte_by_byte = Hasher::with_seed(0);
406
        for byte in bytes.chunks(1) {
407
            byte_by_byte.write(byte);
408
        }
409
        let byte_by_byte = byte_by_byte.finish();
410
411
        let mut one_chunk = Hasher::with_seed(0);
412
        one_chunk.write(&bytes);
413
        let one_chunk = one_chunk.finish();
414
415
        assert_eq!(byte_by_byte, one_chunk);
416
    }
417
418
    #[test]
419
    fn hash_of_nothing_matches_c_implementation() {
420
        let mut hasher = Hasher::with_seed(0);
421
        hasher.write(&EMPTY_BYTES);
422
        assert_eq!(hasher.finish(), 0x02cc_5d05);
423
    }
424
425
    #[test]
426
    fn hash_of_single_byte_matches_c_implementation() {
427
        let mut hasher = Hasher::with_seed(0);
428
        hasher.write(&[42]);
429
        assert_eq!(hasher.finish(), 0xe0fe_705f);
430
    }
431
432
    #[test]
433
    fn hash_of_multiple_bytes_matches_c_implementation() {
434
        let mut hasher = Hasher::with_seed(0);
435
        hasher.write(b"Hello, world!\0");
436
        assert_eq!(hasher.finish(), 0x9e5e_7e93);
437
    }
438
439
    #[test]
440
    fn hash_of_multiple_chunks_matches_c_implementation() {
441
        let bytes: [u8; 100] = array::from_fn(|i| i as u8);
442
        let mut hasher = Hasher::with_seed(0);
443
        hasher.write(&bytes);
444
        assert_eq!(hasher.finish(), 0x7f89_ba44);
445
    }
446
447
    #[test]
448
    fn hash_with_different_seed_matches_c_implementation() {
449
        let mut hasher = Hasher::with_seed(0x42c9_1977);
450
        hasher.write(&EMPTY_BYTES);
451
        assert_eq!(hasher.finish(), 0xd6bf_8459);
452
    }
453
454
    #[test]
455
    fn hash_with_different_seed_and_multiple_chunks_matches_c_implementation() {
456
        let bytes: [u8; 100] = array::from_fn(|i| i as u8);
457
        let mut hasher = Hasher::with_seed(0x42c9_1977);
458
        hasher.write(&bytes);
459
        assert_eq!(hasher.finish(), 0x6d2f_6c17);
460
    }
461
462
    #[test]
463
    fn hashes_with_different_offsets_are_the_same() {
464
        let bytes = [0x7c; 4096];
465
        let expected = Hasher::oneshot(0, &[0x7c; 64]);
466
467
        let the_same = bytes
468
            .windows(64)
469
            .map(|w| {
470
                let mut hasher = Hasher::with_seed(0);
471
                hasher.write(w);
472
                hasher.finish_32()
473
            })
474
            .all(|h| h == expected);
475
        assert!(the_same);
476
    }
477
478
    // This test validates wraparound/truncation behavior for very
479
    // large inputs of a 32-bit hash, but runs very slowly in the
480
    // normal "cargo test" build config since it hashes 4.3GB of
481
    // data. It runs reasonably quick under "cargo test --release".
482
    #[ignore]
483
    #[test]
484
    fn length_overflows_32bit() {
485
        // Hash 4.3 billion (4_300_000_000) bytes, which overflows a u32.
486
        let bytes200: [u8; 200] = array::from_fn(|i| i as _);
487
488
        let mut hasher = Hasher::with_seed(0);
489
        for _ in 0..(4_300_000_000 / bytes200.len()) {
490
            hasher.write(&bytes200);
491
        }
492
493
        assert_eq!(hasher.total_len(), 0x0000_0001_004c_cb00);
494
        assert_eq!(hasher.total_len_32(), 0x004c_cb00);
495
496
        // compared against the C implementation
497
        assert_eq!(hasher.finish(), 0x1522_4ca7);
498
    }
499
500
    #[test]
501
    fn can_be_used_in_a_hashmap_with_a_default_seed() {
502
        let mut hash: HashMap<_, _, BuildHasherDefault<Hasher>> = Default::default();
503
        hash.insert(42, "the answer");
504
        assert_eq!(hash.get(&42), Some(&"the answer"));
505
    }
506
}
507
508
#[cfg(feature = "random")]
509
#[cfg_attr(docsrs, doc(cfg(feature = "random")))]
510
mod random_impl {
511
    use super::*;
512
513
    /// Constructs a randomized seed and reuses it for multiple hasher
514
    /// instances. See the [usage warning][Hasher#caution].
515
    #[derive(Clone)]
516
    pub struct RandomState(State);
517
518
    impl Default for RandomState {
519
        fn default() -> Self {
520
            Self::new()
521
        }
522
    }
523
524
    impl RandomState {
525
        fn new() -> Self {
526
            Self(State::with_seed(rand::random()))
527
        }
528
    }
529
530
    impl BuildHasher for RandomState {
531
        type Hasher = Hasher;
532
533
        fn build_hasher(&self) -> Self::Hasher {
534
            self.0.build_hasher()
535
        }
536
    }
537
538
    #[cfg(test)]
539
    mod test {
540
        use std::collections::HashMap;
541
542
        use super::*;
543
544
        const _: () = {
545
            const fn is_clone<T: Clone>() {}
546
            is_clone::<Hasher>();
547
            is_clone::<RandomState>();
548
        };
549
550
        #[test]
551
        fn can_be_used_in_a_hashmap_with_a_random_seed() {
552
            let mut hash: HashMap<_, _, RandomState> = Default::default();
553
            hash.insert(42, "the answer");
554
            assert_eq!(hash.get(&42), Some(&"the answer"));
555
        }
556
    }
557
}
558
559
#[cfg(feature = "random")]
560
#[cfg_attr(docsrs, doc(cfg(feature = "random")))]
561
pub use random_impl::*;
562
563
#[cfg(feature = "serialize")]
564
#[cfg_attr(docsrs, doc(cfg(feature = "serialize")))]
565
mod serialize_impl {
566
    use serde::{Deserialize, Serialize};
567
568
    use super::*;
569
570
    impl<'de> Deserialize<'de> for Hasher {
571
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
572
        where
573
            D: serde::Deserializer<'de>,
574
        {
575
            let shim = Deserialize::deserialize(deserializer)?;
576
577
            let Shim {
578
                total_len,
579
                seed,
580
                core,
581
                buffer,
582
                buffer_usage,
583
            } = shim;
584
            let Core { v1, v2, v3, v4 } = core;
585
586
            let mut buffer_data = BufferData::new();
587
            buffer_data.bytes_mut().copy_from_slice(&buffer);
588
589
            Ok(Hasher {
590
                seed,
591
                accumulators: Accumulators([v1, v2, v3, v4]),
592
                buffer: Buffer {
593
                    offset: buffer_usage,
594
                    data: buffer_data,
595
                },
596
                length: total_len,
597
            })
598
        }
599
    }
600
601
    impl Serialize for Hasher {
602
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
603
        where
604
            S: serde::Serializer,
605
        {
606
            let Hasher {
607
                seed,
608
                ref accumulators,
609
                ref buffer,
610
                length,
611
            } = *self;
612
            let [v1, v2, v3, v4] = accumulators.0;
613
            let Buffer { offset, ref data } = *buffer;
614
            let buffer = *data.bytes();
615
616
            let shim = Shim {
617
                total_len: length,
618
                seed,
619
                core: Core { v1, v2, v3, v4 },
620
                buffer,
621
                buffer_usage: offset,
622
            };
623
624
            shim.serialize(serializer)
625
        }
626
    }
627
628
    #[derive(Serialize, Deserialize)]
629
    struct Shim {
630
        total_len: u64,
631
        seed: u32,
632
        core: Core,
633
        buffer: [u8; 16],
634
        buffer_usage: usize,
635
    }
636
637
    #[derive(Serialize, Deserialize)]
638
    struct Core {
639
        v1: u32,
640
        v2: u32,
641
        v3: u32,
642
        v4: u32,
643
    }
644
645
    #[cfg(test)]
646
    mod test {
647
        use std::hash::Hasher as _;
648
649
        use super::*;
650
651
        type Result<T = (), E = serde_json::Error> = core::result::Result<T, E>;
652
653
        #[test]
654
        fn test_serialization_cycle() -> Result {
655
            let mut hasher = Hasher::with_seed(0);
656
            hasher.write(b"Hello, world!\0");
657
            let _ = hasher.finish();
658
659
            let serialized = serde_json::to_string(&hasher)?;
660
            let unserialized: Hasher = serde_json::from_str(&serialized)?;
661
            assert_eq!(hasher, unserialized);
662
            Ok(())
663
        }
664
665
        #[test]
666
        fn test_serialization_stability() -> Result {
667
            let mut hasher = Hasher::with_seed(0);
668
            hasher.write(b"Hello, world!\0");
669
            let _ = hasher.finish();
670
671
            let expected_serialized = r#"{
672
                "total_len": 14,
673
                "seed": 0,
674
                "core": {
675
                  "v1": 606290984,
676
                  "v2": 2246822519,
677
                  "v3": 0,
678
                  "v4": 1640531535
679
                },
680
                "buffer": [
681
                  72,  101, 108, 108, 111, 44, 32, 119,
682
                  111, 114, 108, 100, 33,  0,  0,  0
683
                ],
684
                "buffer_usage": 14
685
            }"#;
686
687
            let unserialized: Hasher = serde_json::from_str(expected_serialized)?;
688
            assert_eq!(hasher, unserialized);
689
690
            let expected_value: serde_json::Value = serde_json::from_str(expected_serialized)?;
691
            let actual_value = serde_json::to_value(&hasher)?;
692
            assert_eq!(expected_value, actual_value);
693
694
            Ok(())
695
        }
696
    }
697
}