Skip to main content

axhash_core/hasher/
trait_impl.rs

1use super::AxHasher;
2
3use crate::backend::hash_bytes_core;
4use crate::constants::SECRET;
5use crate::math::{avalanche, folded_multiply};
6
7use core::hash::Hasher;
8
9impl Hasher for AxHasher {
10    #[inline(always)]
11    fn finish(&self) -> u64 {
12        let mut acc = self.acc;
13        if self.sponge_bits != 0 {
14            let lo = self.sponge as u64;
15            let hi = (self.sponge >> 64) as u64;
16            acc = folded_multiply(lo ^ acc, hi ^ SECRET[1]);
17        }
18        avalanche(acc)
19    }
20
21    #[inline(always)]
22    fn write(&mut self, bytes: &[u8]) {
23        let len = bytes.len();
24        if len == 0 {
25            return;
26        }
27
28        // Slice sangat pendek (<8 byte) di-buffer ke sponge — overhead
29        // push_bytes lebih murah dari hash_bytes_short dispatch untuk
30        // sub-word writes (write_u8 trait, partial byte streams).
31        //
32        // Slice 8..=16 byte tetap lewat hash_bytes_core karena hash_bytes_short
33        // branch len≥8 hanya 2 folded_multiply — sudah optimal dan tidak
34        // perlu sponge overhead.
35        if len < 8 {
36            let used = (self.sponge_bits >> 3) as usize;
37            let free = 16 - used;
38
39            if len <= free {
40                self.push_bytes(bytes);
41            } else {
42                self.push_bytes(&bytes[..free]);
43                self.flush_sponge_hot();
44                self.push_bytes(&bytes[free..]);
45            }
46            return;
47        }
48
49        // Slice panjang: flush sponge dulu, lalu lewat hash_bytes_core
50        // (AES path untuk len > 128, scalar untuk 17..=128).
51        if self.sponge_bits != 0 {
52            self.flush_sponge_slow();
53        }
54        self.acc = hash_bytes_core(bytes, self.acc);
55    }
56
57    #[inline(always)]
58    fn write_u8(&mut self, i: u8) {
59        self.push_num(i, 8);
60    }
61
62    #[inline(always)]
63    fn write_u16(&mut self, i: u16) {
64        self.push_num(i, 16);
65    }
66
67    #[inline(always)]
68    fn write_u32(&mut self, i: u32) {
69        if self.sponge_bits != 0 {
70            self.flush_sponge_slow();
71        }
72        self.acc = folded_multiply(self.acc ^ i as u64, SECRET[1]);
73    }
74
75    #[inline(always)]
76    fn write_u64(&mut self, i: u64) {
77        if self.sponge_bits != 0 {
78            self.flush_sponge_slow();
79        }
80        self.acc = folded_multiply(self.acc ^ i, SECRET[1]);
81    }
82
83    #[inline(always)]
84    fn write_u128(&mut self, i: u128) {
85        if self.sponge_bits != 0 {
86            self.flush_sponge_slow();
87        }
88        let lo = i as u64;
89        let hi = (i >> 64) as u64;
90        self.acc = folded_multiply(lo ^ self.acc, hi ^ SECRET[1]);
91    }
92
93    #[inline(always)]
94    fn write_usize(&mut self, i: usize) {
95        #[cfg(target_pointer_width = "32")]
96        self.write_u32(i as u32);
97        #[cfg(target_pointer_width = "64")]
98        self.write_u64(i as u64);
99    }
100
101    #[inline(always)]
102    fn write_i8(&mut self, i: i8) {
103        self.write_u8(i as u8);
104    }
105
106    #[inline(always)]
107    fn write_i16(&mut self, i: i16) {
108        self.write_u16(i as u16);
109    }
110
111    #[inline(always)]
112    fn write_i32(&mut self, i: i32) {
113        self.write_u32(i as u32);
114    }
115
116    #[inline(always)]
117    fn write_i64(&mut self, i: i64) {
118        self.write_u64(i as u64);
119    }
120
121    #[inline(always)]
122    fn write_i128(&mut self, i: i128) {
123        self.write_u128(i as u128);
124    }
125
126    #[inline(always)]
127    fn write_isize(&mut self, i: isize) {
128        self.write_usize(i as usize);
129    }
130}