///|
/// FNV-1a hasher used by upstream Hashable. Numeric writes use little-endian
/// encoding, matching the pinned Rust oracle on supported 64-bit hosts.
pub struct FnvHasher {
priv mut state : UInt64
}
///|
pub fn FnvHasher::FnvHasher() -> FnvHasher {
{ state: 0xcbf29ce484222325UL, }
}
///|
pub fn FnvHasher::write_byte(self : FnvHasher, value : Byte) -> Unit {
self.state = (self.state ^ value.to_uint64()) * 0x100000001b3UL
}
///|
pub fn FnvHasher::write(self : FnvHasher, bytes : BytesView) -> Unit {
for value in bytes {
self.write_byte(value)
}
}
///|
pub fn FnvHasher::write_word(
self : FnvHasher,
value : UInt64,
width : Int32,
) -> Unit {
guard width >= 0 && width <= 8 else {
abort("hash word width must be between zero and eight")
}
for index in 0..> (index * 8)).to_byte())
}
}
///|
pub fn FnvHasher::finish(self : FnvHasher) -> UInt64 {
self.state
}
///|
/// Rust Hash byte encoding for identifier interoperability. Custom records can
/// implement this trait by hashing their fields in declaration order.
pub(open) trait RustHash {
fn hash_into(Self, FnvHasher) -> Unit
}
///|
pub fn[T : RustHash] rust_hash(value : T) -> UInt64 {
let hasher = FnvHasher()
value.hash_into(hasher)
hasher.finish()
}
///|
pub impl RustHash for Byte with fn hash_into(self, hasher) {
hasher.write_word(self.to_uint64(), 1)
}
///|
pub impl RustHash for Int8 with fn hash_into(self, hasher) {
hasher.write_word(self.to_int().to_int64().reinterpret_as_uint64(), 1)
}
///|
pub impl RustHash for Int16 with fn hash_into(self, hasher) {
hasher.write_word(self.to_int().to_int64().reinterpret_as_uint64(), 2)
}
///|
pub impl RustHash for UInt16 with fn hash_into(self, hasher) {
hasher.write_word(self.to_uint64(), 2)
}
///|
pub impl RustHash for Int32 with fn hash_into(self, hasher) {
hasher.write_word(self.to_int64().reinterpret_as_uint64(), 4)
}
///|
pub impl RustHash for UInt32 with fn hash_into(self, hasher) {
hasher.write_word(self.to_uint64(), 4)
}
///|
pub impl RustHash for Int64 with fn hash_into(self, hasher) {
hasher.write_word(self.reinterpret_as_uint64(), 8)
}
///|
pub impl RustHash for UInt64 with fn hash_into(self, hasher) {
hasher.write_word(self, 8)
}
///|
pub impl RustHash for Int128 with fn hash_into(self, hasher) {
let (high, low) = self.to_words()
hasher.write_word(low, 8)
hasher.write_word(high.reinterpret_as_uint64(), 8)
}
///|
pub impl RustHash for UInt128 with fn hash_into(self, hasher) {
let (high, low) = self.to_words()
hasher.write_word(low, 8)
hasher.write_word(high, 8)
}
///|
pub impl RustHash for Bool with fn hash_into(self, hasher) {
hasher.write_byte(if self { 1 } else { 0 })
}
///|
pub impl RustHash for Unit with fn hash_into(_, _) {
()
}
///|
pub impl RustHash for Char with fn hash_into(self, hasher) {
hasher.write_word(self.to_int().to_uint64(), 4)
}
///|
pub impl RustHash for String with fn hash_into(self, hasher) {
hasher.write(@utf8.encode(self[:]))
hasher.write_byte(255)
}
///|
pub impl RustHash for Bytes with fn hash_into(self, hasher) {
hasher.write_word(self.length().to_uint64(), 8)
hasher.write(self)
}
///|
pub impl[T : RustHash] RustHash for Array[T] with fn hash_into(self, hasher) {
hasher.write_word(self.length().to_uint64(), 8)
for value in self {
value.hash_into(hasher)
}
}
///|
pub impl[T : RustHash] RustHash for T? with fn hash_into(self, hasher) {
match self {
None => hasher.write_word(0UL, 8)
Some(value) => {
hasher.write_word(1UL, 8)
value.hash_into(hasher)
}
}
}
///|
pub impl[A : RustHash, B : RustHash] RustHash for (A, B) with fn hash_into(
self,
hasher,
) {
self.0.hash_into(hasher)
self.1.hash_into(hasher)
}
///|
pub impl[A : RustHash, B : RustHash, C : RustHash] RustHash for (A, B, C) with fn hash_into(
self,
hasher,
) {
self.0.hash_into(hasher)
self.1.hash_into(hasher)
self.2.hash_into(hasher)
}
///|
pub impl[A : RustHash, B : RustHash, C : RustHash, D : RustHash] RustHash for (
A,
B,
C,
D,
) with fn hash_into(self, hasher) {
self.0.hash_into(hasher)
self.1.hash_into(hasher)
self.2.hash_into(hasher)
self.3.hash_into(hasher)
}
///|
pub extend Int8 with RustHash::{hash_into}
///|
pub extend Int128 with RustHash::{hash_into}
///|
pub extend UInt128 with RustHash::{hash_into}