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