wraith/util/
hash.rs

1//! String hashing utilities for API hashing
2
3/// DJB2 hash algorithm
4pub const fn djb2_hash(s: &[u8]) -> u32 {
5    let mut hash: u32 = 5381;
6    let mut i = 0;
7    while i < s.len() {
8        hash = hash.wrapping_mul(33).wrapping_add(s[i] as u32);
9        i += 1;
10    }
11    hash
12}
13
14/// FNV-1a hash algorithm
15pub const fn fnv1a_hash(s: &[u8]) -> u32 {
16    const FNV_OFFSET: u32 = 2166136261;
17    const FNV_PRIME: u32 = 16777619;
18
19    let mut hash = FNV_OFFSET;
20    let mut i = 0;
21    while i < s.len() {
22        hash ^= s[i] as u32;
23        hash = hash.wrapping_mul(FNV_PRIME);
24        i += 1;
25    }
26    hash
27}
28
29/// hash string with lowercase conversion (for case-insensitive matching)
30pub const fn djb2_hash_lowercase(s: &[u8]) -> u32 {
31    let mut hash: u32 = 5381;
32    let mut i = 0;
33    while i < s.len() {
34        let c = if s[i] >= b'A' && s[i] <= b'Z' {
35            s[i] + 32
36        } else {
37            s[i]
38        };
39        hash = hash.wrapping_mul(33).wrapping_add(c as u32);
40        i += 1;
41    }
42    hash
43}
44
45/// compile-time hash macro
46#[macro_export]
47macro_rules! hash {
48    ($s:expr) => {
49        $crate::util::hash::djb2_hash($s.as_bytes())
50    };
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_djb2() {
59        assert_eq!(djb2_hash(b"ntdll.dll"), djb2_hash(b"ntdll.dll"));
60        assert_ne!(djb2_hash(b"ntdll.dll"), djb2_hash(b"kernel32.dll"));
61    }
62
63    #[test]
64    fn test_case_insensitive() {
65        assert_eq!(
66            djb2_hash_lowercase(b"NtDll.Dll"),
67            djb2_hash_lowercase(b"ntdll.dll")
68        );
69    }
70}