1 #![doc(html_root_url="https://docs.rs/phf_shared/0.7")]
2 #![cfg_attr(feature = "core", no_std)]
3 
4 #[cfg(not(feature = "core"))]
5 extern crate std as core;
6 
7 extern crate siphasher;
8 
9 #[cfg(feature = "unicase")]
10 extern crate unicase;
11 
12 use core::hash::{Hasher, Hash};
13 use siphasher::sip::SipHasher13;
14 
15 #[inline]
displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u3216 pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
17     d2 + f1 * d1 + f2
18 }
19 
20 #[inline]
split(hash: u64) -> (u32, u32, u32)21 pub fn split(hash: u64) -> (u32, u32, u32) {
22     const BITS: u32 = 21;
23     const MASK: u64 = (1 << BITS) - 1;
24 
25     ((hash & MASK) as u32,
26      ((hash >> BITS) & MASK) as u32,
27      ((hash >> (2 * BITS)) & MASK) as u32)
28 }
29 
30 /// `key` is from `phf_generator::HashState::key`.
31 #[inline]
hash<T: ?Sized + PhfHash>(x: &T, key: u64) -> u6432 pub fn hash<T: ?Sized + PhfHash>(x: &T, key: u64) -> u64 {
33     let mut hasher = SipHasher13::new_with_keys(0, key);
34     x.phf_hash(&mut hasher);
35     hasher.finish()
36 }
37 
38 /// Return an index into `phf_generator::HashState::map`.
39 ///
40 /// * `hash` is from `hash()` in this crate.
41 /// * `disps` is from `phf_generator::HashState::disps`.
42 /// * `len` is the length of `phf_generator::HashState::map`.
43 #[inline]
get_index(hash: u64, disps: &[(u32, u32)], len: usize) -> u3244 pub fn get_index(hash: u64, disps: &[(u32, u32)], len: usize) -> u32 {
45     let (g, f1, f2) = split(hash);
46     let (d1, d2) = disps[(g % (disps.len() as u32)) as usize];
47     displace(f1, f2, d1, d2) % (len as u32)
48 }
49 
50 /// A trait implemented by types which can be used in PHF data structures.
51 ///
52 /// This differs from the standard library's `Hash` trait in that `PhfHash`'s
53 /// results must be architecture independent so that hashes will be consistent
54 /// between the host and target when cross compiling.
55 pub trait PhfHash {
56     /// Feeds the value into the state given, updating the hasher as necessary.
phf_hash<H: Hasher>(&self, state: &mut H)57     fn phf_hash<H: Hasher>(&self, state: &mut H);
58 
59     /// Feeds a slice of this type into the state provided.
phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized60     fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H)
61         where Self: Sized
62     {
63         for piece in data {
64             piece.phf_hash(state);
65         }
66     }
67 }
68 
69 #[cfg(not(feature = "core"))]
70 impl PhfHash for String {
71     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)72     fn phf_hash<H: Hasher>(&self, state: &mut H) {
73         (**self).phf_hash(state)
74     }
75 }
76 
77 #[cfg(not(feature = "core"))]
78 impl PhfHash for Vec<u8> {
79     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)80     fn phf_hash<H: Hasher>(&self, state: &mut H) {
81         (**self).phf_hash(state)
82     }
83 }
84 
85 impl<'a> PhfHash for &'a str {
86     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)87     fn phf_hash<H: Hasher>(&self, state: &mut H) {
88         (*self).phf_hash(state)
89     }
90 }
91 
92 impl<'a> PhfHash for &'a [u8] {
93     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)94     fn phf_hash<H: Hasher>(&self, state: &mut H) {
95         (*self).phf_hash(state)
96     }
97 }
98 
99 impl PhfHash for str {
100     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)101     fn phf_hash<H: Hasher>(&self, state: &mut H) {
102         self.as_bytes().phf_hash(state)
103     }
104 }
105 
106 impl PhfHash for [u8] {
107     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)108     fn phf_hash<H: Hasher>(&self, state: &mut H) {
109         state.write(self);
110     }
111 }
112 
113 #[cfg(feature = "unicase")]
114 impl<S> PhfHash for unicase::UniCase<S>
115 where unicase::UniCase<S>: Hash {
116     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)117     fn phf_hash<H: Hasher>(&self, state: &mut H) {
118         self.hash(state)
119     }
120 }
121 
122 macro_rules! sip_impl(
123     (le $t:ty) => (
124         impl PhfHash for $t {
125             #[inline]
126             fn phf_hash<H: Hasher>(&self, state: &mut H) {
127                 self.to_le().hash(state);
128             }
129         }
130     );
131     ($t:ty) => (
132         impl PhfHash for $t {
133             #[inline]
134             fn phf_hash<H: Hasher>(&self, state: &mut H) {
135                 self.hash(state);
136             }
137         }
138     )
139 );
140 
141 sip_impl!(u8);
142 sip_impl!(i8);
143 sip_impl!(le u16);
144 sip_impl!(le i16);
145 sip_impl!(le u32);
146 sip_impl!(le i32);
147 sip_impl!(le u64);
148 sip_impl!(le i64);
149 sip_impl!(bool);
150 
151 impl PhfHash for char {
152     #[inline]
phf_hash<H: Hasher>(&self, state: &mut H)153     fn phf_hash<H: Hasher>(&self, state: &mut H) {
154         (*self as u32).phf_hash(state)
155     }
156 }
157 
158 macro_rules! array_impl(
159     ($t:ty, $n:expr) => (
160         impl PhfHash for [$t; $n] {
161             #[inline]
162             fn phf_hash<H: Hasher>(&self, state: &mut H) {
163                 state.write(self);
164             }
165         }
166     )
167 );
168 
169 array_impl!(u8, 1);
170 array_impl!(u8, 2);
171 array_impl!(u8, 3);
172 array_impl!(u8, 4);
173 array_impl!(u8, 5);
174 array_impl!(u8, 6);
175 array_impl!(u8, 7);
176 array_impl!(u8, 8);
177 array_impl!(u8, 9);
178 array_impl!(u8, 10);
179 array_impl!(u8, 11);
180 array_impl!(u8, 12);
181 array_impl!(u8, 13);
182 array_impl!(u8, 14);
183 array_impl!(u8, 15);
184 array_impl!(u8, 16);
185 array_impl!(u8, 17);
186 array_impl!(u8, 18);
187 array_impl!(u8, 19);
188 array_impl!(u8, 20);
189 array_impl!(u8, 21);
190 array_impl!(u8, 22);
191 array_impl!(u8, 23);
192 array_impl!(u8, 24);
193 array_impl!(u8, 25);
194 array_impl!(u8, 26);
195 array_impl!(u8, 27);
196 array_impl!(u8, 28);
197 array_impl!(u8, 29);
198 array_impl!(u8, 30);
199 array_impl!(u8, 31);
200 array_impl!(u8, 32);
201