ustr_fxhash/
hash.rs

1use super::Ustr;
2use byteorder::{ByteOrder, NativeEndian};
3use std::{
4    collections::{HashMap, HashSet},
5    hash::{BuildHasherDefault, Hasher},
6};
7
8/// A standard `HashMap` using `Ustr` as the key type with a custom `Hasher`
9/// that just uses the precomputed hash for speed instead of calculating it.
10pub type UstrMap<V> = HashMap<Ustr, V, BuildHasherDefault<IdentityHasher>>;
11
12/// A standard `HashSet` using `Ustr` as the key type with a custom `Hasher`
13/// that just uses the precomputed hash for speed instead of calculating it.
14pub type UstrSet = HashSet<Ustr, BuildHasherDefault<IdentityHasher>>;
15
16/// The worst hasher in the world -- the identity hasher.
17#[doc(hidden)]
18#[derive(Default)]
19pub struct IdentityHasher {
20    hash: u64,
21}
22
23impl Hasher for IdentityHasher {
24    #[inline]
25    fn write(&mut self, bytes: &[u8]) {
26        if bytes.len() == 8 {
27            self.hash = NativeEndian::read_u64(bytes);
28        }
29    }
30
31    #[inline]
32    fn finish(&self) -> u64 {
33        self.hash
34    }
35}
36
37#[test]
38fn test_hashing() {
39    let _t = super::TEST_LOCK.lock();
40    use crate::ustr as u;
41
42    use std::hash::Hash;
43    let u1 = u("the quick brown fox");
44    let u2 = u("jumped over the lazy dog");
45
46    let mut hasher = IdentityHasher::default();
47    u1.hash(&mut hasher);
48    assert_eq!(hasher.finish(), u1.precomputed_hash());
49
50    let mut hasher = IdentityHasher::default();
51    u2.hash(&mut hasher);
52    assert_eq!(hasher.finish(), u2.precomputed_hash());
53
54    let mut hm = UstrMap::<u32>::default();
55    hm.insert(u1, 17);
56    hm.insert(u2, 42);
57
58    assert_eq!(hm.get(&u1), Some(&17));
59    assert_eq!(hm.get(&u2), Some(&42));
60}