1pub const fn fnv1a(bytes: &[u8]) -> u64 {
15 let mut h: u64 = 0xcbf2_9ce4_8422_2325;
16 let mut i = 0usize;
17 while i < bytes.len() {
18 h ^= bytes[i] as u64;
19 h = h.wrapping_mul(0x0000_0100_0000_01b3);
20 i += 1;
21 }
22 h
23}
24
25pub fn fnv1a_str(s: &str) -> u64 {
27 fnv1a(s.as_bytes())
28}
29
30pub fn fnv1a_parts(parts: &[u64]) -> u64 {
32 let mut h: u64 = 0xcbf2_9ce4_8422_2325;
33 for &p in parts {
34 let mut shift = 0usize;
35 while shift < 8 {
36 h ^= (p >> (shift * 8)) & 0xff;
37 h = h.wrapping_mul(0x0000_0100_0000_01b3);
38 shift += 1;
39 }
40 }
41 h
42}
43
44pub fn fnv1a_combine(acc: u64, next: u64) -> u64 {
46 let mut h = acc ^ 0x9e37_79b9_7f4a_7c15;
47 let mut shift = 0usize;
48 while shift < 8 {
49 h ^= (next >> (shift * 8)) & 0xff;
50 h = h.wrapping_mul(0x0000_0100_0000_01b3);
51 shift += 1;
52 }
53 h
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59
60 #[test]
61 fn fnv1a_known_vector() {
62 assert_eq!(fnv1a(b""), 0xcbf2_9ce4_8422_2325);
64 assert_eq!(fnv1a(b"a"), 0xaf63_dc4c_8601_ec8c);
66 }
67
68 #[test]
69 fn parts_combine_is_stable() {
70 assert_eq!(fnv1a_parts(&[1, 2, 3]), fnv1a_parts(&[1, 2, 3]));
71 assert_ne!(fnv1a_parts(&[1, 2, 3]), fnv1a_parts(&[1, 2, 4]));
72 }
73
74 #[test]
75 fn str_matches_bytes() {
76 assert_eq!(fnv1a_str("hello"), fnv1a(b"hello"));
77 }
78}