1
use 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
};
5
use crate::parser::types::CalendarComponent;
6
use crate::parser::types::ComponentProperty;
7
use crate::parser::Error;
8
use nom::branch::alt;
9
use nom::bytes::streaming::tag;
10
use nom::error::ParseError;
11
use nom::multi::many0;
12
use nom::sequence::tuple;
13
use nom::{IResult, Parser};
14

            
15
205
pub fn component_alarm<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E>
16
205
where
17
205
    E: ParseError<&'a [u8]>
18
205
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
19
205
        + From<Error<'a>>,
20
205
{
21
205
    let (input, (_, properties, _)) = tuple((
22
205
        tag("BEGIN:VALARM\r\n"),
23
205
        many0(alt((
24
205
            alt((
25
205
                prop_action.map(ComponentProperty::Action),
26
205
                prop_trigger.map(ComponentProperty::Trigger),
27
205
                prop_duration.map(ComponentProperty::Duration),
28
205
                prop_repeat.map(ComponentProperty::RepeatCount),
29
205
                prop_attach.map(ComponentProperty::Attach),
30
205
                prop_description.map(ComponentProperty::Description),
31
205
                prop_summary.map(ComponentProperty::Summary),
32
205
                prop_attendee.map(ComponentProperty::Attendee),
33
205
            )),
34
205
            prop_x.map(ComponentProperty::XProperty),
35
205
            prop_iana.map(ComponentProperty::IanaProperty),
36
205
        ))),
37
205
        tag("END:VALARM\r\n"),
38
205
    ))(input)?;
39

            
40
48
    Ok((input, CalendarComponent::Alarm { properties }))
41
205
}
42

            
43
#[cfg(test)]
44
mod 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
2
    fn test_component_alarm() {
56
2
        let input = b"BEGIN:VALARM\r\n\
57
2
TRIGGER;VALUE=DATE-TIME:19970317T133000Z\r\n\
58
2
REPEAT:4\r\n\
59
2
DURATION:PT15M\r\n\
60
2
ACTION:AUDIO\r\n\
61
2
ATTACH;FMTTYPE=audio/basic:ftp://example.com/pub/sounds/bell-01.aud\r\n\
62
2
END:VALARM\r\n";
63
2

            
64
2
        let (rem, component) = component_alarm::<Error>(input).unwrap();
65
2
        check_rem(rem, 0);
66
2
        match component {
67
2
            CalendarComponent::Alarm { properties } => {
68
2
                assert_eq!(5, properties.len());
69

            
70
2
                assert_eq!(
71
2
                    properties[0],
72
2
                    ComponentProperty::Trigger(TriggerProperty {
73
2
                        params: vec![ParamValue::ValueType {
74
2
                            value: Value::DateTime,
75
2
                        },],
76
2
                        value: DurationOrDateTime::DateTime(DateTime {
77
2
                            date: Date {
78
2
                                year: 1997,
79
2
                                month: 3,
80
2
                                day: 17,
81
2
                            },
82
2
                            time: Time {
83
2
                                hour: 13,
84
2
                                minute: 30,
85
2
                                second: 0,
86
2
                                is_utc: true,
87
2
                            },
88
2
                        }),
89
2
                    })
90
2
                );
91

            
92
2
                assert_eq!(
93
2
                    properties[1],
94
2
                    ComponentProperty::RepeatCount(RepeatProperty {
95
2
                        other_params: vec![],
96
2
                        value: 4,
97
2
                    })
98
2
                );
99

            
100
2
                assert_eq!(
101
2
                    properties[2],
102
2
                    ComponentProperty::Duration(DurationProperty {
103
2
                        other_params: vec![],
104
2
                        value: Duration {
105
2
                            sign: 1,
106
2
                            minutes: Some(15),
107
2
                            ..Default::default()
108
2
                        },
109
2
                    })
110
2
                );
111

            
112
2
                assert_eq!(
113
2
                    properties[3],
114
2
                    ComponentProperty::Action(ActionProperty {
115
2
                        other_params: vec![],
116
2
                        value: Action::Audio,
117
2
                    })
118
2
                );
119

            
120
2
                assert_eq!(
121
2
                    properties[4],
122
2
                    ComponentProperty::Attach(AttachProperty {
123
2
                        params: vec![ParamValue::FormatType {
124
2
                            type_name: "audio".to_string(),
125
2
                            sub_type_name: "basic".to_string(),
126
2
                        },],
127
2
                        value: AttachValue::Uri(b"ftp://example.com/pub/sounds/bell-01.aud"),
128
2
                    })
129
2
                );
130
            }
131
            _ => panic!("Unexpected component type"),
132
        }
133
2
    }
134
}