pub fn fnv1a_xor8hex(s: &str) -> String {
let h = fnv1a_u64(s.as_bytes());
format!("{:08x}", (h as u32) ^ ((h >> 32) as u32))
}
pub fn fnv1a_u16_mod(s: &str, modulus: u16) -> u16 {
if modulus == 0 {
return 0;
}
let h = fnv1a_u64(s.as_bytes());
(h as u16) % modulus
}
pub fn fnv1a_u64(bytes: &[u8]) -> u64 {
let mut h: u64 = 0xcbf2_9ce4_8422_2325; for b in bytes {
h ^= u64::from(*b);
h = h.wrapping_mul(0x100_0000_01b3); }
h
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fnv1a_empty_is_offset_basis() {
assert_eq!(fnv1a_u64(b""), 0xcbf2_9ce4_8422_2325);
}
#[test]
fn fnv1a_stable() {
assert_eq!(fnv1a_xor8hex("gpu,cuda").len(), 8);
assert_eq!(fnv1a_xor8hex("gpu,cuda"), fnv1a_xor8hex("gpu,cuda"));
}
#[test]
fn fnv1a_u16_mod_spread() {
let a = fnv1a_u16_mod("worker-a", 256);
let b = fnv1a_u16_mod("worker-b", 256);
assert!(a < 256 && b < 256);
assert_eq!(fnv1a_u16_mod("anything", 0), 0);
}
}