A pit full of rusty nails
1use estr::Estr;
2
3/// Representation of a string segment.
4#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
5#[repr(transparent)]
6pub struct Token(Estr);
7
8impl Token {
9 #[inline(always)]
10 pub fn new(str: &str) -> Self {
11 Self(Estr::from(str))
12 }
13
14 #[inline]
15 pub fn as_str(&self) -> &'static str {
16 self.0.as_str()
17 }
18
19 #[inline]
20 pub fn as_bytes(&self) -> &'static [u8] {
21 self.0.as_str().as_bytes()
22 }
23}
24
25impl From<&str> for Token {
26 fn from(value: &str) -> Self {
27 Self::new(value)
28 }
29}
30
31/// An owned pair of [`Token`]s.
32#[derive(Copy, Clone, Debug, PartialEq, Eq)]
33// Alignment repr necessary to allow LLVM to better output
34// Prior art taken from my contribution to Bevy:
35// https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/entity/mod.rs#L309
36#[repr(C, align(16))]
37pub struct TokenPair {
38 // Do not reorder the fields here. The ordering is explicitly used by repr(C)
39 // to make this struct equivalent to a u128.
40 #[cfg(target_endian = "little")]
41 pub left: Token,
42 pub right: Token,
43 #[cfg(target_endian = "big")]
44 pub left: Token,
45}
46
47impl core::hash::Hash for TokenPair {
48 #[inline]
49 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
50 // Use only with an IdentityHasher so that you don't rehash the hash
51 self.mix_hashes().hash(state);
52 }
53}
54
55impl TokenPair {
56 #[inline(always)]
57 pub const fn new(left: Token, right: Token) -> Self {
58 Self { left, right }
59 }
60
61 /// Use the precomputed hashes to generate a secondary hash.
62 /// Method from [fastbloom](https://github.com/tomtomwombat/fastbloom/blob/main/src/hasher.rs#L182),
63 /// which was in turn adapted from <https://www.eecs.harvard.edu/~michaelm/postscripts/rsa2008.pdf>.
64 #[inline(always)]
65 fn mix_hashes(&self) -> u64 {
66 self.left
67 .0
68 .digest()
69 .hash()
70 .rotate_left(5)
71 .wrapping_add(self.right.0.digest().hash())
72 }
73}
74
75impl AsRef<TokenPair> for TokenPair {
76 #[inline]
77 fn as_ref(&self) -> &TokenPair {
78 self
79 }
80}