use alloc::{borrow::Cow, vec::Vec};
use crate::{
param::VcardParamKind,
prop::VcardPropKind,
tree::{
codec::VcardCodec,
line::VcardLine,
param::lens::VcardParamLens,
prop::{cardinality::VcardPropCardinality, lens::VcardPropLens, spec::VcardPropSpec},
},
value::{VcardValueKind, n::VcardN},
version::VcardVersion,
};
pub struct N;
impl VcardPropLens for N {
type Target<'v> = VcardN<'v>;
type Cursor<'c, 'a>
= VcardNCursor<'c, 'a>
where
'a: 'c;
fn cursor<'c, 'a>(line: &'c mut VcardLine<'a>) -> VcardNCursor<'c, 'a> {
VcardNCursor { line }
}
}
impl VcardPropSpec for N {
const KIND: VcardPropKind = VcardPropKind::N;
fn cardinality(version: VcardVersion) -> VcardPropCardinality {
match version {
VcardVersion::V4_0 => VcardPropCardinality::AtMostOne,
_ => VcardPropCardinality::ExactlyOne,
}
}
fn allowed_values(_version: VcardVersion) -> &'static [VcardValueKind] {
&[VcardValueKind::N]
}
fn allowed_params(_version: VcardVersion) -> &'static [VcardParamKind] {
&[
VcardParamKind::SortAs,
VcardParamKind::Language,
VcardParamKind::Phonetic,
VcardParamKind::Script,
VcardParamKind::AltId,
VcardParamKind::Value,
]
}
}
pub struct VcardNCursor<'c, 'a> {
pub line: &'c mut VcardLine<'a>,
}
impl VcardNCursor<'_, '_> {
pub fn get(&self) -> VcardN<'_> {
VcardN::decode(&self.line.value)
}
pub fn family(&self) -> Vec<Cow<'_, str>> {
self.line.value.decode_at(0)
}
pub fn given(&self) -> Vec<Cow<'_, str>> {
self.line.value.decode_at(1)
}
pub fn additional(&self) -> Vec<Cow<'_, str>> {
self.line.value.decode_at(2)
}
pub fn prefixes(&self) -> Vec<Cow<'_, str>> {
self.line.value.decode_at(3)
}
pub fn suffixes(&self) -> Vec<Cow<'_, str>> {
self.line.value.decode_at(4)
}
pub fn set_family<S: AsRef<str>>(&mut self, values: &[S]) {
self.line.value.set_at(0, values);
}
pub fn set_given<S: AsRef<str>>(&mut self, values: &[S]) {
self.line.value.set_at(1, values);
}
pub fn set_additional<S: AsRef<str>>(&mut self, values: &[S]) {
self.line.value.set_at(2, values);
}
pub fn set_prefixes<S: AsRef<str>>(&mut self, values: &[S]) {
self.line.value.set_at(3, values);
}
pub fn set_suffixes<S: AsRef<str>>(&mut self, values: &[S]) {
self.line.value.set_at(4, values);
}
pub fn param<P: VcardParamLens>(&self) -> Option<P::Target<'_>> {
self.line.param::<P>()
}
}
#[cfg(test)]
mod tests {
use alloc::{borrow::Cow, string::ToString, vec};
use crate::tree::{cst::VcardCst, prop::n::N};
#[test]
fn names_components_and_sets_them_preserving_the_rest() {
let mut card =
VcardCst::parse("BEGIN:VCARD\r\nVERSION:4.0\r\nN:Doe;John;;;\r\nEND:VCARD\r\n")
.unwrap();
assert_eq!(
card.prop_mut::<N>().unwrap().family(),
vec![Cow::Borrowed("Doe")],
);
card.prop_mut::<N>().unwrap().set_given(&["Jane"]);
assert!(card.to_string().contains("N:Doe;Jane;;;\r\n"));
}
}