1use std::collections::hash_map::DefaultHasher;
2use std::hash::Hasher;
3
4#[derive(Copy, Clone, Debug)]
20pub struct JumpHasher<H = DefaultHasher> {
21 slots: u32,
22 hasher: H,
23}
24
25impl<H: Hasher> JumpHasher<H> {
26 pub fn new_with_hasher(slots: u32, hasher: H) -> Self {
33 Self { slots, hasher }
34 }
35}
36
37impl<H: Hasher + Default> JumpHasher<H> {
38 pub fn new(slots: u32) -> Self {
45 Self {
46 slots,
47 hasher: H::default(),
48 }
49 }
50}
51
52impl<H: Hasher> Hasher for JumpHasher<H> {
53 fn finish(&self) -> u64 {
54 hash(self.hasher.finish(), self.slots as i64) as u64
55 }
56
57 fn write(&mut self, bytes: &[u8]) {
58 self.hasher.write(bytes)
59 }
60}
61
62pub fn hash(mut key: u64, slots: i64) -> u32 {
70 let (mut b, mut j) = (-1i64, 0i64);
71 while j < slots {
72 b = j;
73 key = key.wrapping_mul(2862933555777941757).wrapping_add(1);
74 j = ((b.wrapping_add(1) as f64) * (((1u64 << 31) as f64) / (((key >> 33) + 1) as f64)))
75 as i64;
76 }
77 b as u32
78}
79
80#[cfg(test)]
81mod tests {
82 use crate::JumpHasher;
83 use std::collections::hash_map::DefaultHasher;
84 use std::hash::{Hash, Hasher};
85
86 #[test]
87 fn test_struct() {
88 #[derive(Hash)]
89 struct Test(i32, String);
90
91 let test = Test(123456, "test".to_string());
92 check_range(&test);
93 }
94
95 #[test]
96 fn test_str() {
97 let test = "test 1";
98 check_range(&test);
99 }
100
101 #[test]
102 fn test_int() {
103 let test = 123456;
104 check_range(&test);
105 }
106
107 fn check_range<H: Hash>(test: &H) {
108 for slots in 0..1000 {
109 check_algorithm(slots, test);
110 }
111 }
112
113 fn check_algorithm<H: Hash>(slots: u32, test: H) {
114 let mut hasher: JumpHasher<DefaultHasher> = JumpHasher::new(slots);
115 test.hash(&mut hasher);
116 let hash = hasher.finish();
117
118 for i in (hash.wrapping_add(1) as u32)..slots.max(1) {
119 let mut hasher = JumpHasher::<DefaultHasher>::new(i);
120
121 test.hash(&mut hasher);
122
123 assert_eq!(hasher.finish(), hash)
124 }
125 }
126}