use serde::{Deserialize, Serialize};
use std::collections::HashSet;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct SpeakerId(pub u32);
#[derive(Debug, Clone, PartialEq)]
pub struct SpeakerIdRemap {
mapping: Vec<(SpeakerId, SpeakerId)>,
}
impl SpeakerIdRemap {
pub fn from_mapping(mapping: Vec<(SpeakerId, SpeakerId)>) -> Option<Self> {
let mut seen = HashSet::with_capacity(mapping.len());
for (old, _) in &mapping {
if !seen.insert(old) {
return None;
}
}
Some(Self { mapping })
}
pub fn remap(&self, id: SpeakerId) -> SpeakerId {
self.mapping
.iter()
.find(|(old, _)| *old == id)
.map(|(_, new)| *new)
.unwrap_or(id)
}
pub fn is_empty(&self) -> bool {
self.mapping.is_empty()
}
pub fn len(&self) -> usize {
self.mapping.len()
}
}
impl fmt::Display for SpeakerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SPEAKER_{:02}", self.0)
}
}
#[allow(clippy::unwrap_used)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_pads_to_two_digits() {
assert_eq!(SpeakerId(0).to_string(), "SPEAKER_00");
assert_eq!(SpeakerId(9).to_string(), "SPEAKER_09");
assert_eq!(SpeakerId(10).to_string(), "SPEAKER_10");
assert_eq!(SpeakerId(123).to_string(), "SPEAKER_123");
}
#[test]
fn from_mapping_rejects_duplicate_old_ids() {
let dup = SpeakerIdRemap::from_mapping(vec![
(SpeakerId(0), SpeakerId(1)),
(SpeakerId(0), SpeakerId(2)),
]);
assert!(dup.is_none());
}
#[test]
fn remap_applies_known_ids_and_passes_through_unknown() {
let remap = SpeakerIdRemap::from_mapping(vec![(SpeakerId(2), SpeakerId(0))]).unwrap();
assert_eq!(remap.len(), 1);
assert!(!remap.is_empty());
assert_eq!(remap.remap(SpeakerId(2)), SpeakerId(0));
assert_eq!(remap.remap(SpeakerId(7)), SpeakerId(7));
}
#[test]
fn empty_remap_is_identity() {
let remap = SpeakerIdRemap::from_mapping(vec![]).unwrap();
assert!(remap.is_empty());
assert_eq!(remap.len(), 0);
assert_eq!(remap.remap(SpeakerId(3)), SpeakerId(3));
}
#[test]
fn speaker_id_serde_roundtrip() {
let id = SpeakerId(42);
let json = serde_json::to_string(&id).unwrap();
assert_eq!(serde_json::from_str::<SpeakerId>(&json).unwrap(), id);
}
}