aetolia/parser/component/
alarm.rs

1use 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}