Coverage Report

Created: 2024-07-06 06:44

/rust/registry/src/index.crates.io-6f17d22bba15001f/fxhash-0.2.1/lib.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2
// file at the top-level directory of this distribution and at
3
// http://rust-lang.org/COPYRIGHT.
4
//
5
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8
// option. This file may not be copied, modified, or distributed
9
// except according to those terms.
10
11
#![deny(missing_docs)]
12
13
//! # Fx Hash
14
//!
15
//! This hashing algorithm was extracted from the Rustc compiler.  This is the same hashing
16
//! algoirthm used for some internal operations in FireFox.  The strength of this algorithm
17
//! is in hashing 8 bytes at a time on 64-bit platforms, where the FNV algorithm works on one
18
//! byte at a time.
19
//!
20
//! ## Disclaimer
21
//!
22
//! It is **not a cryptographically secure** hash, so it is strongly recommended that you do
23
//! not use this hash for cryptographic purproses.  Furthermore, this hashing algorithm was
24
//! not designed to prevent any attacks for determining collisions which could be used to
25
//! potentially cause quadratic behavior in `HashMap`s.  So it is not recommended to expose
26
//! this hash in places where collissions or DDOS attacks may be a concern.
27
28
use std::collections::{HashMap, HashSet};
29
use std::default::Default;
30
use std::hash::{Hasher, Hash, BuildHasherDefault};
31
use std::ops::BitXor;
32
33
extern crate byteorder;
34
use byteorder::{ByteOrder, NativeEndian};
35
36
/// A builder for default Fx hashers.
37
pub type FxBuildHasher = BuildHasherDefault<FxHasher>;
38
39
/// A `HashMap` using a default Fx hasher.
40
pub type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>;
41
42
/// A `HashSet` using a default Fx hasher.
43
pub type FxHashSet<V> = HashSet<V, FxBuildHasher>;
44
45
const ROTATE: u32 = 5;
46
const SEED64: u64 = 0x517cc1b727220a95;
47
const SEED32: u32 = (SEED64 & 0xFFFF_FFFF) as u32;
48
49
#[cfg(target_pointer_width = "32")]
50
const SEED: usize = SEED32 as usize;
51
#[cfg(target_pointer_width = "64")]
52
const SEED: usize = SEED64 as usize;
53
54
trait HashWord {
55
    fn hash_word(&mut self, Self);
56
}
57
58
macro_rules! impl_hash_word {
59
    ($($ty:ty = $key:ident),* $(,)*) => (
60
        $(
61
            impl HashWord for $ty {
62
                #[inline]
63
16.0k
                fn hash_word(&mut self, word: Self) {
64
16.0k
                    *self = self.rotate_left(ROTATE).bitxor(word).wrapping_mul($key);
65
16.0k
                }
<u64 as fxhash::HashWord>::hash_word
Line
Count
Source
63
1.93k
                fn hash_word(&mut self, word: Self) {
64
1.93k
                    *self = self.rotate_left(ROTATE).bitxor(word).wrapping_mul($key);
65
1.93k
                }
<u64 as fxhash::HashWord>::hash_word
Line
Count
Source
63
14.0k
                fn hash_word(&mut self, word: Self) {
64
14.0k
                    *self = self.rotate_left(ROTATE).bitxor(word).wrapping_mul($key);
65
14.0k
                }
Unexecuted instantiation: <u64 as fxhash::HashWord>::hash_word
Unexecuted instantiation: <usize as fxhash::HashWord>::hash_word
Unexecuted instantiation: <u32 as fxhash::HashWord>::hash_word
66
            }
67
        )*
68
    )
69
}
70
71
impl_hash_word!(usize = SEED, u32 = SEED32, u64 = SEED64);
72
73
#[inline]
74
0
fn write32(mut hash: u32, mut bytes: &[u8]) -> u32 {
75
0
    while bytes.len() >= 4 {
76
0
        let n = NativeEndian::read_u32(bytes);
77
0
        hash.hash_word(n);
78
0
        bytes = bytes.split_at(4).1;
79
0
    }
80
81
0
    for byte in bytes {
82
0
        hash.hash_word(*byte as u32);
83
0
    }
84
0
    hash
85
0
}
86
87
#[inline]
88
2.38k
fn write64(mut hash: u64, mut bytes: &[u8]) -> u64 {
89
8.06k
    while bytes.len() >= 8 {
90
5.67k
        let n = NativeEndian::read_u64(bytes);
91
5.67k
        hash.hash_word(n);
92
5.67k
        bytes = bytes.split_at(8).1;
93
5.67k
    }
94
95
2.38k
    if bytes.len() >= 4 {
96
1.00k
        let n = NativeEndian::read_u32(bytes);
97
1.00k
        hash.hash_word(n as u64);
98
1.00k
        bytes = bytes.split_at(4).1;
99
1.38k
    }
100
101
7.41k
    for byte in bytes {
102
5.03k
        hash.hash_word(*byte as u64);
103
5.03k
    }
104
2.38k
    hash
105
2.38k
}
fxhash::write64
Line
Count
Source
88
2.38k
fn write64(mut hash: u64, mut bytes: &[u8]) -> u64 {
89
8.06k
    while bytes.len() >= 8 {
90
5.67k
        let n = NativeEndian::read_u64(bytes);
91
5.67k
        hash.hash_word(n);
92
5.67k
        bytes = bytes.split_at(8).1;
93
5.67k
    }
94
95
2.38k
    if bytes.len() >= 4 {
96
1.00k
        let n = NativeEndian::read_u32(bytes);
97
1.00k
        hash.hash_word(n as u64);
98
1.00k
        bytes = bytes.split_at(4).1;
99
1.38k
    }
100
101
7.41k
    for byte in bytes {
102
5.03k
        hash.hash_word(*byte as u64);
103
5.03k
    }
104
2.38k
    hash
105
2.38k
}
Unexecuted instantiation: fxhash::write64
106
107
#[inline]
108
#[cfg(target_pointer_width = "32")]
109
fn write(hash: usize, bytes: &[u8]) -> usize {
110
    write32(hash as u32, bytes) as usize
111
}
112
113
#[inline]
114
#[cfg(target_pointer_width = "64")]
115
0
fn write(hash: usize, bytes: &[u8]) -> usize {
116
0
    write64(hash as u64, bytes) as usize
117
0
}
118
119
/// This hashing algorithm was extracted from the Rustc compiler.
120
/// This is the same hashing algoirthm used for some internal operations in FireFox.
121
/// The strength of this algorithm is in hashing 8 bytes at a time on 64-bit platforms,
122
/// where the FNV algorithm works on one byte at a time.
123
///
124
/// This hashing algorithm should not be used for cryptographic, or in scenarios where
125
/// DOS attacks are a concern.
126
#[derive(Debug, Clone)]
127
pub struct FxHasher {
128
    hash: usize,
129
}
130
131
impl Default for FxHasher {
132
    #[inline]
133
0
    fn default() -> FxHasher {
134
0
        FxHasher { hash: 0 }
135
0
    }
136
}
137
138
impl Hasher for FxHasher {
139
    #[inline]
140
0
    fn write(&mut self, bytes: &[u8]) {
141
0
        self.hash = write(self.hash, bytes);
142
0
    }
143
144
    #[inline]
145
0
    fn write_u8(&mut self, i: u8) {
146
0
        self.hash.hash_word(i as usize);
147
0
    }
148
149
    #[inline]
150
0
    fn write_u16(&mut self, i: u16) {
151
0
        self.hash.hash_word(i as usize);
152
0
    }
153
154
    #[inline]
155
0
    fn write_u32(&mut self, i: u32) {
156
0
        self.hash.hash_word(i as usize);
157
0
    }
158
159
    #[inline]
160
    #[cfg(target_pointer_width = "32")]
161
    fn write_u64(&mut self, i: u64) {
162
        self.hash.hash_word(i as usize);
163
        self.hash.hash_word((i >> 32) as usize);
164
    }
165
166
    #[inline]
167
    #[cfg(target_pointer_width = "64")]
168
0
    fn write_u64(&mut self, i: u64) {
169
0
        self.hash.hash_word(i as usize);
170
0
    }
171
172
    #[inline]
173
0
    fn write_usize(&mut self, i: usize) {
174
0
        self.hash.hash_word(i);
175
0
    }
176
177
    #[inline]
178
0
    fn finish(&self) -> u64 {
179
0
        self.hash as u64
180
0
    }
181
}
182
183
/// This hashing algorithm was extracted from the Rustc compiler.
184
/// This is the same hashing algoirthm used for some internal operations in FireFox.
185
/// The strength of this algorithm is in hashing 8 bytes at a time on any platform,
186
/// where the FNV algorithm works on one byte at a time.
187
///
188
/// This hashing algorithm should not be used for cryptographic, or in scenarios where
189
/// DOS attacks are a concern.
190
#[derive(Debug, Clone)]
191
pub struct FxHasher64 {
192
    hash: u64,
193
}
194
195
impl Default for FxHasher64 {
196
    #[inline]
197
4.32k
    fn default() -> FxHasher64 {
198
4.32k
        FxHasher64 { hash: 0 }
199
4.32k
    }
<fxhash::FxHasher64 as core::default::Default>::default
Line
Count
Source
197
1.95k
    fn default() -> FxHasher64 {
198
1.95k
        FxHasher64 { hash: 0 }
199
1.95k
    }
<fxhash::FxHasher64 as core::default::Default>::default
Line
Count
Source
197
2.36k
    fn default() -> FxHasher64 {
198
2.36k
        FxHasher64 { hash: 0 }
199
2.36k
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::default::Default>::default
200
}
201
202
impl Hasher for FxHasher64 {
203
    #[inline]
204
2.38k
    fn write(&mut self, bytes: &[u8]) {
205
2.38k
        self.hash = write64(self.hash, bytes);
206
2.38k
    }
<fxhash::FxHasher64 as core::hash::Hasher>::write
Line
Count
Source
204
2.38k
    fn write(&mut self, bytes: &[u8]) {
205
2.38k
        self.hash = write64(self.hash, bytes);
206
2.38k
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::hash::Hasher>::write
207
208
    #[inline]
209
2.38k
    fn write_u8(&mut self, i: u8) {
210
2.38k
        self.hash.hash_word(i as u64);
211
2.38k
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::hash::Hasher>::write_u8
<fxhash::FxHasher64 as core::hash::Hasher>::write_u8
Line
Count
Source
209
2.38k
    fn write_u8(&mut self, i: u8) {
210
2.38k
        self.hash.hash_word(i as u64);
211
2.38k
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::hash::Hasher>::write_u8
212
213
    #[inline]
214
0
    fn write_u16(&mut self, i: u16) {
215
0
        self.hash.hash_word(i as u64);
216
0
    }
217
218
    #[inline]
219
1.86k
    fn write_u32(&mut self, i: u32) {
220
1.86k
        self.hash.hash_word(i as u64);
221
1.86k
    }
<fxhash::FxHasher64 as core::hash::Hasher>::write_u32
Line
Count
Source
219
1.86k
    fn write_u32(&mut self, i: u32) {
220
1.86k
        self.hash.hash_word(i as u64);
221
1.86k
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::hash::Hasher>::write_u32
222
223
0
    fn write_u64(&mut self, i: u64) {
224
0
        self.hash.hash_word(i);
225
0
    }
226
227
    #[inline]
228
69
    fn write_usize(&mut self, i: usize) {
229
69
        self.hash.hash_word(i as u64);
230
69
    }
<fxhash::FxHasher64 as core::hash::Hasher>::write_usize
Line
Count
Source
228
69
    fn write_usize(&mut self, i: usize) {
229
69
        self.hash.hash_word(i as u64);
230
69
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::hash::Hasher>::write_usize
231
232
    #[inline]
233
4.32k
    fn finish(&self) -> u64 {
234
4.32k
        self.hash
235
4.32k
    }
<fxhash::FxHasher64 as core::hash::Hasher>::finish
Line
Count
Source
233
1.95k
    fn finish(&self) -> u64 {
234
1.95k
        self.hash
235
1.95k
    }
<fxhash::FxHasher64 as core::hash::Hasher>::finish
Line
Count
Source
233
2.36k
    fn finish(&self) -> u64 {
234
2.36k
        self.hash
235
2.36k
    }
Unexecuted instantiation: <fxhash::FxHasher64 as core::hash::Hasher>::finish
236
}
237
238
/// This hashing algorithm was extracted from the Rustc compiler.
239
/// This is the same hashing algoirthm used for some internal operations in FireFox.
240
/// The strength of this algorithm is in hashing 4 bytes at a time on any platform,
241
/// where the FNV algorithm works on one byte at a time.
242
///
243
/// This hashing algorithm should not be used for cryptographic, or in scenarios where
244
/// DOS attacks are a concern.
245
#[derive(Debug, Clone)]
246
pub struct FxHasher32 {
247
    hash: u32,
248
}
249
250
impl Default for FxHasher32 {
251
    #[inline]
252
0
    fn default() -> FxHasher32 {
253
0
        FxHasher32 { hash: 0 }
254
0
    }
255
}
256
257
impl Hasher for FxHasher32 {
258
    #[inline]
259
0
    fn write(&mut self, bytes: &[u8]) {
260
0
        self.hash = write32(self.hash, bytes);
261
0
    }
262
263
    #[inline]
264
0
    fn write_u8(&mut self, i: u8) {
265
0
        self.hash.hash_word(i as u32);
266
0
    }
267
268
    #[inline]
269
0
    fn write_u16(&mut self, i: u16) {
270
0
        self.hash.hash_word(i as u32);
271
0
    }
272
273
    #[inline]
274
0
    fn write_u32(&mut self, i: u32) {
275
0
        self.hash.hash_word(i);
276
0
    }
277
278
    #[inline]
279
0
    fn write_u64(&mut self, i: u64) {
280
0
        self.hash.hash_word(i as u32);
281
0
        self.hash.hash_word((i >> 32) as u32);
282
0
    }
283
284
    #[inline]
285
    #[cfg(target_pointer_width = "32")]
286
    fn write_usize(&mut self, i: usize) {
287
        self.write_u32(i as u32);
288
    }
289
290
    #[inline]
291
    #[cfg(target_pointer_width = "64")]
292
0
    fn write_usize(&mut self, i: usize) {
293
0
        self.write_u64(i as u64);
294
0
    }
295
296
    #[inline]
297
0
    fn finish(&self) -> u64 {
298
0
        self.hash as u64
299
0
    }
300
}
301
302
/// A convenience function for when you need a quick 64-bit hash.
303
#[inline]
304
0
pub fn hash64<T: Hash + ?Sized>(v: &T) -> u64 {
305
0
    let mut state = FxHasher64::default();
306
0
    v.hash(&mut state);
307
0
    state.finish()
308
0
}
309
310
/// A convenience function for when you need a quick 32-bit hash.
311
#[inline]
312
0
pub fn hash32<T: Hash + ?Sized>(v: &T) -> u32 {
313
0
    let mut state = FxHasher32::default();
314
0
    v.hash(&mut state);
315
0
    state.finish() as u32
316
0
}
317
318
/// A convenience function for when you need a quick usize hash.
319
#[inline]
320
0
pub fn hash<T: Hash + ?Sized>(v: &T) -> usize {
321
0
    let mut state = FxHasher::default();
322
0
    v.hash(&mut state);
323
0
    state.finish() as usize
324
0
}