Coverage Report

Created: 2025-11-16 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/phf_shared-0.10.0/src/lib.rs
Line
Count
Source
1
#![doc(html_root_url = "https://docs.rs/phf_shared/0.9")]
2
#![cfg_attr(not(feature = "std"), no_std)]
3
4
#[cfg(feature = "std")]
5
extern crate std as core;
6
7
use core::fmt;
8
use core::hash::{Hash, Hasher};
9
use core::num::Wrapping;
10
use siphasher::sip128::{Hash128, Hasher128, SipHasher13};
11
12
#[non_exhaustive]
13
pub struct Hashes {
14
    pub g: u32,
15
    pub f1: u32,
16
    pub f2: u32,
17
}
18
19
/// A central typedef for hash keys
20
///
21
/// Makes experimentation easier by only needing to be updated here.
22
pub type HashKey = u64;
23
24
#[inline]
25
0
pub fn displace(f1: u32, f2: u32, d1: u32, d2: u32) -> u32 {
26
0
    (Wrapping(d2) + Wrapping(f1) * Wrapping(d1) + Wrapping(f2)).0
27
0
}
28
29
/// `key` is from `phf_generator::HashState`.
30
#[inline]
31
0
pub fn hash<T: ?Sized + PhfHash>(x: &T, key: &HashKey) -> Hashes {
32
0
    let mut hasher = SipHasher13::new_with_keys(0, *key);
33
0
    x.phf_hash(&mut hasher);
34
35
    let Hash128 {
36
0
        h1: lower,
37
0
        h2: upper,
38
0
    } = hasher.finish128();
39
40
0
    Hashes {
41
0
        g: (lower >> 32) as u32,
42
0
        f1: lower as u32,
43
0
        f2: upper as u32,
44
0
    }
45
0
}
Unexecuted instantiation: phf_shared::hash::<u16>
Unexecuted instantiation: phf_shared::hash::<u16>
46
47
/// Return an index into `phf_generator::HashState::map`.
48
///
49
/// * `hash` is from `hash()` in this crate.
50
/// * `disps` is from `phf_generator::HashState::disps`.
51
/// * `len` is the length of `phf_generator::HashState::map`.
52
#[inline]
53
0
pub fn get_index(hashes: &Hashes, disps: &[(u32, u32)], len: usize) -> u32 {
54
0
    let (d1, d2) = disps[(hashes.g % (disps.len() as u32)) as usize];
55
0
    displace(hashes.f1, hashes.f2, d1, d2) % (len as u32)
56
0
}
57
58
/// A trait implemented by types which can be used in PHF data structures.
59
///
60
/// This differs from the standard library's `Hash` trait in that `PhfHash`'s
61
/// results must be architecture independent so that hashes will be consistent
62
/// between the host and target when cross compiling.
63
pub trait PhfHash {
64
    /// Feeds the value into the state given, updating the hasher as necessary.
65
    fn phf_hash<H: Hasher>(&self, state: &mut H);
66
67
    /// Feeds a slice of this type into the state provided.
68
    fn phf_hash_slice<H: Hasher>(data: &[Self], state: &mut H)
69
    where
70
        Self: Sized,
71
    {
72
        for piece in data {
73
            piece.phf_hash(state);
74
        }
75
    }
76
}
77
78
/// Trait for printing types with `const` constructors, used by `phf_codegen` and `phf_macros`.
79
pub trait FmtConst {
80
    /// Print a `const` expression representing this value.
81
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
82
}
83
84
/// Identical to `std::borrow::Borrow` except omitting blanket impls to facilitate other
85
/// borrowing patterns.
86
///
87
/// The same semantic requirements apply:
88
///
89
/// > In particular `Eq`, `Ord` and `Hash` must be equivalent for borrowed and owned values:
90
/// `x.borrow() == y.borrow()` should give the same result as `x == y`.
91
///
92
/// (This crate's API only requires `Eq` and `PhfHash`, however.)
93
///
94
/// ### Motivation
95
/// The conventional signature for lookup methods on collections looks something like this:
96
///
97
/// ```rust,ignore
98
/// impl<K, V> Map<K, V> where K: PhfHash + Eq {
99
///     fn get<T: ?Sized>(&self, key: &T) -> Option<&V> where T: PhfHash + Eq, K: Borrow<T> {
100
///         ...
101
///     }
102
/// }
103
/// ```
104
///
105
/// This allows the key type used for lookup to be different than the key stored in the map so for
106
/// example you can use `&str` to look up a value in a `Map<String, _>`. However, this runs into
107
/// a problem in the case where `T` and `K` are both a `Foo<_>` type constructor but
108
/// the contained type is different (even being the same type with different lifetimes).
109
///
110
/// The main issue for this crate's API is that, with this method signature, you cannot perform a
111
/// lookup on a `Map<UniCase<&'static str>, _>` with a `UniCase<&'a str>` where `'a` is not
112
/// `'static`; there is no impl of `Borrow` that resolves to
113
/// `impl Borrow<UniCase<'a>> for UniCase<&'static str>` and one cannot be added either because of
114
/// all the blanket impls.
115
///
116
/// Instead, this trait is implemented conservatively, without blanket impls, so that impls like
117
/// this may be added. This is feasible since the set of types that implement `PhfHash` is
118
/// intentionally small.
119
///
120
/// This likely won't be fixable with specialization alone but will require full support for lattice
121
/// impls since we technically want to add overlapping blanket impls.
122
pub trait PhfBorrow<B: ?Sized> {
123
    /// Convert a reference to `self` to a reference to the borrowed type.
124
    fn borrow(&self) -> &B;
125
}
126
127
/// Create an impl of `FmtConst` delegating to `fmt::Debug` for types that can deal with it.
128
///
129
/// Ideally with specialization this could be just one default impl and then specialized where
130
/// it doesn't apply.
131
macro_rules! delegate_debug (
132
    ($ty:ty) => {
133
        impl FmtConst for $ty {
134
            fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
135
                write!(f, "{:?}", self)
136
            }
137
        }
138
    }
139
);
140
141
delegate_debug!(str);
142
delegate_debug!(char);
143
delegate_debug!(u8);
144
delegate_debug!(i8);
145
delegate_debug!(u16);
146
delegate_debug!(i16);
147
delegate_debug!(u32);
148
delegate_debug!(i32);
149
delegate_debug!(u64);
150
delegate_debug!(i64);
151
delegate_debug!(u128);
152
delegate_debug!(i128);
153
delegate_debug!(bool);
154
155
/// `impl PhfBorrow<T> for T`
156
macro_rules! impl_reflexive(
157
    ($($t:ty),*) => (
158
        $(impl PhfBorrow<$t> for $t {
159
0
            fn borrow(&self) -> &$t {
160
0
                self
161
0
            }
162
        })*
163
    )
164
);
165
166
impl_reflexive!(
167
    str,
168
    char,
169
    u8,
170
    i8,
171
    u16,
172
    i16,
173
    u32,
174
    i32,
175
    u64,
176
    i64,
177
    u128,
178
    i128,
179
    bool,
180
    [u8]
181
);
182
183
#[cfg(feature = "std")]
184
impl PhfBorrow<str> for String {
185
    fn borrow(&self) -> &str {
186
        self
187
    }
188
}
189
190
#[cfg(feature = "std")]
191
impl PhfBorrow<[u8]> for Vec<u8> {
192
    fn borrow(&self) -> &[u8] {
193
        self
194
    }
195
}
196
197
#[cfg(feature = "std")]
198
delegate_debug!(String);
199
200
#[cfg(feature = "std")]
201
impl PhfHash for String {
202
    #[inline]
203
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
204
        (**self).phf_hash(state)
205
    }
206
}
207
208
#[cfg(feature = "std")]
209
impl PhfHash for Vec<u8> {
210
    #[inline]
211
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
212
        (**self).phf_hash(state)
213
    }
214
}
215
216
impl<'a, T: 'a + PhfHash + ?Sized> PhfHash for &'a T {
217
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
218
        (*self).phf_hash(state)
219
    }
220
}
221
222
impl<'a, T: 'a + FmtConst + ?Sized> FmtConst for &'a T {
223
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
224
        (*self).fmt_const(f)
225
    }
226
}
227
228
impl<'a> PhfBorrow<str> for &'a str {
229
    fn borrow(&self) -> &str {
230
        self
231
    }
232
}
233
234
impl<'a> PhfBorrow<[u8]> for &'a [u8] {
235
    fn borrow(&self) -> &[u8] {
236
        self
237
    }
238
}
239
240
impl PhfHash for str {
241
    #[inline]
242
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
243
        self.as_bytes().phf_hash(state)
244
    }
245
}
246
247
impl PhfHash for [u8] {
248
    #[inline]
249
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
250
        state.write(self);
251
    }
252
}
253
254
impl FmtConst for [u8] {
255
    #[inline]
256
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257
        // slices need a leading reference
258
        write!(f, "&{:?}", self)
259
    }
260
}
261
262
#[cfg(feature = "unicase")]
263
impl<S> PhfHash for unicase::UniCase<S>
264
where
265
    unicase::UniCase<S>: Hash,
266
{
267
    #[inline]
268
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
269
        self.hash(state)
270
    }
271
}
272
273
#[cfg(feature = "unicase")]
274
impl<S> FmtConst for unicase::UniCase<S>
275
where
276
    S: AsRef<str>,
277
{
278
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
279
        if self.is_ascii() {
280
            f.write_str("UniCase::ascii(")?;
281
        } else {
282
            f.write_str("UniCase::unicode(")?;
283
        }
284
285
        self.as_ref().fmt_const(f)?;
286
        f.write_str(")")
287
    }
288
}
289
290
#[cfg(feature = "unicase")]
291
impl<'b, 'a: 'b, S: ?Sized + 'a> PhfBorrow<unicase::UniCase<&'b S>> for unicase::UniCase<&'a S> {
292
    fn borrow(&self) -> &unicase::UniCase<&'b S> {
293
        self
294
    }
295
}
296
297
#[cfg(feature = "uncased")]
298
impl PhfHash for uncased::UncasedStr {
299
    #[inline]
300
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
301
        self.hash(state)
302
    }
303
}
304
305
#[cfg(feature = "uncased")]
306
impl FmtConst for uncased::UncasedStr {
307
    fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308
        // transmute is not stable in const fns (rust-lang/rust#53605), so
309
        // `UncasedStr::new` can't be a const fn itself, but we can inline the
310
        // call to transmute here in the meantime.
311
        f.write_str("unsafe { ::std::mem::transmute::<&'static str, &'static UncasedStr>(")?;
312
        self.as_str().fmt_const(f)?;
313
        f.write_str(") }")
314
    }
315
}
316
317
#[cfg(feature = "uncased")]
318
impl PhfBorrow<uncased::UncasedStr> for &uncased::UncasedStr {
319
    fn borrow(&self) -> &uncased::UncasedStr {
320
        self
321
    }
322
}
323
324
macro_rules! sip_impl (
325
    (le $t:ty) => (
326
        impl PhfHash for $t {
327
            #[inline]
328
0
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
329
0
                self.to_le().hash(state);
330
0
            }
Unexecuted instantiation: <u16 as phf_shared::PhfHash>::phf_hash::<siphasher::sip128::SipHasher13>
Unexecuted instantiation: <u16 as phf_shared::PhfHash>::phf_hash::<siphasher::sip128::SipHasher13>
331
        }
332
    );
333
    ($t:ty) => (
334
        impl PhfHash for $t {
335
            #[inline]
336
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
337
                self.hash(state);
338
            }
339
        }
340
    )
341
);
342
343
sip_impl!(u8);
344
sip_impl!(i8);
345
sip_impl!(le u16);
346
sip_impl!(le i16);
347
sip_impl!(le u32);
348
sip_impl!(le i32);
349
sip_impl!(le u64);
350
sip_impl!(le i64);
351
sip_impl!(le u128);
352
sip_impl!(le i128);
353
sip_impl!(bool);
354
355
impl PhfHash for char {
356
    #[inline]
357
    fn phf_hash<H: Hasher>(&self, state: &mut H) {
358
        (*self as u32).phf_hash(state)
359
    }
360
}
361
362
// minimize duplicated code since formatting drags in quite a bit
363
fn fmt_array(array: &[u8], f: &mut fmt::Formatter<'_>) -> fmt::Result {
364
    write!(f, "{:?}", array)
365
}
366
367
macro_rules! array_impl (
368
    ($t:ty, $n:expr) => (
369
        impl PhfHash for [$t; $n] {
370
            #[inline]
371
            fn phf_hash<H: Hasher>(&self, state: &mut H) {
372
                state.write(self);
373
            }
374
        }
375
376
        impl FmtConst for [$t; $n] {
377
            fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
378
                fmt_array(self, f)
379
            }
380
        }
381
382
        impl PhfBorrow<[$t]> for [$t; $n] {
383
            fn borrow(&self) -> &[$t] {
384
                self
385
            }
386
        }
387
    )
388
);
389
390
array_impl!(u8, 1);
391
array_impl!(u8, 2);
392
array_impl!(u8, 3);
393
array_impl!(u8, 4);
394
array_impl!(u8, 5);
395
array_impl!(u8, 6);
396
array_impl!(u8, 7);
397
array_impl!(u8, 8);
398
array_impl!(u8, 9);
399
array_impl!(u8, 10);
400
array_impl!(u8, 11);
401
array_impl!(u8, 12);
402
array_impl!(u8, 13);
403
array_impl!(u8, 14);
404
array_impl!(u8, 15);
405
array_impl!(u8, 16);
406
array_impl!(u8, 17);
407
array_impl!(u8, 18);
408
array_impl!(u8, 19);
409
array_impl!(u8, 20);
410
array_impl!(u8, 21);
411
array_impl!(u8, 22);
412
array_impl!(u8, 23);
413
array_impl!(u8, 24);
414
array_impl!(u8, 25);
415
array_impl!(u8, 26);
416
array_impl!(u8, 27);
417
array_impl!(u8, 28);
418
array_impl!(u8, 29);
419
array_impl!(u8, 30);
420
array_impl!(u8, 31);
421
array_impl!(u8, 32);