Skip to content

Commit

Permalink
feat(lcrust-stdlib): Implement SipHash and `core::hash::lcrust::hash_…
Browse files Browse the repository at this point in the history
…str`
  • Loading branch information
chorman0773 committed Aug 27, 2023
1 parent c7efcac commit 9d245d5
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 3 deletions.
56 changes: 56 additions & 0 deletions lcrust/libraries/libcore/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
35 changes: 32 additions & 3 deletions lcrust/libraries/libcore/src/hash/siphash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,21 @@ impl<const C: usize, const D: usize> SipHasher<C, D> {
}

impl<const C: usize, const D: usize> Hasher for SipHasher<C, D> {
#[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();
Expand All @@ -38,15 +51,31 @@ impl<const C: usize, const D: usize> Hasher for SipHasher<C, D> {

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 {
Expand Down

0 comments on commit 9d245d5

Please sign in to comment.