1
pub(crate) mod value;
2

            
3
use crate::common::Range;
4
use crate::parser::language_tag::language_tag;
5
use crate::parser::property::uri::param_value_uri;
6
use crate::parser::types::ParamValue;
7
use crate::parser::{param_name, param_value, read_string, reg_name, x_name, Error};
8
use nom::branch::alt;
9
use nom::bytes::complete::tag_no_case;
10
use nom::bytes::streaming::tag;
11
use nom::character::streaming::char;
12
use nom::combinator::{cut, map_res, recognize};
13
use nom::error::ParseError;
14
use nom::multi::{many0, separated_list1};
15
use nom::sequence::{delimited, separated_pair, tuple};
16
use nom::{IResult, Parser};
17
pub use value::*;
18

            
19
/// Recognize a list of parameters.
20
876
pub fn property_params<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec<ParamValue<'a>>, E>
21
876
where
22
876
    E: ParseError<&'a [u8]>
23
876
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
24
876
        + From<Error<'a>>,
25
876
{
26
1270
    many0(tuple((char(';'), cut(property_param))).map(|(_, p)| p)).parse(input)
27
876
}
28

            
29
/// Recognize a single parameter.
30
863
pub fn property_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
31
863
where
32
863
    E: ParseError<&'a [u8]>
33
863
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
34
863
        + From<Error<'a>>,
35
863
{
36
863
    alt((known_param, iana_param, x_param))(input)
37
863
}
38

            
39
/// Parse an ALTREP param
40
///
41
/// RFC 5545, section 3.2.1
42
937
fn param_alternate_text_representation<'a, E>(
43
937
    input: &'a [u8],
44
937
) -> IResult<&'a [u8], ParamValue<'a>, E>
45
937
where
46
937
    E: ParseError<&'a [u8]>
47
937
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
48
937
        + From<Error<'a>>,
49
937
{
50
937
    let (input, (_, _, uri)) = tuple((
51
937
        tag_no_case("ALTREP"),
52
937
        char('='),
53
937
        cut(delimited(char('"'), recognize(param_value_uri), char('"'))),
54
937
    ))(input)?;
55

            
56
46
    Ok((input, ParamValue::AltRep { uri }))
57
937
}
58

            
59
/// Parse a CN param
60
///
61
/// RFC 5545, section 3.2.2
62
891
fn param_common_name<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
63
891
where
64
891
    E: ParseError<&'a [u8]> + From<Error<'a>>,
65
891
{
66
891
    let (input, (_, _, value)) = tuple((tag_no_case("CN"), char('='), cut(param_value)))(input)?;
67

            
68
    Ok((
69
26
        input,
70
26
        ParamValue::CommonName {
71
26
            name: read_string(value, "common_name")?,
72
        },
73
    ))
74
891
}
75

            
76
/// Parse a CUTYPE param
77
///
78
/// RFC 5545, section 3.2.3
79
865
fn param_calendar_user_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
80
865
where
81
865
    E: ParseError<&'a [u8]>
82
865
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
83
865
        + From<Error<'a>>,
84
865
{
85
865
    let (input, (_, _, cu_type)) = tuple((
86
865
        tag_no_case("CUTYPE"),
87
865
        char('='),
88
865
        cut(param_value_calendar_user_type),
89
865
    ))(input)?;
90

            
91
25
    Ok((input, ParamValue::CalendarUserType { cu_type }))
92
865
}
93

            
94
/// Parse a DELEGATED-FROM param
95
///
96
/// RFC 5545, section 3.2.4
97
840
fn param_delegated_from<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
98
840
where
99
840
    E: ParseError<&'a [u8]>
100
840
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
101
840
        + From<Error<'a>>,
102
840
{
103
840
    let (input, (_, _, delegators)) = tuple((
104
840
        tag_no_case("DELEGATED-FROM"),
105
840
        char('='),
106
840
        cut(param_value_delegated_from),
107
840
    ))(input)?;
108

            
109
14
    Ok((input, ParamValue::DelegatedFrom { delegators }))
110
840
}
111

            
112
14
pub(crate) fn param_value_delegated_from<'a, E>(
113
14
    input: &'a [u8],
114
14
) -> IResult<&'a [u8], Vec<&'a [u8]>, E>
115
14
where
116
14
    E: ParseError<&'a [u8]>
117
14
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
118
14
        + From<Error<'a>>,
119
14
{
120
14
    separated_list1(
121
14
        char(','),
122
14
        delimited(char('"'), recognize(param_value_uri), char('"')),
123
14
    )(input)
124
14
}
125

            
126
/// Parse a DELEGATED-TO param
127
///
128
/// RFC 5545, section 3.2.5
129
826
fn param_delegated_to<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
130
826
where
131
826
    E: ParseError<&'a [u8]>
132
826
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
133
826
        + From<Error<'a>>,
134
826
{
135
826
    let (input, (_, _, delegates)) = tuple((
136
826
        tag_no_case("DELEGATED-TO"),
137
826
        char('='),
138
826
        cut(separated_list1(
139
826
            char(','),
140
826
            delimited(char('"'), recognize(param_value_uri), char('"')),
141
826
        )),
142
826
    ))(input)?;
143

            
144
12
    Ok((input, ParamValue::DelegatedTo { delegates }))
145
826
}
146

            
147
/// Parse a DIR param
148
///
149
/// RFC 5545, section 3.2.6
150
814
fn param_dir<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
151
814
where
152
814
    E: ParseError<&'a [u8]>
153
814
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
154
814
        + From<Error<'a>>,
155
814
{
156
814
    let (input, (_, _, uri)) = tuple((
157
814
        tag_no_case("DIR"),
158
814
        char('='),
159
814
        cut(delimited(char('"'), recognize(param_value_uri), char('"'))),
160
814
    ))(input)?;
161

            
162
20
    Ok((input, ParamValue::DirectoryEntryReference { uri }))
163
814
}
164

            
165
/// Parse an ENCODING param
166
///
167
/// RFC 5545, section 3.2.7
168
794
fn param_encoding<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
169
794
where
170
794
    E: ParseError<&'a [u8]>
171
794
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
172
794
        + From<Error<'a>>,
173
794
{
174
794
    let (input, (_, _, encoding)) = tuple((
175
794
        tag_no_case("ENCODING"),
176
794
        char('='),
177
794
        cut(param_value_encoding),
178
794
    ))(input)?;
179

            
180
18
    Ok((input, ParamValue::Encoding { encoding }))
181
794
}
182

            
183
/// Parse an FMTTYPE param
184
///
185
/// RFC 5545, section 3.2.8
186
776
fn param_format_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
187
776
where
188
776
    E: ParseError<&'a [u8]>
189
776
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
190
776
        + From<Error<'a>>,
191
776
{
192
776
    let (input, (_, _, (type_name, sub_type_name))) = tuple((
193
776
        tag_no_case("FMTTYPE"),
194
776
        char('='),
195
776
        cut(separated_pair(
196
776
            map_res(reg_name, |t| read_string(t, "FMTTYPE type-name")),
197
776
            char('/'),
198
776
            map_res(reg_name, |t| read_string(t, "FMTTYPE subtype-name")),
199
776
        )),
200
776
    ))(input)?;
201

            
202
18
    Ok((
203
18
        input,
204
18
        ParamValue::FormatType {
205
18
            type_name,
206
18
            sub_type_name,
207
18
        },
208
18
    ))
209
776
}
210

            
211
/// Parse an FBTYPE param
212
///
213
/// RFC 5545, section 3.2.9
214
758
fn param_free_busy_time_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
215
758
where
216
758
    E: ParseError<&'a [u8]>
217
758
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
218
758
        + From<Error<'a>>,
219
758
{
220
758
    let (input, (_, _, fb_type)) = tuple((
221
758
        tag_no_case("FBTYPE"),
222
758
        char('='),
223
758
        cut(param_value_free_busy_time_type),
224
758
    ))(input)?;
225

            
226
16
    Ok((input, ParamValue::FreeBusyTimeType { fb_type }))
227
758
}
228

            
229
/// Parse a LANGUAGE param
230
///
231
/// RFC 5545, section 3.2.10
232
742
fn param_language<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
233
742
where
234
742
    E: ParseError<&'a [u8]>
235
742
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
236
742
        + From<Error<'a>>,
237
742
{
238
76
    let (input, (_, _, language)) =
239
742
        tuple((tag_no_case("LANGUAGE"), char('='), cut(language_tag)))(input)?;
240

            
241
76
    Ok((input, ParamValue::Language { language }))
242
742
}
243

            
244
/// Parse a MEMBER param
245
///
246
/// RFC 5545, section 3.2.11
247
666
fn param_member<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
248
666
where
249
666
    E: ParseError<&'a [u8]>
250
666
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
251
666
        + From<Error<'a>>,
252
666
{
253
666
    let (input, (_, _, members)) = tuple((
254
666
        tag_no_case("MEMBER"),
255
666
        char('='),
256
666
        cut(separated_list1(
257
666
            char(','),
258
666
            delimited(char('"'), recognize(param_value_uri), char('"')),
259
666
        )),
260
666
    ))(input)?;
261

            
262
12
    Ok((input, ParamValue::Members { members }))
263
666
}
264

            
265
/// Parse a PARTSTAT param
266
///
267
/// RFC 5545, section 3.2.12
268
654
fn param_participation_status<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
269
654
where
270
654
    E: ParseError<&'a [u8]>
271
654
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
272
654
        + From<Error<'a>>,
273
654
{
274
654
    let (input, (_, _, status)) = tuple((
275
654
        tag_no_case("PARTSTAT"),
276
654
        char('='),
277
654
        cut(param_value_participation_status),
278
654
    ))(input)?;
279

            
280
16
    Ok((input, ParamValue::ParticipationStatus { status }))
281
654
}
282

            
283
/// Parse a RANGE param
284
///
285
/// RFC 5545, section 3.2.13
286
638
fn param_range<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
287
638
where
288
638
    E: ParseError<&'a [u8]>
289
638
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
290
638
        + From<Error<'a>>,
291
638
{
292
12
    let (input, (_, _, _)) =
293
638
        tuple((tag_no_case("RANGE"), char('='), cut(tag("THISANDFUTURE"))))(input)?;
294

            
295
12
    Ok((
296
12
        input,
297
12
        ParamValue::Range {
298
12
            range: Range::ThisAndFuture,
299
12
        },
300
12
    ))
301
638
}
302

            
303
/// Parse a RELATED param
304
///
305
/// RFC 5545, section 3.2.14
306
626
fn param_related<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
307
626
where
308
626
    E: ParseError<&'a [u8]>
309
626
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
310
626
        + From<Error<'a>>,
311
626
{
312
626
    let (input, (_, _, related)) = tuple((
313
626
        tag_no_case("RELATED"),
314
626
        char('='),
315
626
        cut(param_value_trigger_relationship),
316
626
    ))(input)?;
317

            
318
12
    Ok((input, ParamValue::Related { related }))
319
626
}
320

            
321
/// Parse a RELTYPE param
322
///
323
/// RFC 5545, section 3.2.15
324
614
fn param_relationship_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
325
614
where
326
614
    E: ParseError<&'a [u8]>
327
614
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
328
614
        + From<Error<'a>>,
329
614
{
330
614
    let (input, (_, _, relationship)) = tuple((
331
614
        tag_no_case("RELTYPE"),
332
614
        char('='),
333
614
        cut(param_value_relationship_type),
334
614
    ))(input)?;
335

            
336
10
    Ok((input, ParamValue::RelationshipType { relationship }))
337
614
}
338

            
339
/// Parse a ROLE param
340
///
341
/// RFC 5545, section 3.2.16
342
604
fn param_role<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
343
604
where
344
604
    E: ParseError<&'a [u8]>
345
604
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
346
604
        + From<Error<'a>>,
347
604
{
348
15
    let (input, (_, _, role)) =
349
604
        tuple((tag_no_case("ROLE"), char('='), cut(param_value_role)))(input)?;
350

            
351
15
    Ok((input, ParamValue::Role { role }))
352
604
}
353

            
354
/// Parse an RSVP param
355
///
356
/// RFC 5545, section 3.2.17
357
589
fn param_rsvp<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
358
589
where
359
589
    E: ParseError<&'a [u8]>
360
589
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
361
589
        + From<Error<'a>>,
362
589
{
363
15
    let (input, (_, _, rsvp)) =
364
589
        tuple((tag_no_case("RSVP"), char('='), cut(param_value_rsvp)))(input)?;
365

            
366
15
    Ok((input, ParamValue::Rsvp { rsvp }))
367
589
}
368

            
369
/// Parse an SENT-BY param
370
///
371
/// RFC 5545, section 3.2.18
372
574
fn param_sent_by<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
373
574
where
374
574
    E: ParseError<&'a [u8]>
375
574
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
376
574
        + From<Error<'a>>,
377
574
{
378
574
    let (input, (_, _, address)) = tuple((
379
574
        tag_no_case("SENT-BY"),
380
574
        char('='),
381
574
        cut(delimited(char('"'), recognize(param_value_uri), char('"'))),
382
574
    ))(input)?;
383

            
384
22
    Ok((input, ParamValue::SentBy { address }))
385
574
}
386

            
387
/// Parse a TZID param
388
///
389
/// RFC 5545, section 3.2.19
390
552
fn param_time_zone_identifier<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
391
552
where
392
552
    E: ParseError<&'a [u8]>
393
552
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
394
552
        + From<Error<'a>>,
395
552
{
396
552
    let (input, (_, _, (tz_id, unique))) = tuple((
397
552
        tag_no_case("TZID"),
398
552
        char('='),
399
552
        cut(param_value_time_zone_id),
400
552
    ))(input)?;
401

            
402
52
    Ok((input, ParamValue::TimeZoneId { tz_id, unique }))
403
552
}
404

            
405
/// Parse a VALUE param
406
///
407
/// RFC 5545, section 3.2.20
408
500
fn param_value_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
409
500
where
410
500
    E: ParseError<&'a [u8]>
411
500
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
412
500
        + From<Error<'a>>,
413
500
{
414
168
    let (input, (_, _, value)) =
415
500
        tuple((tag_no_case("VALUE"), char('='), cut(param_value_value_type)))(input)?;
416

            
417
168
    Ok((input, ParamValue::ValueType { value }))
418
500
}
419

            
420
937
fn known_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
421
937
where
422
937
    E: ParseError<&'a [u8]>
423
937
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
424
937
        + From<Error<'a>>,
425
937
{
426
937
    let (input, param_value) = alt((
427
937
        param_alternate_text_representation,
428
937
        param_common_name,
429
937
        param_calendar_user_type,
430
937
        param_delegated_from,
431
937
        param_delegated_to,
432
937
        param_dir,
433
937
        param_encoding,
434
937
        param_format_type,
435
937
        param_free_busy_time_type,
436
937
        param_language,
437
937
        param_member,
438
937
        param_participation_status,
439
937
        param_range,
440
937
        param_related,
441
937
        param_relationship_type,
442
937
        param_role,
443
937
        param_rsvp,
444
937
        param_sent_by,
445
937
        param_time_zone_identifier,
446
937
        param_value_type,
447
937
    ))(input)?;
448

            
449
605
    Ok((input, param_value))
450
937
}
451

            
452
1531
pub fn other_params<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec<ParamValue<'a>>, E>
453
1531
where
454
1531
    E: ParseError<&'a [u8]> + From<Error<'a>>,
455
1531
{
456
1621
    many0(tuple((char(';'), other_param)).map(|(_, p)| p)).parse(input)
457
1531
}
458

            
459
260
pub fn other_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
460
260
where
461
260
    E: ParseError<&'a [u8]> + From<Error<'a>>,
462
260
{
463
260
    alt((iana_param, x_param))(input)
464
260
}
465

            
466
592
fn iana_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
467
592
where
468
592
    E: ParseError<&'a [u8]> + From<Error<'a>>,
469
592
{
470
592
    let (input, (name, _, values)) = tuple((
471
592
        param_name,
472
592
        char('='),
473
592
        separated_list1(char(','), param_value),
474
592
    ))(input)?;
475

            
476
    Ok((
477
592
        input,
478
592
        match values.len() {
479
592
            1 => ParamValue::Other {
480
592
                name,
481
592
                value: values[0],
482
592
            },
483
            _ => ParamValue::Others { name, values },
484
        },
485
    ))
486
592
}
487

            
488
fn x_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
489
where
490
    E: ParseError<&'a [u8]> + From<Error<'a>>,
491
{
492
    let (input, (name, _, values)) =
493
        tuple((x_name, char('='), separated_list1(char(','), param_value)))(input)?;
494

            
495
    Ok((
496
        input,
497
        match values.len() {
498
            1 => ParamValue::Other {
499
                name,
500
                value: values[0],
501
            },
502
            _ => ParamValue::Others { name, values },
503
        },
504
    ))
505
}
506

            
507
#[cfg(test)]
508
mod tests {
509
    use super::*;
510
    use crate::common::LanguageTag;
511
    use crate::common::{
512
        CalendarUserType, Encoding, FreeBusyTimeType, ParticipationStatusUnknown, RelationshipType,
513
        Role, TriggerRelationship, Value,
514
    };
515
    use crate::test_utils::check_rem;
516

            
517
    #[test]
518
2
    fn param_altrep() {
519
2
        let (rem, param) =
520
2
            known_param::<Error>(b"ALTREP=\"http://example.com/calendar\";").unwrap();
521
2
        check_rem(rem, 1);
522
2
        assert_eq!(
523
2
            ParamValue::AltRep {
524
2
                uri: b"http://example.com/calendar"
525
2
            },
526
2
            param
527
2
        );
528
2
    }
529

            
530
    #[test]
531
2
    fn param_cn() {
532
2
        let (rem, param) = known_param::<Error>(b"CN=\"John Smith\";").unwrap();
533
2
        check_rem(rem, 1);
534
2
        assert_eq!(
535
2
            ParamValue::CommonName {
536
2
                name: "John Smith".to_string()
537
2
            },
538
2
            param
539
2
        );
540
2
    }
541

            
542
    #[test]
543
2
    fn param_cn_not_quoted() {
544
2
        let (rem, param) = known_param::<Error>(b"CN=Danny;").unwrap();
545
2
        check_rem(rem, 1);
546
2
        assert_eq!(
547
2
            ParamValue::CommonName {
548
2
                name: "Danny".to_string()
549
2
            },
550
2
            param
551
2
        );
552
2
    }
553

            
554
    #[test]
555
2
    fn param_cu_type_individual() {
556
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=INDIVIDUAL;").unwrap();
557
2
        check_rem(rem, 1);
558
2
        assert_eq!(
559
2
            ParamValue::CalendarUserType {
560
2
                cu_type: CalendarUserType::Individual
561
2
            },
562
2
            param
563
2
        );
564
2
    }
565

            
566
    #[test]
567
2
    fn param_cu_type_group() {
568
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=GROUP;").unwrap();
569
2
        check_rem(rem, 1);
570
2
        assert_eq!(
571
2
            ParamValue::CalendarUserType {
572
2
                cu_type: CalendarUserType::Group
573
2
            },
574
2
            param
575
2
        );
576
2
    }
577

            
578
    #[test]
579
2
    fn param_cu_type_resource() {
580
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=RESOURCE;").unwrap();
581
2
        check_rem(rem, 1);
582
2
        assert_eq!(
583
2
            ParamValue::CalendarUserType {
584
2
                cu_type: CalendarUserType::Resource
585
2
            },
586
2
            param
587
2
        );
588
2
    }
589

            
590
    #[test]
591
2
    fn param_cu_type_room() {
592
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=ROOM;").unwrap();
593
2
        check_rem(rem, 1);
594
2
        assert_eq!(
595
2
            ParamValue::CalendarUserType {
596
2
                cu_type: CalendarUserType::Room
597
2
            },
598
2
            param
599
2
        );
600
2
    }
601

            
602
    #[test]
603
2
    fn param_cu_type_unknown() {
604
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=UNKNOWN;").unwrap();
605
2
        check_rem(rem, 1);
606
2
        assert_eq!(
607
2
            ParamValue::CalendarUserType {
608
2
                cu_type: CalendarUserType::Unknown
609
2
            },
610
2
            param
611
2
        );
612
2
    }
613

            
614
    #[test]
615
2
    fn param_cu_type_x_name() {
616
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=X-esl-special;").unwrap();
617
2
        check_rem(rem, 1);
618
2
        assert_eq!(
619
2
            ParamValue::CalendarUserType {
620
2
                cu_type: CalendarUserType::XName("X-esl-special".to_string())
621
2
            },
622
2
            param
623
2
        );
624
2
    }
625

            
626
    #[test]
627
2
    fn param_cu_type_iana_token() {
628
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=other;").unwrap();
629
2
        check_rem(rem, 1);
630
2
        assert_eq!(
631
2
            ParamValue::CalendarUserType {
632
2
                cu_type: CalendarUserType::IanaToken("other".to_string())
633
2
            },
634
2
            param
635
2
        );
636
2
    }
637

            
638
    #[test]
639
2
    fn param_delegated_from() {
640
2
        let (rem, param) =
641
2
            known_param::<Error>(b"DELEGATED-FROM=\"mailto:jsmith@example.com\";").unwrap();
642
2
        check_rem(rem, 1);
643
2
        assert_eq!(
644
2
            ParamValue::DelegatedFrom {
645
2
                delegators: vec![b"mailto:jsmith@example.com"],
646
2
            },
647
2
            param
648
2
        );
649
2
    }
650

            
651
    #[test]
652
2
    fn param_delegated_from_multi() {
653
2
        let (rem, param) = known_param::<Error>(
654
2
            b"DELEGATED-FROM=\"mailto:jsmith@example.com\",\"mailto:danny@example.com\";",
655
2
        )
656
2
        .unwrap();
657
2
        check_rem(rem, 1);
658
2
        assert_eq!(
659
2
            ParamValue::DelegatedFrom {
660
2
                delegators: vec![b"mailto:jsmith@example.com", b"mailto:danny@example.com",],
661
2
            },
662
2
            param
663
2
        );
664
2
    }
665

            
666
    #[test]
667
2
    fn param_delegated_to() {
668
2
        let (rem, param) =
669
2
            known_param::<Error>(b"DELEGATED-TO=\"mailto:jsmith@example.com\";").unwrap();
670
2
        check_rem(rem, 1);
671
2
        assert_eq!(
672
2
            ParamValue::DelegatedTo {
673
2
                delegates: vec![b"mailto:jsmith@example.com"],
674
2
            },
675
2
            param
676
2
        );
677
2
    }
678

            
679
    #[test]
680
2
    fn param_delegated_to_multi() {
681
2
        let (rem, param) = known_param::<Error>(
682
2
            b"DELEGATED-TO=\"mailto:jsmith@example.com\",\"mailto:danny@example.com\";",
683
2
        )
684
2
        .unwrap();
685
2
        check_rem(rem, 1);
686
2
        assert_eq!(
687
2
            ParamValue::DelegatedTo {
688
2
                delegates: vec![b"mailto:jsmith@example.com", b"mailto:danny@example.com",],
689
2
            },
690
2
            param
691
2
        );
692
2
    }
693

            
694
    #[test]
695
2
    fn param_dir() {
696
2
        let (rem, param) = known_param::<Error>(
697
2
            b"DIR=\"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)\";",
698
2
        )
699
2
        .unwrap();
700
2
        check_rem(rem, 1);
701
2
        assert_eq!(
702
2
            ParamValue::DirectoryEntryReference {
703
2
                uri: b"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)"
704
2
            },
705
2
            param
706
2
        );
707
2
    }
708

            
709
    #[test]
710
2
    fn param_encoding_8bit() {
711
2
        let (rem, param) = known_param::<Error>(b"ENCODING=8BIT;").unwrap();
712
2
        check_rem(rem, 1);
713
2
        assert_eq!(
714
2
            ParamValue::Encoding {
715
2
                encoding: Encoding::EightBit
716
2
            },
717
2
            param
718
2
        );
719
2
    }
720

            
721
    #[test]
722
2
    fn param_encoding_base64() {
723
2
        let (rem, param) = known_param::<Error>(b"ENCODING=BASE64;").unwrap();
724
2
        check_rem(rem, 1);
725
2
        assert_eq!(
726
2
            ParamValue::Encoding {
727
2
                encoding: Encoding::Base64
728
2
            },
729
2
            param
730
2
        );
731
2
    }
732

            
733
    #[test]
734
2
    fn param_fmt_type() {
735
2
        let (rem, param) = known_param::<Error>(b"FMTTYPE=application/msword;").unwrap();
736
2
        check_rem(rem, 1);
737
2
        assert_eq!(
738
2
            ParamValue::FormatType {
739
2
                type_name: "application".to_string(),
740
2
                sub_type_name: "msword".to_string(),
741
2
            },
742
2
            param
743
2
        );
744
2
    }
745

            
746
    #[test]
747
2
    fn param_fb_type_free() {
748
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=FREE;").unwrap();
749
2
        check_rem(rem, 1);
750
2
        assert_eq!(
751
2
            ParamValue::FreeBusyTimeType {
752
2
                fb_type: FreeBusyTimeType::Free
753
2
            },
754
2
            param
755
2
        );
756
2
    }
757

            
758
    #[test]
759
2
    fn param_fb_type_busy() {
760
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=BUSY;").unwrap();
761
2
        check_rem(rem, 1);
762
2
        assert_eq!(
763
2
            ParamValue::FreeBusyTimeType {
764
2
                fb_type: FreeBusyTimeType::Busy
765
2
            },
766
2
            param
767
2
        );
768
2
    }
769

            
770
    #[test]
771
2
    fn param_fb_type_busy_unavailable() {
772
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=BUSY-UNAVAILABLE;").unwrap();
773
2
        check_rem(rem, 1);
774
2
        assert_eq!(
775
2
            ParamValue::FreeBusyTimeType {
776
2
                fb_type: FreeBusyTimeType::BusyUnavailable
777
2
            },
778
2
            param
779
2
        );
780
2
    }
781

            
782
    #[test]
783
2
    fn param_fb_type_busy_tentative() {
784
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=BUSY-TENTATIVE;").unwrap();
785
2
        check_rem(rem, 1);
786
2
        assert_eq!(
787
2
            ParamValue::FreeBusyTimeType {
788
2
                fb_type: FreeBusyTimeType::BusyTentative
789
2
            },
790
2
            param
791
2
        );
792
2
    }
793

            
794
    #[test]
795
2
    fn param_language() {
796
2
        let (rem, param) = known_param::<Error>(b"LANGUAGE=en-US;").unwrap();
797
2
        check_rem(rem, 1);
798
2
        assert_eq!(
799
2
            ParamValue::Language {
800
2
                language: LanguageTag {
801
2
                    language: "en".to_string(),
802
2
                    region: Some("US".to_string()),
803
2
                    ..Default::default()
804
2
                }
805
2
            },
806
2
            param
807
2
        );
808
2
    }
809

            
810
    #[test]
811
2
    fn param_member() {
812
2
        let (rem, param) =
813
2
            known_param::<Error>(b"MEMBER=\"mailto:ietf-calsch@example.org\";").unwrap();
814
2
        check_rem(rem, 1);
815
2
        assert_eq!(
816
2
            ParamValue::Members {
817
2
                members: vec![b"mailto:ietf-calsch@example.org"],
818
2
            },
819
2
            param
820
2
        );
821
2
    }
822

            
823
    #[test]
824
2
    fn param_member_multi() {
825
2
        let (rem, param) = known_param::<Error>(
826
2
            b"MEMBER=\"mailto:projectA@example.com\",\"mailto:projectB@example.com\";",
827
2
        )
828
2
        .unwrap();
829
2
        check_rem(rem, 1);
830
2
        assert_eq!(
831
2
            ParamValue::Members {
832
2
                members: vec![
833
2
                    b"mailto:projectA@example.com",
834
2
                    b"mailto:projectB@example.com",
835
2
                ],
836
2
            },
837
2
            param
838
2
        );
839
2
    }
840

            
841
    #[test]
842
2
    fn param_part_stat_declined() {
843
2
        let (rem, param) = known_param::<Error>(b"PARTSTAT=DECLINED;").unwrap();
844
2
        check_rem(rem, 1);
845
2
        assert_eq!(
846
2
            ParamValue::ParticipationStatus {
847
2
                status: ParticipationStatusUnknown::Declined
848
2
            },
849
2
            param
850
2
        );
851
2
    }
852

            
853
    #[test]
854
2
    fn param_range() {
855
2
        let (rem, param) = known_param::<Error>(b"RANGE=THISANDFUTURE;").unwrap();
856
2
        check_rem(rem, 1);
857
2
        assert_eq!(
858
2
            ParamValue::Range {
859
2
                range: Range::ThisAndFuture
860
2
            },
861
2
            param
862
2
        );
863
2
    }
864

            
865
    #[test]
866
2
    fn param_related_start() {
867
2
        let (rem, param) = known_param::<Error>(b"RELATED=START;").unwrap();
868
2
        check_rem(rem, 1);
869
2
        assert_eq!(
870
2
            ParamValue::Related {
871
2
                related: TriggerRelationship::Start
872
2
            },
873
2
            param
874
2
        );
875
2
    }
876

            
877
    #[test]
878
2
    fn param_related_end() {
879
2
        let (rem, param) = known_param::<Error>(b"RELATED=END;").unwrap();
880
2
        check_rem(rem, 1);
881
2
        assert_eq!(
882
2
            ParamValue::Related {
883
2
                related: TriggerRelationship::End
884
2
            },
885
2
            param
886
2
        );
887
2
    }
888

            
889
    #[test]
890
2
    fn param_rel_type() {
891
2
        let (rem, param) = known_param::<Error>(b"RELTYPE=SIBLING;").unwrap();
892
2
        check_rem(rem, 1);
893
2
        assert_eq!(
894
2
            ParamValue::RelationshipType {
895
2
                relationship: RelationshipType::Sibling
896
2
            },
897
2
            param
898
2
        );
899
2
    }
900

            
901
    #[test]
902
2
    fn param_role() {
903
2
        let (rem, param) = known_param::<Error>(b"ROLE=CHAIR;").unwrap();
904
2
        check_rem(rem, 1);
905
2
        assert_eq!(ParamValue::Role { role: Role::Chair }, param);
906
2
    }
907

            
908
    #[test]
909
2
    fn param_rsvp_true() {
910
2
        let (rem, param) = known_param::<Error>(b"RSVP=TRUE;").unwrap();
911
2
        check_rem(rem, 1);
912
2
        assert_eq!(ParamValue::Rsvp { rsvp: true }, param);
913
2
    }
914

            
915
    #[test]
916
2
    fn param_rsvp_false() {
917
2
        let (rem, param) = known_param::<Error>(b"RSVP=FALSE;").unwrap();
918
2
        check_rem(rem, 1);
919
2
        assert_eq!(ParamValue::Rsvp { rsvp: false }, param);
920
2
    }
921

            
922
    #[test]
923
2
    fn param_sent_by() {
924
2
        let (rem, param) = known_param::<Error>(b"SENT-BY=\"mailto:sray@example.com\";").unwrap();
925
2
        check_rem(rem, 1);
926
2
        assert_eq!(
927
2
            ParamValue::SentBy {
928
2
                address: b"mailto:sray@example.com"
929
2
            },
930
2
            param
931
2
        );
932
2
    }
933

            
934
    #[test]
935
2
    fn param_tz_id() {
936
2
        let (rem, param) = known_param::<Error>(b"TZID=America/New_York;").unwrap();
937
2
        check_rem(rem, 1);
938
2
        assert_eq!(
939
2
            ParamValue::TimeZoneId {
940
2
                tz_id: "America/New_York".to_string(),
941
2
                unique: false,
942
2
            },
943
2
            param
944
2
        );
945
2
    }
946

            
947
    #[test]
948
2
    fn param_tz_id_unique() {
949
2
        let (rem, param) = known_param::<Error>(b"TZID=/America/New_York;").unwrap();
950
2
        check_rem(rem, 1);
951
2
        assert_eq!(
952
2
            ParamValue::TimeZoneId {
953
2
                tz_id: "America/New_York".to_string(),
954
2
                unique: true,
955
2
            },
956
2
            param
957
2
        );
958
2
    }
959

            
960
    #[test]
961
2
    fn param_value_binary() {
962
2
        let (rem, param) = known_param::<Error>(b"VALUE=BINARY;").unwrap();
963
2
        check_rem(rem, 1);
964
2
        assert_eq!(
965
2
            ParamValue::ValueType {
966
2
                value: Value::Binary
967
2
            },
968
2
            param
969
2
        );
970
2
    }
971
}