#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct SignatureCollision {
pub signature: u32,
pub members: Vec<usize>,
}
#[must_use]
pub fn find_signature_collisions(signatures: &[u32]) -> Vec<SignatureCollision> {
let mut order: Vec<u32> = Vec::new();
let mut groups: std::collections::HashMap<u32, Vec<usize>> = std::collections::HashMap::new();
for (i, &sig) in signatures.iter().enumerate() {
if sig == 0 {
continue;
}
let entry = groups.entry(sig).or_default();
if entry.is_empty() {
order.push(sig);
}
entry.push(i);
}
order
.into_iter()
.filter_map(|sig| {
let members = groups.remove(&sig).unwrap_or_default();
(members.len() >= 2).then_some(SignatureCollision {
signature: sig,
members,
})
})
.collect()
}