pub fn sip_round(v0: &mut u64, v1: &mut u64, v2: &mut u64, v3: &mut u64) {
*v0 = v0.wrapping_add(*v1);
*v1 = v1.rotate_left(13);
*v1 ^= *v0;
*v0 = v0.rotate_left(32);
*v2 = v2.wrapping_add(*v3);
*v3 = v3.rotate_left(16);
*v3 ^= *v2;
*v0 = v0.wrapping_add(*v3);
*v3 = v3.rotate_left(21);
*v3 ^= *v0;
*v2 = v2.wrapping_add(*v1);
*v1 = v1.rotate_left(17);
*v1 ^= *v2;
*v2 = v2.rotate_left(32);
}
#[must_use]
pub(crate) fn siphash13(msg: &[u8], key: u64) -> u64 {
let k0 = key;
let k1 = key.rotate_left(32) ^ 0x736f6d6570736575;
let mut v0 = 0x736f6d6570736575 ^ k0;
let mut v1 = 0x646f72616e646f6d ^ k1;
let mut v2 = 0x6c7967656e657261 ^ k0;
let mut v3 = 0x7465646279746573 ^ k1;
let mut chunks = msg.chunks_exact(8);
for chunk in &mut chunks {
let m = u64::from_le_bytes([
chunk[0], chunk[1], chunk[2], chunk[3], chunk[4], chunk[5], chunk[6], chunk[7],
]);
v3 ^= m;
sip_round(&mut v0, &mut v1, &mut v2, &mut v3);
v0 ^= m;
}
let rem = chunks.remainder();
let mut b = (msg.len() as u64) << 56;
for (i, byte) in rem.iter().enumerate() {
b |= u64::from(*byte) << (8 * i);
}
v3 ^= b;
sip_round(&mut v0, &mut v1, &mut v2, &mut v3);
v0 ^= b;
v2 ^= 0xff;
for _ in 0..3 {
sip_round(&mut v0, &mut v1, &mut v2, &mut v3);
}
v0 ^ v1 ^ v2 ^ v3
}