axhash_core/hasher/
core.rs1use crate::constants::SECRET;
2use crate::math::folded_multiply;
3
4#[derive(Clone, Debug)]
5pub struct AxHasher {
6 pub(crate) acc: u64,
7 pub(crate) sponge: u128,
8 pub(crate) sponge_bits: u8,
9}
10
11impl AxHasher {
12 #[inline(always)]
13 pub fn new() -> Self {
14 Self::new_with_seed(0)
15 }
16
17 #[inline(always)]
18 pub fn new_with_seed(seed: u64) -> Self {
19 Self {
20 acc: seed ^ SECRET[0],
21 sponge: 0,
22 sponge_bits: 0,
23 }
24 }
25
26 #[inline(always)]
27 pub(crate) fn flush_sponge(&mut self) {
28 if self.sponge_bits != 0 {
29 self.flush_sponge_slow();
30 }
31 }
32
33 #[inline(always)]
36 pub(crate) fn flush_sponge_hot(&mut self) {
37 let lo = self.sponge as u64;
38 let hi = (self.sponge >> 64) as u64;
39 self.acc = folded_multiply(lo ^ self.acc, hi ^ SECRET[1]);
40 self.sponge = 0;
41 self.sponge_bits = 0;
42 }
43
44 #[inline(never)]
47 #[cold]
48 pub(crate) fn flush_sponge_slow(&mut self) {
49 self.flush_sponge_hot();
50 }
51
52 #[inline(always)]
53 pub(crate) fn push_num<T: Into<u128>>(&mut self, value: T, bits: u8) {
54 if self.sponge_bits as u16 + bits as u16 > 128 {
55 self.flush_sponge();
56 }
57
58 self.sponge |= value.into() << self.sponge_bits;
59 self.sponge_bits += bits;
60 }
61
62 #[inline(always)]
66 pub(crate) fn push_bytes(&mut self, bytes: &[u8]) {
67 let n = bytes.len();
68 debug_assert!(n + ((self.sponge_bits >> 3) as usize) <= 16);
69 if n == 0 {
70 return;
71 }
72
73 let value: u128 = if n == 8 {
75 let arr: [u8; 8] = bytes.try_into().unwrap();
76 u64::from_le_bytes(arr) as u128
77 } else if n == 4 {
78 let arr: [u8; 4] = bytes.try_into().unwrap();
79 u32::from_le_bytes(arr) as u128
80 } else if n == 16 {
81 let arr: [u8; 16] = bytes.try_into().unwrap();
82 u128::from_le_bytes(arr)
83 } else if n == 1 {
84 bytes[0] as u128
85 } else if n == 2 {
86 let arr: [u8; 2] = bytes.try_into().unwrap();
87 u16::from_le_bytes(arr) as u128
88 } else {
89 let mut buf = [0u8; 16];
91 buf[..n].copy_from_slice(bytes);
92 u128::from_le_bytes(buf)
93 };
94
95 self.sponge |= value << self.sponge_bits;
96 self.sponge_bits += (n << 3) as u8;
97 }
98}
99
100impl Default for AxHasher {
101 #[inline(always)]
102 fn default() -> Self {
103 Self::new()
104 }
105}