use calcard::vcard::{VCardProperty, VCardValue};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ContactError {
#[error("vCard parse failed")]
ParseFailed,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Contact {
pub display_name: Option<String>,
phones: Vec<String>,
}
impl Contact {
#[inline]
#[must_use]
pub fn phones(&self) -> &[String] {
&self.phones
}
}
impl Contact {
pub fn from_vcard_str(input: &str) -> Result<Self, ContactError> {
let vcard = calcard::vcard::VCard::parse(input).map_err(|_| ContactError::ParseFailed)?;
let display_name = vcard
.property(&VCardProperty::Fn)
.and_then(|e| e.values.first())
.and_then(VCardValue::as_text)
.map(str::to_owned);
let phones = vcard
.properties(&VCardProperty::Tel)
.flat_map(|e| e.values.iter())
.filter_map(VCardValue::as_text)
.map(|s| s.split_whitespace().collect::<String>())
.filter(|s| !s.is_empty())
.collect();
Ok(Self { display_name, phones })
}
}