use std::fmt::{Display, Formatter};
use crate::constants::ParameterName;
use crate::parse::value::utf8_to_string;
use crate::vcard::parameter::parameter_altid::ParameterAltIdData;
use crate::vcard::parameter::parameter_calscale::ParameterCalScaleData;
use crate::vcard::parameter::parameter_cc::ParameterCcData;
use crate::vcard::parameter::parameter_geo::ParameterGeoData;
use crate::vcard::parameter::parameter_index::ParameterIndexData;
use crate::vcard::parameter::parameter_label::ParameterLabelData;
use crate::vcard::parameter::parameter_language::ParameterLanguageData;
use crate::vcard::parameter::parameter_level::ParameterLevelData;
use crate::vcard::parameter::parameter_mediatype::ParameterMediaTypeData;
use crate::vcard::parameter::parameter_pid::ParameterPidData;
use crate::vcard::parameter::parameter_pref::ParameterPrefData;
use crate::vcard::parameter::parameter_sortas::ParameterSortAsData;
use crate::vcard::parameter::parameter_type::ParameterTypeData;
use crate::vcard::parameter::parameter_tz::ParameterTzData;
use crate::vcard::parameter::parameter_value::ValueParameterData;
use crate::vcard::parameter::parameter_xname::XNameParameterData;
use crate::vcard::value::Value;
use crate::{parse, HasName, HasValue, VcardError};
pub mod parameter_altid;
pub mod parameter_calscale;
pub mod parameter_cc;
pub mod parameter_geo;
pub mod parameter_index;
pub mod parameter_label;
pub mod parameter_language;
pub mod parameter_level;
pub mod parameter_mediatype;
pub mod parameter_pid;
pub mod parameter_pref;
pub mod parameter_sortas;
pub mod parameter_type;
pub mod parameter_tz;
pub mod parameter_value;
pub mod parameter_xname;
#[derive(Clone, Debug, PartialEq)]
pub enum Parameter {
ParameterAltId(ParameterAltIdData),
ParameterCalScale(ParameterCalScaleData),
ParameterCc(ParameterCcData),
ParameterGeo(ParameterGeoData),
ParameterIndex(ParameterIndexData),
ParameterLabel(ParameterLabelData),
ParameterLanguage(ParameterLanguageData),
ParameterLevel(ParameterLevelData),
ParameterMediaType(ParameterMediaTypeData),
ParameterPid(ParameterPidData),
ParameterPref(ParameterPrefData),
ParameterSortAs(ParameterSortAsData),
ParameterType(ParameterTypeData),
ParameterTz(ParameterTzData),
ParameterValue(ValueParameterData),
ParameterXName(XNameParameterData),
}
impl Parameter {
pub fn default(name: &str) -> Self {
match name.to_uppercase().as_str() {
ParameterName::ALTID => Self::ParameterAltId(ParameterAltIdData::default()),
ParameterName::CALSCALE => Self::ParameterCalScale(ParameterCalScaleData::default()),
ParameterName::CC => Self::ParameterCc(ParameterCcData::default()),
ParameterName::GEO => Self::ParameterGeo(ParameterGeoData::default()),
ParameterName::INDEX => Self::ParameterIndex(ParameterIndexData::default()),
ParameterName::LABEL => Self::ParameterLabel(ParameterLabelData::default()),
ParameterName::LANGUAGE => Self::ParameterLanguage(ParameterLanguageData::default()),
ParameterName::LEVEL => Self::ParameterLevel(ParameterLevelData::default()),
ParameterName::MEDIATYPE => Self::ParameterMediaType(ParameterMediaTypeData::default()),
ParameterName::PID => Self::ParameterPid(ParameterPidData::default()),
ParameterName::PREF => Self::ParameterPref(ParameterPrefData::default()),
ParameterName::SORTAS => Self::ParameterSortAs(ParameterSortAsData::default()),
ParameterName::TYPE => Self::ParameterType(ParameterTypeData::default()),
ParameterName::TZ => Self::ParameterTz(ParameterTzData::default()),
ParameterName::VALUE => Self::ParameterValue(ValueParameterData::default()),
_ => Self::ParameterXName(XNameParameterData::default(name)),
}
}
}
impl TryFrom<&str> for Parameter {
type Error = VcardError;
fn try_from(str: &str) -> Result<Self, Self::Error> {
let (_, (parameter_name, parameter_value)) = parse::parameter::parameter(str.as_bytes())?;
Parameter::try_from((utf8_to_string(parameter_name)?.as_str(), utf8_to_string(parameter_value)?.as_str()))
}
}
impl TryFrom<(&[u8], &[u8])> for Parameter {
type Error = VcardError;
fn try_from((parameter_name, parameter_value): (&[u8], &[u8])) -> Result<Self, Self::Error> {
Parameter::try_from((utf8_to_string(parameter_name)?.as_str(), utf8_to_string(parameter_value)?.as_str()))
}
}
impl TryFrom<(&str, &str)> for Parameter {
type Error = VcardError;
fn try_from((parameter_name, parameter_value): (&str, &str)) -> Result<Self, Self::Error> {
match parameter_name.to_uppercase().as_str() {
ParameterName::ALTID => Ok(Self::ParameterAltId(ParameterAltIdData::try_from(parameter_value)?)),
ParameterName::CALSCALE => Ok(Self::ParameterCalScale(ParameterCalScaleData::try_from(parameter_value)?)),
ParameterName::CC => Ok(Self::ParameterCc(ParameterCcData::try_from(parameter_value)?)),
ParameterName::GEO => Ok(Self::ParameterGeo(ParameterGeoData::try_from(parameter_value)?)),
ParameterName::INDEX => Ok(Self::ParameterIndex(ParameterIndexData::try_from(parameter_value)?)),
ParameterName::LABEL => Ok(Self::ParameterLabel(ParameterLabelData::try_from(parameter_value)?)),
ParameterName::LANGUAGE => Ok(Self::ParameterLanguage(ParameterLanguageData::try_from(parameter_value)?)),
ParameterName::LEVEL => Ok(Self::ParameterLevel(ParameterLevelData::try_from(parameter_value)?)),
ParameterName::MEDIATYPE => Ok(Self::ParameterMediaType(ParameterMediaTypeData::try_from(parameter_value)?)),
ParameterName::PID => Ok(Self::ParameterPid(ParameterPidData::try_from(parameter_value)?)),
ParameterName::PREF => Ok(Self::ParameterPref(ParameterPrefData::try_from(parameter_value)?)),
ParameterName::SORTAS => Ok(Self::ParameterSortAs(ParameterSortAsData::try_from(parameter_value)?)),
ParameterName::TYPE => Ok(Self::ParameterType(ParameterTypeData::try_from(parameter_value)?)),
ParameterName::TZ => Ok(Self::ParameterTz(ParameterTzData::try_from(parameter_value)?)),
ParameterName::VALUE => Ok(Self::ParameterValue(ValueParameterData::try_from(parameter_value)?)),
_ => Ok(Self::ParameterXName(XNameParameterData::try_from((parameter_name, parameter_value))?)),
}
}
}
impl Display for Parameter {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, ";{}={}", self.name(), self.get_value())
}
}
impl HasName for Parameter {
fn name(&self) -> &str {
match self {
Parameter::ParameterAltId(parameter) => parameter.name(),
Parameter::ParameterCalScale(parameter) => parameter.name(),
Parameter::ParameterCc(parameter) => parameter.name(),
Parameter::ParameterGeo(parameter) => parameter.name(),
Parameter::ParameterIndex(parameter) => parameter.name(),
Parameter::ParameterLabel(parameter) => parameter.name(),
Parameter::ParameterLanguage(parameter) => parameter.name(),
Parameter::ParameterLevel(parameter) => parameter.name(),
Parameter::ParameterMediaType(parameter) => parameter.name(),
Parameter::ParameterPid(parameter) => parameter.name(),
Parameter::ParameterPref(parameter) => parameter.name(),
Parameter::ParameterSortAs(parameter) => parameter.name(),
Parameter::ParameterType(parameter) => parameter.name(),
Parameter::ParameterTz(parameter) => parameter.name(),
Parameter::ParameterValue(parameter) => parameter.name(),
Parameter::ParameterXName(parameter) => parameter.name(),
}
}
}
impl HasValue for Parameter {
fn get_value(&self) -> &Value {
match self {
Parameter::ParameterAltId(parameter) => parameter.get_value(),
Parameter::ParameterCalScale(parameter) => parameter.get_value(),
Parameter::ParameterCc(parameter) => parameter.get_value(),
Parameter::ParameterGeo(parameter) => parameter.get_value(),
Parameter::ParameterIndex(parameter) => parameter.get_value(),
Parameter::ParameterLabel(parameter) => parameter.get_value(),
Parameter::ParameterLanguage(parameter) => parameter.get_value(),
Parameter::ParameterLevel(parameter) => parameter.get_value(),
Parameter::ParameterMediaType(parameter) => parameter.get_value(),
Parameter::ParameterPid(parameter) => parameter.get_value(),
Parameter::ParameterPref(parameter) => parameter.get_value(),
Parameter::ParameterSortAs(parameter) => parameter.get_value(),
Parameter::ParameterType(parameter) => parameter.get_value(),
Parameter::ParameterTz(parameter) => parameter.get_value(),
Parameter::ParameterValue(parameter) => parameter.get_value(),
Parameter::ParameterXName(parameter) => parameter.get_value(),
}
}
fn set_value(&mut self, value: Value) -> Result<(), VcardError> {
match self {
Parameter::ParameterAltId(parameter) => parameter.set_value(value),
Parameter::ParameterCalScale(parameter) => parameter.set_value(value),
Parameter::ParameterCc(parameter) => parameter.set_value(value),
Parameter::ParameterGeo(parameter) => parameter.set_value(value),
Parameter::ParameterIndex(parameter) => parameter.set_value(value),
Parameter::ParameterLabel(parameter) => parameter.set_value(value),
Parameter::ParameterLanguage(parameter) => parameter.set_value(value),
Parameter::ParameterLevel(parameter) => parameter.set_value(value),
Parameter::ParameterMediaType(parameter) => parameter.set_value(value),
Parameter::ParameterPid(parameter) => parameter.set_value(value),
Parameter::ParameterPref(parameter) => parameter.set_value(value),
Parameter::ParameterSortAs(parameter) => parameter.set_value(value),
Parameter::ParameterType(parameter) => parameter.set_value(value),
Parameter::ParameterTz(parameter) => parameter.set_value(value),
Parameter::ParameterValue(parameter) => parameter.set_value(value),
Parameter::ParameterXName(parameter) => parameter.set_value(value),
}
}
}
#[cfg(test)]
mod tests {
use crate::vcard::parameter::Parameter;
#[test]
fn parameter_try_from() {
assert!(Parameter::try_from(";ALTID=1").is_ok());
assert!(Parameter::try_from(";CALSCALE=gregorian").is_ok());
assert!(Parameter::try_from(";CC=us").is_ok());
assert!(Parameter::try_from(";GEO=\"geo:0.0,-0.0\"").is_ok());
assert!(Parameter::try_from(";INDEX=1").is_ok());
assert!(Parameter::try_from(";LABEL=WORK").is_ok());
assert!(Parameter::try_from(";LANGUAGE=en").is_ok());
assert!(Parameter::try_from(";LEVEL=1").is_ok());
assert!(Parameter::try_from(";MEDIATYPE=1").is_ok());
assert!(Parameter::try_from(";PID=1").is_ok());
assert!(Parameter::try_from(";PREF=1").is_ok());
assert!(Parameter::try_from(";SORT-AS=1").is_ok());
assert!(Parameter::try_from(";TYPE=1").is_ok());
assert!(Parameter::try_from(";TZ=1").is_ok());
assert!(Parameter::try_from(";VALUE=1").is_ok());
assert!(Parameter::try_from(";X-VALUE=1").is_ok());
}
}