1#![cfg_attr(not(any(feature = "std", test)), no_std)]
2pub mod hash;
3
4mod bytes;
5mod constants;
6mod hasher;
7mod math;
8mod memory;
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub enum RuntimeBackend {
12 Scalar,
13 Aarch64AesNeon,
14 X86_64AesAvx2,
15}
16
17#[inline(always)]
18pub fn runtime_backend() -> RuntimeBackend {
19 match bytes::selected_backend() {
20 bytes::Backend::Scalar => RuntimeBackend::Scalar,
21 #[cfg(target_arch = "aarch64")]
22 bytes::Backend::Aarch64AesNeon => RuntimeBackend::Aarch64AesNeon,
23 #[cfg(target_arch = "x86_64")]
24 bytes::Backend::X86_64AesAvx2 => RuntimeBackend::X86_64AesAvx2,
25 }
26}
27
28#[inline(always)]
29pub fn runtime_has_aes() -> bool {
30 runtime_backend() != RuntimeBackend::Scalar
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::RuntimeBackend;
36 use crate::hash::AxHasher;
37 use crate::hash::api::*;
38 use core::hash::{Hash, Hasher};
39
40 #[derive(Hash)]
41 struct DemoRecord {
42 id: u64,
43 shard: u32,
44 flags: u32,
45 }
46
47 #[test]
48 fn hash_is_deterministic_for_bytes() {
49 let data = b"axhash regression seed";
50 let a = axhash_seeded(data, 0x1234_5678_9abc_def0);
51 let b = axhash_seeded(data, 0x1234_5678_9abc_def0);
52 assert_eq!(a, b);
53 }
54
55 #[test]
56 fn hash_changes_when_seed_changes() {
57 let data = b"same payload different seed";
58 let a = axhash_seeded(data, 1);
59 let b = axhash_seeded(data, 2);
60 assert_ne!(a, b);
61 }
62
63 #[test]
64 fn hash_trait_path_is_deterministic() {
65 let record = DemoRecord {
66 id: 42,
67 shard: 7,
68 flags: 3,
69 };
70 let a = axhash_of_seeded(&record, 0xdead_beef);
71 let b = axhash_of_seeded(&record, 0xdead_beef);
72 assert_eq!(a, b);
73 }
74
75 #[test]
76 fn primitive_writes_produce_a_stable_finish() {
77 let mut hasher = AxHasher::new_with_seed(0x4444);
78 hasher.write_u64(0x0102_0304_0506_0708);
79 hasher.write_u32(0xaabb_ccdd);
80 hasher.write_u16(0xeeff);
81 hasher.write_u8(0x11);
82 let value = hasher.finish();
83 assert_ne!(value, 0);
84 }
85
86 #[test]
87 fn test_axhash_default_seed() {
88 let data = b"default seed test";
89 let a = axhash(data);
90 let b = axhash_seeded(data, 0);
91 assert_eq!(a, b);
92 }
93
94 #[test]
95 fn test_axhash_of_default_seed() {
96 let record = DemoRecord {
97 id: 1,
98 shard: 2,
99 flags: 3,
100 };
101 let a = axhash_of(&record);
102 let b = axhash_of_seeded(&record, 0);
103 assert_eq!(a, b);
104 }
105
106 #[test]
107 fn runtime_backend_smoke_test() {
108 match super::runtime_backend() {
109 RuntimeBackend::Scalar
110 | RuntimeBackend::Aarch64AesNeon
111 | RuntimeBackend::X86_64AesAvx2 => {}
112 }
113 }
114}