From 9d245d5d5015e1aa3e9bf9dd4860696f9c5fdfe1 Mon Sep 17 00:00:00 2001 From: Connor Horman Date: Sun, 27 Aug 2023 15:36:40 -0400 Subject: [PATCH] feat(lcrust-stdlib): Implement SipHash and `core::hash::lcrust::hash_str` --- lcrust/libraries/libcore/src/hash.rs | 56 ++++++++++++++++++++ lcrust/libraries/libcore/src/hash/siphash.rs | 35 ++++++++++-- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/lcrust/libraries/libcore/src/hash.rs b/lcrust/libraries/libcore/src/hash.rs index 2fb287be..c63a4da1 100644 --- a/lcrust/libraries/libcore/src/hash.rs +++ b/lcrust/libraries/libcore/src/hash.rs @@ -141,3 +141,59 @@ impl SipHasher { Self(siphash::SipHasher::new_with_keys(k0, k1)) } } + +impl Hasher for SipHasher { + #[inline] + fn write(&mut self, x: &[u8]) { + self.0.write(x) + } + + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } +} + +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub struct SipHasher13(siphash::SipHasher<1, 3>); + +impl Default for SipHasher13 { + pub fn default() -> Self { + Self::new() + } +} + +impl SipHasher13 { + pub const fn new() -> Self { + Self::new_with_keys(0, 0); + } + + pub const fn new_with_keys(k0: u64, k1: u64) -> Self { + Self(siphash::SipHasher::new_with_keys(k0, k1)) + } +} + +impl Hasher for SipHasher13 { + #[inline] + fn write(&mut self, x: &[u8]) { + self.0.write(x) + } + + #[inline] + fn finish(&self) -> u64 { + self.0.finish() + } +} + +#[unstable(feature = "lcrust_abi_symbols")] +pub mod lcrust { + #[inline] + #[lcrust::force_export] + #[lang = "lcrust_hash_str_symbol"] + pub fn hash_str(x: &str, k0: u64, k1: u64) -> u64 { + let mut hasher = super::siphash::SipHash::<2, 4>::new_with_keys(k0, k1); + hasher.write(x); + + hasher.finish() + } +} diff --git a/lcrust/libraries/libcore/src/hash/siphash.rs b/lcrust/libraries/libcore/src/hash/siphash.rs index ba3689cd..2452fe4a 100644 --- a/lcrust/libraries/libcore/src/hash/siphash.rs +++ b/lcrust/libraries/libcore/src/hash/siphash.rs @@ -25,8 +25,21 @@ impl SipHasher { } impl Hasher for SipHasher { + #[inline] fn write(&mut self, mut s: &[u8]) { + if ntail > 0{ + let required = s.len().min(8-ntail); + let (l,r) = s.split_at(required); + + crate::mem::transmute(&self.tail)[ntail..][..required].copy_from_slice(l); + + s = r; + if required+ntail==8{ + self.update(self.tail.to_le()); + self.ntail = 0; + } + } let chunks_exact = s.chunks_exact(8); let remainder = chunks_exact.remainder(); @@ -38,15 +51,31 @@ impl Hasher for SipHasher { if !remainder.is_empty() { let mut bytes = [0u8; 8]; - bytes[..remainder.len()].copy_from_slice(remainder); - let word = u64::from_ne_bytes(bytes); - self.update(word); + self.ntail = remainder.len(); + bytes[..self.ntail].copy_from_slice(remainder); + self.tail = u64::from_ne_bytes(bytes); + } } + #[inline] fn finish(&self) -> u64 { let mut state = self.0; + if self.ntail >= 0{ + let mut val = self.tail.to_le(); + + if cfg!(target_endian = "big"){ + val >>= ((8-ntail)<<3); + } + + state.update_before_rounds(word); + for _ in 0..C { + state.round(); + } + state.update_after_rounds(word); + } + state.update_before_final(); for _ in 0..D {