1
use crate::parser::property::{
2
    prop_attendee, prop_comment, prop_contact, prop_date_time_end, prop_date_time_stamp,
3
    prop_date_time_start, prop_free_busy_time, prop_iana, prop_organizer, prop_request_status,
4
    prop_unique_identifier, prop_url, prop_x,
5
};
6
use crate::parser::types::CalendarComponent;
7
use crate::parser::types::ComponentProperty;
8
use crate::parser::Error;
9
use nom::branch::alt;
10
use nom::bytes::streaming::tag;
11
use nom::combinator::cut;
12
use nom::error::ParseError;
13
use nom::multi::many0;
14
use nom::sequence::tuple;
15
use nom::IResult;
16
use nom::Parser;
17

            
18
308
pub fn component_free_busy<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], CalendarComponent<'a>, E>
19
308
where
20
308
    E: ParseError<&'a [u8]>
21
308
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
22
308
        + From<Error<'a>>,
23
308
{
24
308
    let (input, (_, properties, _)) = tuple((
25
308
        tag("BEGIN:VFREEBUSY\r\n"),
26
308
        cut(many0(alt((
27
308
            alt((
28
308
                prop_date_time_stamp.map(ComponentProperty::DateTimeStamp),
29
308
                prop_unique_identifier.map(ComponentProperty::UniqueIdentifier),
30
308
                prop_contact.map(ComponentProperty::Contact),
31
308
                prop_date_time_start.map(ComponentProperty::DateTimeStart),
32
308
                prop_date_time_end.map(ComponentProperty::DateTimeEnd),
33
308
                prop_organizer.map(ComponentProperty::Organizer),
34
308
                prop_url.map(ComponentProperty::Url),
35
308
                prop_attendee.map(ComponentProperty::Attendee),
36
308
                prop_comment.map(ComponentProperty::Comment),
37
308
                prop_free_busy_time.map(ComponentProperty::FreeBusyTime),
38
308
                prop_request_status.map(ComponentProperty::RequestStatus),
39
308
            )),
40
308
            prop_x.map(ComponentProperty::XProperty),
41
308
            prop_iana.map(ComponentProperty::IanaProperty),
42
308
        )))),
43
308
        tag("END:VFREEBUSY\r\n"),
44
308
    ))(input)?;
45

            
46
14
    Ok((input, CalendarComponent::FreeBusy { properties }))
47
308
}
48

            
49
#[cfg(test)]
50
mod tests {
51
    use super::*;
52
    use crate::parser::types::{
53
        AttendeeProperty, Date, DateOrDateTime, DateTime, DateTimeEndProperty,
54
        DateTimeStampProperty, DateTimeStartProperty, OrganizerProperty, Time,
55
        UniqueIdentifierProperty,
56
    };
57
    use crate::parser::Error;
58
    use crate::test_utils::check_rem;
59

            
60
    #[test]
61
2
    fn test_component_free_busy() {
62
2
        let input = b"BEGIN:VFREEBUSY\r\n\
63
2
UID:19970901T082949Z-FA43EF@example.com\r\n\
64
2
ORGANIZER:mailto:jane_doe@example.com\r\n\
65
2
ATTENDEE:mailto:john_public@example.com\r\n\
66
2
DTSTART:19971015T050000Z\r\n\
67
2
DTEND:19971016T050000Z\r\n\
68
2
DTSTAMP:19970901T083000Z\r\n\
69
2
END:VFREEBUSY\r\n";
70
2

            
71
2
        let (rem, component) = component_free_busy::<Error>(input).unwrap();
72
2
        check_rem(rem, 0);
73
2
        match component {
74
2
            CalendarComponent::FreeBusy { properties } => {
75
2
                assert_eq!(properties.len(), 6);
76

            
77
2
                assert_eq!(
78
2
                    properties[0],
79
2
                    ComponentProperty::UniqueIdentifier(UniqueIdentifierProperty {
80
2
                        other_params: vec![],
81
2
                        value: b"19970901T082949Z-FA43EF@example.com".to_vec(),
82
2
                    })
83
2
                );
84

            
85
2
                assert_eq!(
86
2
                    properties[1],
87
2
                    ComponentProperty::Organizer(OrganizerProperty {
88
2
                        params: vec![],
89
2
                        value: b"mailto:jane_doe@example.com",
90
2
                    })
91
2
                );
92

            
93
2
                assert_eq!(
94
2
                    properties[2],
95
2
                    ComponentProperty::Attendee(AttendeeProperty {
96
2
                        params: vec![],
97
2
                        value: b"mailto:john_public@example.com",
98
2
                    })
99
2
                );
100

            
101
2
                assert_eq!(
102
2
                    properties[3],
103
2
                    ComponentProperty::DateTimeStart(DateTimeStartProperty {
104
2
                        params: vec![],
105
2
                        value: DateOrDateTime::DateTime(DateTime {
106
2
                            date: Date {
107
2
                                year: 1997,
108
2
                                month: 10,
109
2
                                day: 15,
110
2
                            },
111
2
                            time: Time {
112
2
                                hour: 5,
113
2
                                minute: 0,
114
2
                                second: 0,
115
2
                                is_utc: true,
116
2
                            },
117
2
                        }),
118
2
                    })
119
2
                );
120

            
121
2
                assert_eq!(
122
2
                    properties[4],
123
2
                    ComponentProperty::DateTimeEnd(DateTimeEndProperty {
124
2
                        params: vec![],
125
2
                        value: DateOrDateTime::DateTime(DateTime {
126
2
                            date: Date {
127
2
                                year: 1997,
128
2
                                month: 10,
129
2
                                day: 16,
130
2
                            },
131
2
                            time: Time {
132
2
                                hour: 5,
133
2
                                minute: 0,
134
2
                                second: 0,
135
2
                                is_utc: true,
136
2
                            },
137
2
                        }),
138
2
                    })
139
2
                );
140

            
141
2
                assert_eq!(
142
2
                    properties[5],
143
2
                    ComponentProperty::DateTimeStamp(DateTimeStampProperty {
144
2
                        other_params: vec![],
145
2
                        value: DateTime {
146
2
                            date: Date {
147
2
                                year: 1997,
148
2
                                month: 9,
149
2
                                day: 1,
150
2
                            },
151
2
                            time: Time {
152
2
                                hour: 8,
153
2
                                minute: 30,
154
2
                                second: 0,
155
2
                                is_utc: true,
156
2
                            },
157
2
                        },
158
2
                    })
159
2
                );
160
            }
161
            _ => panic!("Unexpected component type"),
162
        }
163
2
    }
164
}