blvm_primitives/crypto/
hash_compare.rs1use crate::types::Hash;
7#[inline]
19pub fn hash_eq(hash1: &Hash, hash2: &Hash) -> bool {
20 #[cfg(all(target_arch = "x86_64", feature = "production"))]
21 {
22 if is_avx2_available() {
24 unsafe { hash_eq_avx2(hash1, hash2) }
25 } else {
26 hash_eq_fallback(hash1, hash2)
27 }
28 }
29
30 #[cfg(not(all(target_arch = "x86_64", feature = "production")))]
31 {
32 hash_eq_fallback(hash1, hash2)
33 }
34}
35
36#[inline(always)]
38fn hash_eq_fallback(hash1: &Hash, hash2: &Hash) -> bool {
39 hash1 == hash2
40}
41
42#[cfg(all(target_arch = "x86_64", feature = "production"))]
46#[target_feature(enable = "avx2")]
47unsafe fn hash_eq_avx2(hash1: &Hash, hash2: &Hash) -> bool {
48 use std::arch::x86_64::*;
49
50 unsafe {
51 let h1 = _mm256_loadu_si256(hash1.as_ptr() as *const __m256i);
53 let h2 = _mm256_loadu_si256(hash2.as_ptr() as *const __m256i);
54
55 let cmp = _mm256_cmpeq_epi8(h1, h2);
57
58 let mask = _mm256_movemask_epi8(cmp);
60
61 mask == -1i32
63 }
64}
65
66#[cfg(all(target_arch = "x86_64", feature = "production"))]
68fn is_avx2_available() -> bool {
69 std::arch::is_x86_feature_detected!("avx2")
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_hash_eq_identical() {
78 let hash1 = [0u8; 32];
79 let hash2 = [0u8; 32];
80 assert!(hash_eq(&hash1, &hash2));
81 }
82
83 #[test]
84 fn test_hash_eq_different() {
85 let hash1 = [0u8; 32];
86 let mut hash2 = [0u8; 32];
87 hash2[0] = 1;
88 assert!(!hash_eq(&hash1, &hash2));
89 }
90
91 #[test]
92 fn test_hash_eq_different_last_byte() {
93 let mut hash1 = [0u8; 32];
94 let mut hash2 = [0u8; 32];
95 hash1[31] = 0;
96 hash2[31] = 1;
97 assert!(!hash_eq(&hash1, &hash2));
98 }
99
100 #[test]
101 fn test_hash_eq_random() {
102 let hash1: Hash = [
103 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
104 25, 26, 27, 28, 29, 30, 31, 32,
105 ];
106 let hash2: Hash = [
107 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
108 25, 26, 27, 28, 29, 30, 31, 33,
109 ];
110
111 assert_eq!(hash_eq(&hash1, &hash1), hash1 == hash1);
113 assert_eq!(hash_eq(&hash1, &hash2), hash1 == hash2);
114 }
115}