use estr::Estr; /// Representation of a string segment. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[repr(transparent)] pub struct Token(Estr); impl Token { #[inline(always)] pub fn new(str: &str) -> Self { Self(Estr::from(str)) } #[inline] pub fn as_str(&self) -> &'static str { self.0.as_str() } #[inline] pub fn as_bytes(&self) -> &'static [u8] { self.0.as_str().as_bytes() } } impl From<&str> for Token { fn from(value: &str) -> Self { Self::new(value) } } /// An owned pair of [`Token`]s. #[derive(Copy, Clone, Debug, PartialEq, Eq)] // Alignment repr necessary to allow LLVM to better output // Prior art taken from my contribution to Bevy: // https://github.com/bevyengine/bevy/blob/main/crates/bevy_ecs/src/entity/mod.rs#L309 #[repr(C, align(16))] pub struct TokenPair { // Do not reorder the fields here. The ordering is explicitly used by repr(C) // to make this struct equivalent to a u128. #[cfg(target_endian = "little")] pub left: Token, pub right: Token, #[cfg(target_endian = "big")] pub left: Token, } impl core::hash::Hash for TokenPair { #[inline] fn hash(&self, state: &mut H) { // Use only with an IdentityHasher so that you don't rehash the hash self.mix_hashes().hash(state); } } impl TokenPair { #[inline(always)] pub const fn new(left: Token, right: Token) -> Self { Self { left, right } } /// Use the precomputed hashes to generate a secondary hash. /// Method from [fastbloom](https://github.com/tomtomwombat/fastbloom/blob/main/src/hasher.rs#L182), /// which was in turn adapted from . #[inline(always)] fn mix_hashes(&self) -> u64 { self.left .0 .digest() .hash() .rotate_left(5) .wrapping_add(self.right.0.digest().hash()) } } impl AsRef for TokenPair { #[inline] fn as_ref(&self) -> &TokenPair { self } }