use crate::entry::GptEntry;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct GuidCollision {
pub guid: String,
pub members: Vec<usize>,
}
const ZERO_GUID: &str = "00000000-0000-0000-0000-000000000000";
#[must_use]
pub fn find_disk_guid_collisions(guids: &[&str]) -> Vec<GuidCollision> {
let mut order: Vec<String> = Vec::new();
let mut groups: std::collections::HashMap<String, Vec<usize>> =
std::collections::HashMap::new();
for (i, g) in guids.iter().enumerate() {
let key = g.to_ascii_uppercase();
if key == ZERO_GUID {
continue;
}
let entry = groups.entry(key.clone()).or_default();
if entry.is_empty() {
order.push(key);
}
entry.push(i);
}
order
.into_iter()
.filter_map(|guid| {
let members = groups.remove(&guid).unwrap_or_default();
(members.len() >= 2).then_some(GuidCollision { guid, members })
})
.collect()
}
#[must_use]
pub fn find_duplicate_partition_guids(entries: &[GptEntry]) -> Vec<(usize, usize)> {
let mut out = Vec::new();
for a in 0..entries.len() {
if entries[a].unique_guid.is_zero() {
continue;
}
for b in (a + 1)..entries.len() {
if entries[a].unique_guid == entries[b].unique_guid {
out.push((a, b));
}
}
}
out
}