Skip to main content

axhash_core/
lib.rs

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}