aetolia/parser/component/
alarm.rs1use crate::parser::property::{
2 prop_action, prop_attach, prop_attendee, prop_description, prop_duration, prop_iana,
3 prop_repeat, prop_summary, prop_trigger, prop_x,
4};
5use crate::parser::types::CalendarComponent;
6use crate::parser::types::ComponentProperty;
7use crate::parser::Error;
8use nom::branch::alt;
9use nom::bytes::streaming::tag;
10use nom::error::ParseError;
11use nom::multi::many0;
12use nom::{IResult, Parser};
13
14pub fn component_alarm<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E>
15where
16 E: ParseError<&'a [u8]>
17 + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
18 + From<Error<'a>>,
19{
20 let (input, (_, properties, _)) = (
21 tag("BEGIN:VALARM\r\n"),
22 many0(alt((
23 alt((
24 prop_action.map(ComponentProperty::Action),
25 prop_trigger.map(ComponentProperty::Trigger),
26 prop_duration.map(ComponentProperty::Duration),
27 prop_repeat.map(ComponentProperty::RepeatCount),
28 prop_attach.map(ComponentProperty::Attach),
29 prop_description.map(ComponentProperty::Description),
30 prop_summary.map(ComponentProperty::Summary),
31 prop_attendee.map(ComponentProperty::Attendee),
32 )),
33 prop_x.map(ComponentProperty::XProperty),
34 prop_iana.map(ComponentProperty::IanaProperty),
35 ))),
36 tag("END:VALARM\r\n"),
37 )
38 .parse(input)?;
39
40 Ok((input, CalendarComponent::Alarm { properties }))
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46 use crate::common::Value;
47 use crate::parser::types::{
48 Action, ActionProperty, AttachProperty, AttachValue, Date, DateTime, Duration,
49 DurationOrDateTime, DurationProperty, ParamValue, RepeatProperty, Time, TriggerProperty,
50 };
51 use crate::parser::Error;
52 use crate::test_utils::check_rem;
53
54 #[test]
55 fn test_component_alarm() {
56 let input = b"BEGIN:VALARM\r\n\
57TRIGGER;VALUE=DATE-TIME:19970317T133000Z\r\n\
58REPEAT:4\r\n\
59DURATION:PT15M\r\n\
60ACTION:AUDIO\r\n\
61ATTACH;FMTTYPE=audio/basic:ftp://example.com/pub/sounds/bell-01.aud\r\n\
62END:VALARM\r\n";
63
64 let (rem, component) = component_alarm::<Error>(input).unwrap();
65 check_rem(rem, 0);
66 match component {
67 CalendarComponent::Alarm { properties } => {
68 assert_eq!(5, properties.len());
69
70 assert_eq!(
71 properties[0],
72 ComponentProperty::Trigger(TriggerProperty {
73 params: vec![ParamValue::ValueType {
74 value: Value::DateTime,
75 },],
76 value: DurationOrDateTime::DateTime(DateTime {
77 date: Date {
78 year: 1997,
79 month: 3,
80 day: 17,
81 },
82 time: Time {
83 hour: 13,
84 minute: 30,
85 second: 0,
86 is_utc: true,
87 },
88 }),
89 })
90 );
91
92 assert_eq!(
93 properties[1],
94 ComponentProperty::RepeatCount(RepeatProperty {
95 other_params: vec![],
96 value: 4,
97 })
98 );
99
100 assert_eq!(
101 properties[2],
102 ComponentProperty::Duration(DurationProperty {
103 other_params: vec![],
104 value: Duration {
105 sign: 1,
106 minutes: Some(15),
107 ..Default::default()
108 },
109 })
110 );
111
112 assert_eq!(
113 properties[3],
114 ComponentProperty::Action(ActionProperty {
115 other_params: vec![],
116 value: Action::Audio,
117 })
118 );
119
120 assert_eq!(
121 properties[4],
122 ComponentProperty::Attach(AttachProperty {
123 params: vec![ParamValue::FormatType {
124 type_name: "audio".to_string(),
125 sub_type_name: "basic".to_string(),
126 },],
127 value: AttachValue::Uri(b"ftp://example.com/pub/sounds/bell-01.aud"),
128 })
129 );
130 }
131 _ => panic!("Unexpected component type"),
132 }
133 }
134}