use anyhow::{Result, anyhow}; use serde::{Deserialize, Serialize}; /// Código de idioma ISO 639-2 (3 letras minúsculas), ex: "por", "eng". #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct TrackLanguage(String); impl TrackLanguage { /// Cria um TrackLanguage validando o formato ISO 639-2 (3 letras minúsculas). pub fn new(code: impl Into) -> Result { let code = code.into(); if code.len() == 3 && code.chars().all(|c| c.is_ascii_lowercase()) { Ok(TrackLanguage(code)) } else { Err(anyhow!( "Código de idioma inválido: '{}'. Esperado formato ISO 639-2 (3 letras minúsculas, ex: 'por', 'eng')", code )) } } pub fn as_str(&self) -> &str { &self.0 } } impl std::fmt::Display for TrackLanguage { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } #[cfg(test)] mod tests { use super::*; #[test] fn idioma_valido() { assert!(TrackLanguage::new("por").is_ok()); assert!(TrackLanguage::new("eng").is_ok()); } #[test] fn idioma_invalido_curto() { assert!(TrackLanguage::new("pt").is_err()); } #[test] fn idioma_invalido_maiusculo() { assert!(TrackLanguage::new("POR").is_err()); } #[test] fn idioma_invalido_longo() { assert!(TrackLanguage::new("port").is_err()); } }