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::IResult;
13
use nom::Parser;
14

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

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

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

            
88
16
    Ok((input, fb_type))
89
16
}
90

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

            
122
30
    Ok((input, part_stat))
123
30
}
124

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

            
137
12
    Ok((input, related))
138
12
}
139

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

            
167
10
    Ok((input, rel_type))
168
10
}
169

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

            
190
15
    Ok((input, role))
191
15
}
192

            
193
15
pub fn param_value_rsvp<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], bool, E>
194
15
where
195
15
    E: ParseError<&'a [u8]> + From<Error<'a>>,
196
15
{
197
15
    let (input, rsvp) = alt((
198
15
        tag_no_case("TRUE").map(|_| true),
199
15
        tag_no_case("FALSE").map(|_| false),
200
15
    ))
201
15
    .parse(input)?;
202

            
203
15
    Ok((input, rsvp))
204
15
}
205

            
206
52
pub fn param_value_time_zone_id<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], (String, bool), E>
207
52
where
208
52
    E: ParseError<&'a [u8]> + From<Error<'a>>,
209
52
{
210
52
    let (input, (unique, tz_id)) =
211
52
        (opt(char('/')).map(|p| p.is_some()), param_text).parse(input)?;
212

            
213
52
    Ok((input, (read_string(tz_id, "TZID")?, unique)))
214
52
}
215

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

            
249
168
    Ok((input, value))
250
168
}