1
use crate::common::ParticipationStatusUnknown;
2
use crate::common::{
3
    CalendarUserType, Encoding, FreeBusyTimeType, RelationshipType, Role, TriggerRelationship,
4
    Value,
5
};
6
use crate::parser::{iana_token, param_text, read_string, x_name, Error};
7
use nom::branch::alt;
8
use nom::bytes::complete::tag_no_case;
9
use nom::character::streaming::char;
10
use nom::combinator::{map_res, opt};
11
use nom::error::ParseError;
12
use nom::sequence::tuple;
13
use nom::IResult;
14
use nom::Parser;
15

            
16
25
pub fn param_value_calendar_user_type<'a, E>(
17
25
    input: &'a [u8],
18
25
) -> IResult<&'a [u8], CalendarUserType, E>
19
25
where
20
25
    E: ParseError<&'a [u8]>
21
25
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
22
25
        + From<Error<'a>>,
23
25
{
24
25
    let (input, cu_type) = alt((
25
25
        tag_no_case("INDIVIDUAL").map(|_| CalendarUserType::Individual),
26
25
        tag_no_case("GROUP").map(|_| CalendarUserType::Group),
27
25
        tag_no_case("RESOURCE").map(|_| CalendarUserType::Resource),
28
25
        tag_no_case("ROOM").map(|_| CalendarUserType::Room),
29
25
        tag_no_case("UNKNOWN").map(|_| CalendarUserType::Unknown),
30
25
        map_res(x_name, |x_name| {
31
2
            Ok(CalendarUserType::XName(read_string(
32
2
                x_name,
33
2
                "CUTYPE x-name",
34
2
            )?))
35
25
        }),
36
25
        map_res(iana_token, |iana_token| {
37
2
            Ok(CalendarUserType::IanaToken(read_string(
38
2
                iana_token,
39
2
                "CUTYPE iana-token",
40
2
            )?))
41
25
        }),
42
25
    ))(input)?;
43

            
44
25
    Ok((input, cu_type))
45
25
}
46

            
47
18
pub fn param_value_encoding<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Encoding, E>
48
18
where
49
18
    E: ParseError<&'a [u8]> + From<Error<'a>>,
50
18
{
51
18
    let (input, encoding) = alt((
52
18
        tag_no_case("8BIT").map(|_| Encoding::EightBit),
53
18
        tag_no_case("BASE64").map(|_| Encoding::Base64),
54
18
    ))(input)?;
55

            
56
18
    Ok((input, encoding))
57
18
}
58

            
59
16
pub fn param_value_free_busy_time_type<'a, E>(
60
16
    input: &'a [u8],
61
16
) -> IResult<&'a [u8], FreeBusyTimeType, E>
62
16
where
63
16
    E: ParseError<&'a [u8]>
64
16
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
65
16
        + From<Error<'a>>,
66
16
{
67
16
    let (input, fb_type) = alt((
68
16
        tag_no_case("FREE").map(|_| FreeBusyTimeType::Free),
69
16
        tag_no_case("BUSY-UNAVAILABLE").map(|_| FreeBusyTimeType::BusyUnavailable),
70
16
        tag_no_case("BUSY-TENTATIVE").map(|_| FreeBusyTimeType::BusyTentative),
71
16
        tag_no_case("BUSY").map(|_| FreeBusyTimeType::Busy),
72
16
        map_res(x_name, |x_name| {
73
            Ok(FreeBusyTimeType::XName(read_string(
74
                x_name,
75
                "FBTYPE x-name",
76
            )?))
77
16
        }),
78
16
        map_res(iana_token, |iana_token| {
79
            Ok(FreeBusyTimeType::IanaToken(read_string(
80
                iana_token,
81
                "FBTYPE iana-token",
82
            )?))
83
16
        }),
84
16
    ))(input)?;
85

            
86
16
    Ok((input, fb_type))
87
16
}
88

            
89
30
pub fn param_value_participation_status<'a, E>(
90
30
    input: &'a [u8],
91
30
) -> IResult<&'a [u8], ParticipationStatusUnknown, E>
92
30
where
93
30
    E: ParseError<&'a [u8]>
94
30
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
95
30
        + From<Error<'a>>,
96
30
{
97
30
    let (input, part_stat) = alt((
98
30
        tag_no_case("NEEDS-ACTION").map(|_| ParticipationStatusUnknown::NeedsAction),
99
30
        tag_no_case("ACCEPTED").map(|_| ParticipationStatusUnknown::Accepted),
100
30
        tag_no_case("DECLINED").map(|_| ParticipationStatusUnknown::Declined),
101
30
        tag_no_case("TENTATIVE").map(|_| ParticipationStatusUnknown::Tentative),
102
30
        tag_no_case("DELEGATED").map(|_| ParticipationStatusUnknown::Delegated),
103
30
        tag_no_case("COMPLETED").map(|_| ParticipationStatusUnknown::Completed),
104
30
        tag_no_case("IN-PROCESS").map(|_| ParticipationStatusUnknown::InProcess),
105
30
        map_res(x_name, |x_name| {
106
            Ok(ParticipationStatusUnknown::XName(read_string(
107
                x_name,
108
                "PARTSTAT x-name",
109
            )?))
110
30
        }),
111
30
        map_res(iana_token, |iana_token| {
112
            Ok(ParticipationStatusUnknown::IanaToken(read_string(
113
                iana_token,
114
                "PARTSTAT iana-token",
115
            )?))
116
30
        }),
117
30
    ))(input)?;
118

            
119
30
    Ok((input, part_stat))
120
30
}
121

            
122
12
pub fn param_value_trigger_relationship<'a, E>(
123
12
    input: &'a [u8],
124
12
) -> IResult<&'a [u8], TriggerRelationship, E>
125
12
where
126
12
    E: ParseError<&'a [u8]> + From<Error<'a>>,
127
12
{
128
12
    let (input, related) = alt((
129
12
        tag_no_case("START").map(|_| TriggerRelationship::Start),
130
12
        tag_no_case("END").map(|_| TriggerRelationship::End),
131
12
    ))(input)?;
132

            
133
12
    Ok((input, related))
134
12
}
135

            
136
10
pub fn param_value_relationship_type<'a, E>(
137
10
    input: &'a [u8],
138
10
) -> IResult<&'a [u8], RelationshipType, E>
139
10
where
140
10
    E: ParseError<&'a [u8]>
141
10
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
142
10
        + From<Error<'a>>,
143
10
{
144
10
    let (input, rel_type) = alt((
145
10
        tag_no_case("PARENT").map(|_| RelationshipType::Parent),
146
10
        tag_no_case("CHILD").map(|_| RelationshipType::Child),
147
10
        tag_no_case("SIBLING").map(|_| RelationshipType::Sibling),
148
10
        map_res(x_name, |x_name| {
149
            Ok(RelationshipType::XName(read_string(
150
                x_name,
151
                "RELTYPE x-name",
152
            )?))
153
10
        }),
154
10
        map_res(iana_token, |iana_token| {
155
            Ok(RelationshipType::IanaToken(read_string(
156
                iana_token,
157
                "RELTYPE iana-token",
158
            )?))
159
10
        }),
160
10
    ))(input)?;
161

            
162
10
    Ok((input, rel_type))
163
10
}
164

            
165
15
pub fn param_value_role<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Role, E>
166
15
where
167
15
    E: ParseError<&'a [u8]>
168
15
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
169
15
        + From<Error<'a>>,
170
15
{
171
15
    let (input, role) = alt((
172
15
        tag_no_case("CHAIR").map(|_| Role::Chair),
173
15
        tag_no_case("REQ-PARTICIPANT").map(|_| Role::RequiredParticipant),
174
15
        tag_no_case("OPT-PARTICIPANT").map(|_| Role::OptionalParticipant),
175
15
        tag_no_case("NON-PARTICIPANT").map(|_| Role::NonParticipant),
176
15
        map_res(x_name, |x_name| {
177
            Ok(Role::XName(read_string(x_name, "ROLE x-name")?))
178
15
        }),
179
15
        map_res(iana_token, |iana_token| {
180
2
            Ok(Role::IanaToken(read_string(iana_token, "ROLE iana-token")?))
181
15
        }),
182
15
    ))(input)?;
183

            
184
15
    Ok((input, role))
185
15
}
186

            
187
15
pub fn param_value_rsvp<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], bool, E>
188
15
where
189
15
    E: ParseError<&'a [u8]> + From<Error<'a>>,
190
15
{
191
15
    let (input, rsvp) = alt((
192
15
        tag_no_case("TRUE").map(|_| true),
193
15
        tag_no_case("FALSE").map(|_| false),
194
15
    ))(input)?;
195

            
196
15
    Ok((input, rsvp))
197
15
}
198

            
199
52
pub fn param_value_time_zone_id<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], (String, bool), E>
200
52
where
201
52
    E: ParseError<&'a [u8]> + From<Error<'a>>,
202
52
{
203
52
    let (input, (unique, tz_id)) = tuple((opt(char('/')).map(|p| p.is_some()), param_text))(input)?;
204

            
205
52
    Ok((input, (read_string(tz_id, "TZID")?, unique)))
206
52
}
207

            
208
168
pub fn param_value_value_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Value, E>
209
168
where
210
168
    E: ParseError<&'a [u8]>
211
168
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
212
168
        + From<Error<'a>>,
213
168
{
214
168
    let (input, value) = alt((
215
168
        tag_no_case("BINARY").map(|_| Value::Binary),
216
168
        tag_no_case("BOOLEAN").map(|_| Value::Boolean),
217
168
        tag_no_case("CAL-ADDRESS").map(|_| Value::CalendarAddress),
218
168
        tag_no_case("DATE-TIME").map(|_| Value::DateTime),
219
168
        tag_no_case("DATE").map(|_| Value::Date),
220
168
        tag_no_case("DURATION").map(|_| Value::Duration),
221
168
        tag_no_case("FLOAT").map(|_| Value::Float),
222
168
        tag_no_case("INTEGER").map(|_| Value::Integer),
223
168
        tag_no_case("PERIOD").map(|_| Value::Period),
224
168
        tag_no_case("RECUR").map(|_| Value::Recurrence),
225
168
        tag_no_case("TEXT").map(|_| Value::Text),
226
168
        tag_no_case("TIME").map(|_| Value::Time),
227
168
        tag_no_case("URI").map(|_| Value::Uri),
228
168
        tag_no_case("UTC-OFFSET").map(|_| Value::UtcOffset),
229
168
        map_res(x_name, |x_name| {
230
            Ok(Value::XName(read_string(x_name, "VALUE x-name")?))
231
168
        }),
232
168
        map_res(iana_token, |iana_token| {
233
            Ok(Value::IanaToken(read_string(
234
                iana_token,
235
                "VALUE iana-token",
236
            )?))
237
168
        }),
238
168
    ))(input)?;
239

            
240
168
    Ok((input, value))
241
168
}