use crate::infrastructure::parser::ParsedVCard;
const OBSOLETE_PROPERTIES: &[&str] = &["AGENT", "LABEL", "MAILER"];
pub fn adapt_v3(vcard: &mut ParsedVCard) {
vcard.raw_properties.retain(|p| {
let upper = p.name.to_uppercase();
!OBSOLETE_PROPERTIES.contains(&upper.as_str())
});
for email in &mut vcard.emails_raw {
normalize_types_v3(&mut email.types, &mut email.pref);
}
for tel in &mut vcard.tels_raw {
normalize_types_v3(&mut tel.types, &mut tel.pref);
}
for prop in &mut vcard.raw_properties {
for param in &mut prop.params {
if param.name.eq_ignore_ascii_case("TYPE") {
param.values = param.values.iter().map(|v| v.to_lowercase()).collect();
}
}
}
vcard.version = Some("4.0".to_string());
}
fn normalize_types_v3(types: &mut Vec<String>, pref: &mut u8) {
let mut new_types = Vec::new();
for t in types.iter() {
let lower = t.to_lowercase();
if lower == "pref" {
*pref = 1;
} else {
new_types.push(lower);
}
}
*types = new_types;
}
#[cfg(test)]
mod tests {
use super::*;
use crate::infrastructure::parser::RawProperty;
#[test]
fn test_v3_type_lowercase() {
let mut vcard = ParsedVCard {
version: Some("3.0".to_string()),
emails_raw: vec![crate::infrastructure::parser::RawTypedValue {
value: "x@y.com".to_string(),
types: vec!["INTERNET".to_string(), "PREF".to_string()],
pref: 0,
}],
..Default::default()
};
adapt_v3(&mut vcard);
let email = &vcard.emails_raw[0];
assert_eq!(email.types, vec!["internet"]);
assert_eq!(email.pref, 1);
}
#[test]
fn test_v3_agent_ignored() {
let mut vcard = ParsedVCard {
version: Some("3.0".to_string()),
raw_properties: vec![
RawProperty {
group: None,
name: "FN".to_string(),
params: vec![],
value: "Test".to_string(),
},
RawProperty {
group: None,
name: "AGENT".to_string(),
params: vec![],
value: "BEGIN:VCARD...".to_string(),
},
RawProperty {
group: None,
name: "LABEL".to_string(),
params: vec![],
value: "Calle Test".to_string(),
},
RawProperty {
group: None,
name: "MAILER".to_string(),
params: vec![],
value: "Apple Mail".to_string(),
},
],
..Default::default()
};
adapt_v3(&mut vcard);
assert_eq!(vcard.raw_properties.len(), 1);
assert_eq!(vcard.raw_properties[0].name, "FN");
}
#[test]
fn test_v3_version_updated() {
let mut vcard = ParsedVCard {
version: Some("3.0".to_string()),
..Default::default()
};
adapt_v3(&mut vcard);
assert_eq!(vcard.version.as_deref(), Some("4.0"));
}
#[test]
fn test_v3_type_multi_value_lowercase() {
let mut vcard = ParsedVCard {
version: Some("3.0".to_string()),
tels_raw: vec![crate::infrastructure::parser::RawTypedValue {
value: "+34600000000".to_string(),
types: vec!["CELL".to_string(), "VOICE".to_string()],
pref: 0,
}],
..Default::default()
};
adapt_v3(&mut vcard);
let tel = &vcard.tels_raw[0];
assert_eq!(tel.types, vec!["cell", "voice"]);
assert_eq!(tel.pref, 0);
}
}