use crate::{
component::{
IcalComponentKind, available, daylight, participant, standard, valarm, vavailability,
vcalendar, vevent, vfreebusy, vjournal, vlocation, vresource, vtimezone, vtodo,
},
prop::IcalPropKind,
};
pub trait IcalComponentSpec {
const KIND: IcalComponentKind;
fn allowed_children() -> &'static [IcalComponentKind] {
&[]
}
fn required_props() -> &'static [IcalPropKind] {
&[]
}
}
#[allow(dead_code)]
pub(crate) struct IcalComponentSpecFns {
pub kind: IcalComponentKind,
pub allowed_children: fn() -> &'static [IcalComponentKind],
pub required_props: fn() -> &'static [IcalPropKind],
}
fn spec_fns<C: IcalComponentSpec>() -> IcalComponentSpecFns {
IcalComponentSpecFns {
kind: C::KIND,
allowed_children: C::allowed_children,
required_props: C::required_props,
}
}
pub(crate) fn component_spec(component: IcalComponentKind) -> IcalComponentSpecFns {
use IcalComponentKind::*;
match component {
VCalendar => spec_fns::<vcalendar::VCALENDAR>(),
VEvent => spec_fns::<vevent::VEVENT>(),
VTodo => spec_fns::<vtodo::VTODO>(),
VJournal => spec_fns::<vjournal::VJOURNAL>(),
VFreeBusy => spec_fns::<vfreebusy::VFREEBUSY>(),
VTimezone => spec_fns::<vtimezone::VTIMEZONE>(),
Standard => spec_fns::<standard::STANDARD>(),
Daylight => spec_fns::<daylight::DAYLIGHT>(),
VAlarm => spec_fns::<valarm::VALARM>(),
Participant => spec_fns::<participant::PARTICIPANT>(),
VLocation => spec_fns::<vlocation::VLOCATION>(),
VResource => spec_fns::<vresource::VRESOURCE>(),
VAvailability => spec_fns::<vavailability::VAVAILABILITY>(),
Available => spec_fns::<available::AVAILABLE>(),
}
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use crate::component::{IcalComponentKind, spec::component_spec};
#[test]
fn dispatches_every_component_onto_its_own_marker() {
for kind in IcalComponentKind::ALL {
assert_eq!(component_spec(kind).kind, kind, "{}", &*kind);
}
}
#[test]
fn no_component_requires_one_property_twice() {
for kind in IcalComponentKind::ALL {
let spec = component_spec(kind);
let mut required: Vec<&str> = (spec.required_props)().iter().map(|p| &**p).collect();
let count = required.len();
required.sort_unstable();
required.dedup();
assert_eq!(
required.len(),
count,
"{} requires a property twice",
&*kind
);
}
}
}