use siphasher::sip::SipHasher24;
use std::hash::{Hash, Hasher};
const DEFAULT_SIPHASH_KEY: (u64, u64) = (
0x0706050403020100, 0x0F0E0D0C0B0A0908, );
pub fn hash_name_u32(name: &str) -> u32 {
let hash = hash_name_u64(name);
((hash >> 32) ^ hash) as u32
}
pub fn hash_name_u64(name: &str) -> u64 {
let mut hasher = SipHasher24::new_with_keys(DEFAULT_SIPHASH_KEY.0, DEFAULT_SIPHASH_KEY.1);
name.hash(&mut hasher);
hasher.finish()
}
pub fn hash_name_with_key(name: &str, key: (u64, u64)) -> u64 {
let mut hasher = SipHasher24::new_with_keys(key.0, key.1);
name.hash(&mut hasher);
hasher.finish()
}
#[macro_export]
macro_rules! interface_id {
($name:expr) => {{ $crate::siphash::hash_name_u32($name) }};
}
#[macro_export]
macro_rules! header_key_id {
($name:expr) => {{ $crate::siphash::hash_name_u32($name) }};
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deterministic_hashing() {
let name = "mensa.user.v2.UserInterface";
let id1 = hash_name_u32(name);
let id2 = hash_name_u32(name);
assert_eq!(id1, id2, "Same name should produce same hash");
}
#[test]
fn test_different_names_different_hashes() {
let id1 = hash_name_u32("mensa.user.v2.UserInterface");
let id2 = hash_name_u32("mensa.payment.v1.PaymentInterface");
assert_ne!(id1, id2, "Different names should produce different hashes");
}
#[test]
fn test_u64_vs_u32() {
let name = "test_interface";
let hash64 = hash_name_u64(name);
let hash32 = hash_name_u32(name);
let expected_u32 = ((hash64 >> 32) ^ hash64) as u32;
assert_eq!(hash32, expected_u32);
}
#[test]
fn test_custom_key() {
let name = "test_name";
let default_hash = hash_name_u64(name);
let custom_hash = hash_name_with_key(name, (0x1111111111111111, 0x2222222222222222));
assert_ne!(
default_hash, custom_hash,
"Custom key should produce different hash"
);
}
#[test]
fn test_header_keys() {
let trace_id = hash_name_u32("trace_id");
let request_id = hash_name_u32("request_id");
let span_id = hash_name_u32("span_id");
assert_ne!(trace_id, request_id);
assert_ne!(trace_id, span_id);
assert_ne!(request_id, span_id);
}
#[test]
fn test_version_sensitivity() {
let v1 = hash_name_u32("mensa.user.v1.UserInterface");
let v2 = hash_name_u32("mensa.user.v2.UserInterface");
assert_ne!(v1, v2, "Different versions should have different IDs");
}
}