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