A pit full of rusty nails
at main 80 lines 2.1 kB view raw
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}