1
use crate::parser::component::alarm::component_alarm;
2
use crate::parser::property::{
3
    prop_attach, prop_attendee, prop_categories, prop_classification, prop_comment, prop_contact,
4
    prop_date_time_created, prop_date_time_end, prop_date_time_stamp, prop_date_time_start,
5
    prop_description, prop_duration, prop_exception_date_times, prop_geographic_position,
6
    prop_iana, prop_last_modified, prop_location, prop_organizer, prop_priority,
7
    prop_recurrence_date_times, prop_recurrence_id, prop_recurrence_rule, prop_related_to,
8
    prop_request_status, prop_resources, prop_sequence, prop_status, prop_summary,
9
    prop_time_transparency, prop_unique_identifier, prop_url, prop_x,
10
};
11
use crate::parser::types::CalendarComponent;
12
use crate::parser::types::ComponentProperty;
13
use crate::parser::Error;
14
use nom::branch::alt;
15
use nom::bytes::streaming::tag;
16
use nom::combinator::cut;
17
use nom::error::ParseError;
18
use nom::multi::many0;
19
use nom::sequence::tuple;
20
use nom::{IResult, Parser};
21

            
22
471
pub fn component_event<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E>
23
471
where
24
471
    E: ParseError<&'a [u8]>
25
471
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
26
471
        + From<Error<'a>>,
27
471
{
28
471
    let (input, (_, properties, alarms, _)) = tuple((
29
471
        tag("BEGIN:VEVENT\r\n"),
30
471
        cut(many0(alt((
31
471
            alt((
32
471
                prop_date_time_stamp.map(ComponentProperty::DateTimeStamp),
33
471
                prop_unique_identifier.map(ComponentProperty::UniqueIdentifier),
34
471
                prop_date_time_start.map(ComponentProperty::DateTimeStart),
35
471
                prop_classification.map(ComponentProperty::Classification),
36
471
                prop_date_time_created.map(ComponentProperty::DateTimeCreated),
37
471
                prop_description.map(ComponentProperty::Description),
38
471
                prop_geographic_position.map(ComponentProperty::GeographicPosition),
39
471
                prop_last_modified.map(ComponentProperty::LastModified),
40
471
                prop_location.map(ComponentProperty::Location),
41
471
                prop_organizer.map(ComponentProperty::Organizer),
42
471
                prop_priority.map(ComponentProperty::Priority),
43
471
                prop_sequence.map(ComponentProperty::Sequence),
44
471
                prop_status.map(ComponentProperty::Status),
45
471
                prop_summary.map(ComponentProperty::Summary),
46
471
                prop_time_transparency.map(ComponentProperty::TimeTransparency),
47
471
            )),
48
471
            alt((
49
471
                prop_url.map(ComponentProperty::Url),
50
471
                prop_recurrence_id.map(ComponentProperty::RecurrenceId),
51
471
                prop_recurrence_rule.map(ComponentProperty::RecurrenceRule),
52
471
                prop_date_time_end.map(ComponentProperty::DateTimeEnd),
53
471
                prop_duration.map(ComponentProperty::Duration),
54
471
                prop_attach.map(ComponentProperty::Attach),
55
471
                prop_attendee.map(ComponentProperty::Attendee),
56
471
                prop_categories.map(ComponentProperty::Categories),
57
471
                prop_comment.map(ComponentProperty::Comment),
58
471
                prop_contact.map(ComponentProperty::Contact),
59
471
                prop_exception_date_times.map(ComponentProperty::ExceptionDateTimes),
60
471
                prop_request_status.map(ComponentProperty::RequestStatus),
61
471
                prop_related_to.map(ComponentProperty::RelatedTo),
62
471
                prop_resources.map(ComponentProperty::Resources),
63
471
                prop_recurrence_date_times.map(ComponentProperty::RecurrenceDateTimes),
64
471
            )),
65
471
            prop_x.map(ComponentProperty::XProperty),
66
471
            prop_iana.map(ComponentProperty::IanaProperty),
67
471
        )))),
68
471
        many0(component_alarm),
69
471
        tag("END:VEVENT\r\n"),
70
471
    ))(input)?;
71

            
72
135
    Ok((input, CalendarComponent::Event { properties, alarms }))
73
471
}
74

            
75
#[cfg(test)]
76
mod tests {
77
    use super::*;
78
    use crate::parser::types::{
79
        CategoriesProperty, Classification, ClassificationProperty, Date, DateOrDateTime, DateTime,
80
        DateTimeEndProperty, DateTimeStampProperty, DateTimeStartProperty, SummaryProperty, Time,
81
        UniqueIdentifierProperty,
82
    };
83
    use crate::parser::Error;
84
    use crate::test_utils::check_rem;
85

            
86
    #[test]
87
2
    fn test_component_event() {
88
2
        let input = b"BEGIN:VEVENT\r\n\
89
2
UID:19970901T130000Z-123401@example.com\r\n\
90
2
DTSTAMP:19970901T130000Z\r\n\
91
2
DTSTART:19970903T163000Z\r\n\
92
2
DTEND:19970903T190000Z\r\n\
93
2
SUMMARY:Annual Employee Review\r\n\
94
2
CLASS:PRIVATE\r\n\
95
2
CATEGORIES:BUSINESS,HUMAN RESOURCES\r\n\
96
2
END:VEVENT\r\n";
97
2

            
98
2
        let (rem, component) = component_event::<Error>(input).unwrap();
99
2
        check_rem(rem, 0);
100
2

            
101
2
        match component {
102
2
            CalendarComponent::Event { properties, .. } => {
103
2
                assert_eq!(properties.len(), 7);
104

            
105
2
                assert_eq!(
106
2
                    properties[0],
107
2
                    ComponentProperty::UniqueIdentifier(UniqueIdentifierProperty {
108
2
                        other_params: vec![],
109
2
                        value: b"19970901T130000Z-123401@example.com".to_vec(),
110
2
                    })
111
2
                );
112

            
113
2
                assert_eq!(
114
2
                    properties[1],
115
2
                    ComponentProperty::DateTimeStamp(DateTimeStampProperty {
116
2
                        other_params: vec![],
117
2
                        value: DateTime {
118
2
                            date: Date {
119
2
                                year: 1997,
120
2
                                month: 9,
121
2
                                day: 1,
122
2
                            },
123
2
                            time: Time {
124
2
                                hour: 13,
125
2
                                minute: 0,
126
2
                                second: 0,
127
2
                                is_utc: true,
128
2
                            },
129
2
                        },
130
2
                    })
131
2
                );
132

            
133
2
                assert_eq!(
134
2
                    properties[2],
135
2
                    ComponentProperty::DateTimeStart(DateTimeStartProperty {
136
2
                        params: vec![],
137
2
                        value: DateOrDateTime::DateTime(DateTime {
138
2
                            date: Date {
139
2
                                year: 1997,
140
2
                                month: 9,
141
2
                                day: 3,
142
2
                            },
143
2
                            time: Time {
144
2
                                hour: 16,
145
2
                                minute: 30,
146
2
                                second: 0,
147
2
                                is_utc: true,
148
2
                            },
149
2
                        }),
150
2
                    })
151
2
                );
152

            
153
2
                assert_eq!(
154
2
                    properties[3],
155
2
                    ComponentProperty::DateTimeEnd(DateTimeEndProperty {
156
2
                        params: vec![],
157
2
                        value: DateOrDateTime::DateTime(DateTime {
158
2
                            date: Date {
159
2
                                year: 1997,
160
2
                                month: 9,
161
2
                                day: 3,
162
2
                            },
163
2
                            time: Time {
164
2
                                hour: 19,
165
2
                                minute: 0,
166
2
                                second: 0,
167
2
                                is_utc: true,
168
2
                            },
169
2
                        }),
170
2
                    })
171
2
                );
172

            
173
2
                assert_eq!(
174
2
                    properties[4],
175
2
                    ComponentProperty::Summary(SummaryProperty {
176
2
                        params: vec![],
177
2
                        value: b"Annual Employee Review".to_vec(),
178
2
                    })
179
2
                );
180

            
181
2
                assert_eq!(
182
2
                    properties[5],
183
2
                    ComponentProperty::Classification(ClassificationProperty {
184
2
                        other_params: vec![],
185
2
                        value: Classification::Private,
186
2
                    })
187
2
                );
188

            
189
2
                assert_eq!(
190
2
                    properties[6],
191
2
                    ComponentProperty::Categories(CategoriesProperty {
192
2
                        params: vec![],
193
2
                        value: vec![b"BUSINESS".to_vec(), b"HUMAN RESOURCES".to_vec()],
194
2
                    })
195
2
                );
196
            }
197
            _ => panic!("Unexpected component type"),
198
        }
199
2
    }
200
}