use crate::dbgeng::ModuleIdentity;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub enum VsSemanticFamily {
#[default]
Inline,
AffinitySlots,
}
impl VsSemanticFamily {
pub fn as_str(self) -> &'static str {
match self {
Self::Inline => "inline_vs",
Self::AffinitySlots => "affinity_slot_vs",
}
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub struct LayoutProvenance {
pub module: ModuleIdentity,
pub fingerprint: String,
pub semantic_family: VsSemanticFamily,
}
pub(crate) fn fingerprint<'a>(facts: impl IntoIterator<Item = &'a str>) -> String {
let mut hash = 0xcbf2_9ce4_8422_2325u64;
for fact in facts {
for byte in fact.as_bytes().iter().copied().chain([0xff]) {
hash ^= u64::from(byte);
hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
}
}
format!("fnv1a64:{hash:016x}")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_layout_fingerprint_is_stable_and_boundary_aware() {
assert_eq!(fingerprint(["a", "b"]), fingerprint(["a", "b"]));
assert_ne!(fingerprint(["ab"]), fingerprint(["a", "b"]));
assert_ne!(fingerprint(["a", "b"]), fingerprint(["b", "a"]));
}
}