siphasher/
common.rs

1/// Compression round for SipHash algorithm.
2macro_rules! compress {
3    ($state:expr) => {{
4        compress!($state.v0, $state.v1, $state.v2, $state.v3)
5    }};
6    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{
7        $v0 = $v0.wrapping_add($v1);
8        $v1 = $v1.rotate_left(13);
9        $v1 ^= $v0;
10        $v0 = $v0.rotate_left(32);
11        $v2 = $v2.wrapping_add($v3);
12        $v3 = $v3.rotate_left(16);
13        $v3 ^= $v2;
14        $v0 = $v0.wrapping_add($v3);
15        $v3 = $v3.rotate_left(21);
16        $v3 ^= $v0;
17        $v2 = $v2.wrapping_add($v1);
18        $v1 = $v1.rotate_left(17);
19        $v1 ^= $v2;
20        $v2 = $v2.rotate_left(32);
21    }};
22}
23
24/// Loads an integer of the desired type from a byte stream, in LE order.
25macro_rules! load_int_le {
26    ($buf:expr, $i:expr, $int_ty:ident) => {{
27        debug_assert!($i + ::core::mem::size_of::<$int_ty>() <= $buf.len());
28        let mut data = 0 as $int_ty;
29        ::core::ptr::copy_nonoverlapping(
30            $buf.as_ptr().add($i),
31            &mut data as *mut _ as *mut u8,
32            ::core::mem::size_of::<$int_ty>(),
33        );
34        data.to_le()
35    }};
36}
37
38/// Loads a u64 using up to 7 bytes of a byte slice.
39///
40/// # Safety
41///
42/// The caller must ensure that `start + len <= buf.len()` and `len < 8`.
43#[inline]
44pub unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
45    debug_assert!(len < 8);
46    let mut i = 0;
47    let mut out = 0;
48    if i + 3 < len {
49        out = load_int_le!(buf, start + i, u32) as u64;
50        i += 4;
51    }
52    if i + 1 < len {
53        out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8);
54        i += 2;
55    }
56    if i < len {
57        out |= (*buf.get_unchecked(start + i) as u64) << (i * 8);
58        i += 1;
59    }
60    debug_assert_eq!(i, len);
61    out
62}
63
64pub(crate) use compress;
65pub(crate) use load_int_le;