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};
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((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)).parse(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)) = (
51
937
        tag_no_case("ALTREP"),
52
937
        char('='),
53
937
        cut(delimited(char('"'), recognize(param_value_uri), char('"'))),
54
937
    )
55
937
        .parse(input)?;
56

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

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

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

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

            
93
25
    Ok((input, ParamValue::CalendarUserType { cu_type }))
94
865
}
95

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

            
112
14
    Ok((input, ParamValue::DelegatedFrom { delegators }))
113
840
}
114

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

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

            
149
12
    Ok((input, ParamValue::DelegatedTo { delegates }))
150
826
}
151

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

            
168
20
    Ok((input, ParamValue::DirectoryEntryReference { uri }))
169
814
}
170

            
171
/// Parse an ENCODING param
172
///
173
/// RFC 5545, section 3.2.7
174
794
fn param_encoding<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
175
794
where
176
794
    E: ParseError<&'a [u8]>
177
794
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
178
794
        + From<Error<'a>>,
179
794
{
180
794
    let (input, (_, _, encoding)) = (
181
794
        tag_no_case("ENCODING"),
182
794
        char('='),
183
794
        cut(param_value_encoding),
184
794
    )
185
794
        .parse(input)?;
186

            
187
18
    Ok((input, ParamValue::Encoding { encoding }))
188
794
}
189

            
190
/// Parse an FMTTYPE param
191
///
192
/// RFC 5545, section 3.2.8
193
776
fn param_format_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
194
776
where
195
776
    E: ParseError<&'a [u8]>
196
776
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
197
776
        + From<Error<'a>>,
198
776
{
199
776
    let (input, (_, _, (type_name, sub_type_name))) = (
200
776
        tag_no_case("FMTTYPE"),
201
776
        char('='),
202
776
        cut(separated_pair(
203
776
            map_res(reg_name, |t| read_string(t, "FMTTYPE type-name")),
204
776
            char('/'),
205
776
            map_res(reg_name, |t| read_string(t, "FMTTYPE subtype-name")),
206
776
        )),
207
776
    )
208
776
        .parse(input)?;
209

            
210
18
    Ok((
211
18
        input,
212
18
        ParamValue::FormatType {
213
18
            type_name,
214
18
            sub_type_name,
215
18
        },
216
18
    ))
217
776
}
218

            
219
/// Parse an FBTYPE param
220
///
221
/// RFC 5545, section 3.2.9
222
758
fn param_free_busy_time_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
223
758
where
224
758
    E: ParseError<&'a [u8]>
225
758
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
226
758
        + From<Error<'a>>,
227
758
{
228
758
    let (input, (_, _, fb_type)) = (
229
758
        tag_no_case("FBTYPE"),
230
758
        char('='),
231
758
        cut(param_value_free_busy_time_type),
232
758
    )
233
758
        .parse(input)?;
234

            
235
16
    Ok((input, ParamValue::FreeBusyTimeType { fb_type }))
236
758
}
237

            
238
/// Parse a LANGUAGE param
239
///
240
/// RFC 5545, section 3.2.10
241
742
fn param_language<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
242
742
where
243
742
    E: ParseError<&'a [u8]>
244
742
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
245
742
        + From<Error<'a>>,
246
742
{
247
76
    let (input, (_, _, language)) =
248
742
        (tag_no_case("LANGUAGE"), char('='), cut(language_tag)).parse(input)?;
249

            
250
76
    Ok((input, ParamValue::Language { language }))
251
742
}
252

            
253
/// Parse a MEMBER param
254
///
255
/// RFC 5545, section 3.2.11
256
666
fn param_member<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
257
666
where
258
666
    E: ParseError<&'a [u8]>
259
666
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
260
666
        + From<Error<'a>>,
261
666
{
262
666
    let (input, (_, _, members)) = (
263
666
        tag_no_case("MEMBER"),
264
666
        char('='),
265
666
        cut(separated_list1(
266
666
            char(','),
267
666
            delimited(char('"'), recognize(param_value_uri), char('"')),
268
666
        )),
269
666
    )
270
666
        .parse(input)?;
271

            
272
12
    Ok((input, ParamValue::Members { members }))
273
666
}
274

            
275
/// Parse a PARTSTAT param
276
///
277
/// RFC 5545, section 3.2.12
278
654
fn param_participation_status<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
279
654
where
280
654
    E: ParseError<&'a [u8]>
281
654
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
282
654
        + From<Error<'a>>,
283
654
{
284
654
    let (input, (_, _, status)) = (
285
654
        tag_no_case("PARTSTAT"),
286
654
        char('='),
287
654
        cut(param_value_participation_status),
288
654
    )
289
654
        .parse(input)?;
290

            
291
16
    Ok((input, ParamValue::ParticipationStatus { status }))
292
654
}
293

            
294
/// Parse a RANGE param
295
///
296
/// RFC 5545, section 3.2.13
297
638
fn param_range<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
298
638
where
299
638
    E: ParseError<&'a [u8]>
300
638
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
301
638
        + From<Error<'a>>,
302
638
{
303
12
    let (input, (_, _, _)) =
304
638
        (tag_no_case("RANGE"), char('='), cut(tag("THISANDFUTURE"))).parse(input)?;
305

            
306
12
    Ok((
307
12
        input,
308
12
        ParamValue::Range {
309
12
            range: Range::ThisAndFuture,
310
12
        },
311
12
    ))
312
638
}
313

            
314
/// Parse a RELATED param
315
///
316
/// RFC 5545, section 3.2.14
317
626
fn param_related<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
318
626
where
319
626
    E: ParseError<&'a [u8]>
320
626
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
321
626
        + From<Error<'a>>,
322
626
{
323
626
    let (input, (_, _, related)) = (
324
626
        tag_no_case("RELATED"),
325
626
        char('='),
326
626
        cut(param_value_trigger_relationship),
327
626
    )
328
626
        .parse(input)?;
329

            
330
12
    Ok((input, ParamValue::Related { related }))
331
626
}
332

            
333
/// Parse a RELTYPE param
334
///
335
/// RFC 5545, section 3.2.15
336
614
fn param_relationship_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
337
614
where
338
614
    E: ParseError<&'a [u8]>
339
614
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
340
614
        + From<Error<'a>>,
341
614
{
342
614
    let (input, (_, _, relationship)) = (
343
614
        tag_no_case("RELTYPE"),
344
614
        char('='),
345
614
        cut(param_value_relationship_type),
346
614
    )
347
614
        .parse(input)?;
348

            
349
10
    Ok((input, ParamValue::RelationshipType { relationship }))
350
614
}
351

            
352
/// Parse a ROLE param
353
///
354
/// RFC 5545, section 3.2.16
355
604
fn param_role<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
356
604
where
357
604
    E: ParseError<&'a [u8]>
358
604
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
359
604
        + From<Error<'a>>,
360
604
{
361
15
    let (input, (_, _, role)) =
362
604
        (tag_no_case("ROLE"), char('='), cut(param_value_role)).parse(input)?;
363

            
364
15
    Ok((input, ParamValue::Role { role }))
365
604
}
366

            
367
/// Parse an RSVP param
368
///
369
/// RFC 5545, section 3.2.17
370
589
fn param_rsvp<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
371
589
where
372
589
    E: ParseError<&'a [u8]>
373
589
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
374
589
        + From<Error<'a>>,
375
589
{
376
15
    let (input, (_, _, rsvp)) =
377
589
        (tag_no_case("RSVP"), char('='), cut(param_value_rsvp)).parse(input)?;
378

            
379
15
    Ok((input, ParamValue::Rsvp { rsvp }))
380
589
}
381

            
382
/// Parse an SENT-BY param
383
///
384
/// RFC 5545, section 3.2.18
385
574
fn param_sent_by<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
386
574
where
387
574
    E: ParseError<&'a [u8]>
388
574
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
389
574
        + From<Error<'a>>,
390
574
{
391
574
    let (input, (_, _, address)) = (
392
574
        tag_no_case("SENT-BY"),
393
574
        char('='),
394
574
        cut(delimited(char('"'), recognize(param_value_uri), char('"'))),
395
574
    )
396
574
        .parse(input)?;
397

            
398
22
    Ok((input, ParamValue::SentBy { address }))
399
574
}
400

            
401
/// Parse a TZID param
402
///
403
/// RFC 5545, section 3.2.19
404
552
fn param_time_zone_identifier<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
405
552
where
406
552
    E: ParseError<&'a [u8]>
407
552
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
408
552
        + From<Error<'a>>,
409
552
{
410
552
    let (input, (_, _, (tz_id, unique))) = (
411
552
        tag_no_case("TZID"),
412
552
        char('='),
413
552
        cut(param_value_time_zone_id),
414
552
    )
415
552
        .parse(input)?;
416

            
417
52
    Ok((input, ParamValue::TimeZoneId { tz_id, unique }))
418
552
}
419

            
420
/// Parse a VALUE param
421
///
422
/// RFC 5545, section 3.2.20
423
500
fn param_value_type<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
424
500
where
425
500
    E: ParseError<&'a [u8]>
426
500
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
427
500
        + From<Error<'a>>,
428
500
{
429
168
    let (input, (_, _, value)) =
430
500
        (tag_no_case("VALUE"), char('='), cut(param_value_value_type)).parse(input)?;
431

            
432
168
    Ok((input, ParamValue::ValueType { value }))
433
500
}
434

            
435
937
fn known_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
436
937
where
437
937
    E: ParseError<&'a [u8]>
438
937
        + nom::error::FromExternalError<&'a [u8], nom::Err<E>>
439
937
        + From<Error<'a>>,
440
937
{
441
937
    let (input, param_value) = alt((
442
937
        param_alternate_text_representation,
443
937
        param_common_name,
444
937
        param_calendar_user_type,
445
937
        param_delegated_from,
446
937
        param_delegated_to,
447
937
        param_dir,
448
937
        param_encoding,
449
937
        param_format_type,
450
937
        param_free_busy_time_type,
451
937
        param_language,
452
937
        param_member,
453
937
        param_participation_status,
454
937
        param_range,
455
937
        param_related,
456
937
        param_relationship_type,
457
937
        param_role,
458
937
        param_rsvp,
459
937
        param_sent_by,
460
937
        param_time_zone_identifier,
461
937
        param_value_type,
462
937
    ))
463
937
    .parse(input)?;
464

            
465
605
    Ok((input, param_value))
466
937
}
467

            
468
1531
pub fn other_params<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], Vec<ParamValue<'a>>, E>
469
1531
where
470
1531
    E: ParseError<&'a [u8]> + From<Error<'a>>,
471
1531
{
472
1531
    many0((char(';'), other_param))
473
1621
        .map(|v| v.into_iter().map(|(_, p)| p).collect())
474
1531
        .parse(input)
475
1531
}
476

            
477
260
pub fn other_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
478
260
where
479
260
    E: ParseError<&'a [u8]> + From<Error<'a>>,
480
260
{
481
260
    alt((iana_param, x_param)).parse(input)
482
260
}
483

            
484
592
fn iana_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
485
592
where
486
592
    E: ParseError<&'a [u8]> + From<Error<'a>>,
487
592
{
488
592
    let (input, (name, _, values)) = (
489
592
        param_name,
490
592
        char('='),
491
592
        separated_list1(char(','), param_value),
492
592
    )
493
592
        .parse(input)?;
494

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

            
507
fn x_param<'a, E>(input: &'a [u8]) -> IResult<&'a [u8], ParamValue<'a>, E>
508
where
509
    E: ParseError<&'a [u8]> + From<Error<'a>>,
510
{
511
    let (input, (name, _, values)) =
512
        (x_name, char('='), separated_list1(char(','), param_value)).parse(input)?;
513

            
514
    Ok((
515
        input,
516
        match values.len() {
517
            1 => ParamValue::Other {
518
                name,
519
                value: values[0],
520
            },
521
            _ => ParamValue::Others { name, values },
522
        },
523
    ))
524
}
525

            
526
#[cfg(test)]
527
mod tests {
528
    use super::*;
529
    use crate::common::LanguageTag;
530
    use crate::common::{
531
        CalendarUserType, Encoding, FreeBusyTimeType, ParticipationStatusUnknown, RelationshipType,
532
        Role, TriggerRelationship, Value,
533
    };
534
    use crate::test_utils::check_rem;
535

            
536
    #[test]
537
2
    fn param_altrep() {
538
2
        let (rem, param) =
539
2
            known_param::<Error>(b"ALTREP=\"http://example.com/calendar\";").unwrap();
540
2
        check_rem(rem, 1);
541
2
        assert_eq!(
542
2
            ParamValue::AltRep {
543
2
                uri: b"http://example.com/calendar"
544
2
            },
545
2
            param
546
2
        );
547
2
    }
548

            
549
    #[test]
550
2
    fn param_cn() {
551
2
        let (rem, param) = known_param::<Error>(b"CN=\"John Smith\";").unwrap();
552
2
        check_rem(rem, 1);
553
2
        assert_eq!(
554
2
            ParamValue::CommonName {
555
2
                name: "John Smith".to_string()
556
2
            },
557
2
            param
558
2
        );
559
2
    }
560

            
561
    #[test]
562
2
    fn param_cn_not_quoted() {
563
2
        let (rem, param) = known_param::<Error>(b"CN=Danny;").unwrap();
564
2
        check_rem(rem, 1);
565
2
        assert_eq!(
566
2
            ParamValue::CommonName {
567
2
                name: "Danny".to_string()
568
2
            },
569
2
            param
570
2
        );
571
2
    }
572

            
573
    #[test]
574
2
    fn param_cu_type_individual() {
575
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=INDIVIDUAL;").unwrap();
576
2
        check_rem(rem, 1);
577
2
        assert_eq!(
578
2
            ParamValue::CalendarUserType {
579
2
                cu_type: CalendarUserType::Individual
580
2
            },
581
2
            param
582
2
        );
583
2
    }
584

            
585
    #[test]
586
2
    fn param_cu_type_group() {
587
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=GROUP;").unwrap();
588
2
        check_rem(rem, 1);
589
2
        assert_eq!(
590
2
            ParamValue::CalendarUserType {
591
2
                cu_type: CalendarUserType::Group
592
2
            },
593
2
            param
594
2
        );
595
2
    }
596

            
597
    #[test]
598
2
    fn param_cu_type_resource() {
599
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=RESOURCE;").unwrap();
600
2
        check_rem(rem, 1);
601
2
        assert_eq!(
602
2
            ParamValue::CalendarUserType {
603
2
                cu_type: CalendarUserType::Resource
604
2
            },
605
2
            param
606
2
        );
607
2
    }
608

            
609
    #[test]
610
2
    fn param_cu_type_room() {
611
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=ROOM;").unwrap();
612
2
        check_rem(rem, 1);
613
2
        assert_eq!(
614
2
            ParamValue::CalendarUserType {
615
2
                cu_type: CalendarUserType::Room
616
2
            },
617
2
            param
618
2
        );
619
2
    }
620

            
621
    #[test]
622
2
    fn param_cu_type_unknown() {
623
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=UNKNOWN;").unwrap();
624
2
        check_rem(rem, 1);
625
2
        assert_eq!(
626
2
            ParamValue::CalendarUserType {
627
2
                cu_type: CalendarUserType::Unknown
628
2
            },
629
2
            param
630
2
        );
631
2
    }
632

            
633
    #[test]
634
2
    fn param_cu_type_x_name() {
635
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=X-esl-special;").unwrap();
636
2
        check_rem(rem, 1);
637
2
        assert_eq!(
638
2
            ParamValue::CalendarUserType {
639
2
                cu_type: CalendarUserType::XName("X-esl-special".to_string())
640
2
            },
641
2
            param
642
2
        );
643
2
    }
644

            
645
    #[test]
646
2
    fn param_cu_type_iana_token() {
647
2
        let (rem, param) = known_param::<Error>(b"CUTYPE=other;").unwrap();
648
2
        check_rem(rem, 1);
649
2
        assert_eq!(
650
2
            ParamValue::CalendarUserType {
651
2
                cu_type: CalendarUserType::IanaToken("other".to_string())
652
2
            },
653
2
            param
654
2
        );
655
2
    }
656

            
657
    #[test]
658
2
    fn param_delegated_from() {
659
2
        let (rem, param) =
660
2
            known_param::<Error>(b"DELEGATED-FROM=\"mailto:jsmith@example.com\";").unwrap();
661
2
        check_rem(rem, 1);
662
2
        assert_eq!(
663
2
            ParamValue::DelegatedFrom {
664
2
                delegators: vec![b"mailto:jsmith@example.com"],
665
2
            },
666
2
            param
667
2
        );
668
2
    }
669

            
670
    #[test]
671
2
    fn param_delegated_from_multi() {
672
2
        let (rem, param) = known_param::<Error>(
673
2
            b"DELEGATED-FROM=\"mailto:jsmith@example.com\",\"mailto:danny@example.com\";",
674
2
        )
675
2
        .unwrap();
676
2
        check_rem(rem, 1);
677
2
        assert_eq!(
678
2
            ParamValue::DelegatedFrom {
679
2
                delegators: vec![b"mailto:jsmith@example.com", b"mailto:danny@example.com",],
680
2
            },
681
2
            param
682
2
        );
683
2
    }
684

            
685
    #[test]
686
2
    fn param_delegated_to() {
687
2
        let (rem, param) =
688
2
            known_param::<Error>(b"DELEGATED-TO=\"mailto:jsmith@example.com\";").unwrap();
689
2
        check_rem(rem, 1);
690
2
        assert_eq!(
691
2
            ParamValue::DelegatedTo {
692
2
                delegates: vec![b"mailto:jsmith@example.com"],
693
2
            },
694
2
            param
695
2
        );
696
2
    }
697

            
698
    #[test]
699
2
    fn param_delegated_to_multi() {
700
2
        let (rem, param) = known_param::<Error>(
701
2
            b"DELEGATED-TO=\"mailto:jsmith@example.com\",\"mailto:danny@example.com\";",
702
2
        )
703
2
        .unwrap();
704
2
        check_rem(rem, 1);
705
2
        assert_eq!(
706
2
            ParamValue::DelegatedTo {
707
2
                delegates: vec![b"mailto:jsmith@example.com", b"mailto:danny@example.com",],
708
2
            },
709
2
            param
710
2
        );
711
2
    }
712

            
713
    #[test]
714
2
    fn param_dir() {
715
2
        let (rem, param) = known_param::<Error>(
716
2
            b"DIR=\"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)\";",
717
2
        )
718
2
        .unwrap();
719
2
        check_rem(rem, 1);
720
2
        assert_eq!(
721
2
            ParamValue::DirectoryEntryReference {
722
2
                uri: b"ldap://example.com:6666/o=ABC%20Industries,c=US???(cn=Jim%20Dolittle)"
723
2
            },
724
2
            param
725
2
        );
726
2
    }
727

            
728
    #[test]
729
2
    fn param_encoding_8bit() {
730
2
        let (rem, param) = known_param::<Error>(b"ENCODING=8BIT;").unwrap();
731
2
        check_rem(rem, 1);
732
2
        assert_eq!(
733
2
            ParamValue::Encoding {
734
2
                encoding: Encoding::EightBit
735
2
            },
736
2
            param
737
2
        );
738
2
    }
739

            
740
    #[test]
741
2
    fn param_encoding_base64() {
742
2
        let (rem, param) = known_param::<Error>(b"ENCODING=BASE64;").unwrap();
743
2
        check_rem(rem, 1);
744
2
        assert_eq!(
745
2
            ParamValue::Encoding {
746
2
                encoding: Encoding::Base64
747
2
            },
748
2
            param
749
2
        );
750
2
    }
751

            
752
    #[test]
753
2
    fn param_fmt_type() {
754
2
        let (rem, param) = known_param::<Error>(b"FMTTYPE=application/msword;").unwrap();
755
2
        check_rem(rem, 1);
756
2
        assert_eq!(
757
2
            ParamValue::FormatType {
758
2
                type_name: "application".to_string(),
759
2
                sub_type_name: "msword".to_string(),
760
2
            },
761
2
            param
762
2
        );
763
2
    }
764

            
765
    #[test]
766
2
    fn param_fb_type_free() {
767
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=FREE;").unwrap();
768
2
        check_rem(rem, 1);
769
2
        assert_eq!(
770
2
            ParamValue::FreeBusyTimeType {
771
2
                fb_type: FreeBusyTimeType::Free
772
2
            },
773
2
            param
774
2
        );
775
2
    }
776

            
777
    #[test]
778
2
    fn param_fb_type_busy() {
779
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=BUSY;").unwrap();
780
2
        check_rem(rem, 1);
781
2
        assert_eq!(
782
2
            ParamValue::FreeBusyTimeType {
783
2
                fb_type: FreeBusyTimeType::Busy
784
2
            },
785
2
            param
786
2
        );
787
2
    }
788

            
789
    #[test]
790
2
    fn param_fb_type_busy_unavailable() {
791
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=BUSY-UNAVAILABLE;").unwrap();
792
2
        check_rem(rem, 1);
793
2
        assert_eq!(
794
2
            ParamValue::FreeBusyTimeType {
795
2
                fb_type: FreeBusyTimeType::BusyUnavailable
796
2
            },
797
2
            param
798
2
        );
799
2
    }
800

            
801
    #[test]
802
2
    fn param_fb_type_busy_tentative() {
803
2
        let (rem, param) = known_param::<Error>(b"FBTYPE=BUSY-TENTATIVE;").unwrap();
804
2
        check_rem(rem, 1);
805
2
        assert_eq!(
806
2
            ParamValue::FreeBusyTimeType {
807
2
                fb_type: FreeBusyTimeType::BusyTentative
808
2
            },
809
2
            param
810
2
        );
811
2
    }
812

            
813
    #[test]
814
2
    fn param_language() {
815
2
        let (rem, param) = known_param::<Error>(b"LANGUAGE=en-US;").unwrap();
816
2
        check_rem(rem, 1);
817
2
        assert_eq!(
818
2
            ParamValue::Language {
819
2
                language: LanguageTag {
820
2
                    language: "en".to_string(),
821
2
                    region: Some("US".to_string()),
822
2
                    ..Default::default()
823
2
                }
824
2
            },
825
2
            param
826
2
        );
827
2
    }
828

            
829
    #[test]
830
2
    fn param_member() {
831
2
        let (rem, param) =
832
2
            known_param::<Error>(b"MEMBER=\"mailto:ietf-calsch@example.org\";").unwrap();
833
2
        check_rem(rem, 1);
834
2
        assert_eq!(
835
2
            ParamValue::Members {
836
2
                members: vec![b"mailto:ietf-calsch@example.org"],
837
2
            },
838
2
            param
839
2
        );
840
2
    }
841

            
842
    #[test]
843
2
    fn param_member_multi() {
844
2
        let (rem, param) = known_param::<Error>(
845
2
            b"MEMBER=\"mailto:projectA@example.com\",\"mailto:projectB@example.com\";",
846
2
        )
847
2
        .unwrap();
848
2
        check_rem(rem, 1);
849
2
        assert_eq!(
850
2
            ParamValue::Members {
851
2
                members: vec![
852
2
                    b"mailto:projectA@example.com",
853
2
                    b"mailto:projectB@example.com",
854
2
                ],
855
2
            },
856
2
            param
857
2
        );
858
2
    }
859

            
860
    #[test]
861
2
    fn param_part_stat_declined() {
862
2
        let (rem, param) = known_param::<Error>(b"PARTSTAT=DECLINED;").unwrap();
863
2
        check_rem(rem, 1);
864
2
        assert_eq!(
865
2
            ParamValue::ParticipationStatus {
866
2
                status: ParticipationStatusUnknown::Declined
867
2
            },
868
2
            param
869
2
        );
870
2
    }
871

            
872
    #[test]
873
2
    fn param_range() {
874
2
        let (rem, param) = known_param::<Error>(b"RANGE=THISANDFUTURE;").unwrap();
875
2
        check_rem(rem, 1);
876
2
        assert_eq!(
877
2
            ParamValue::Range {
878
2
                range: Range::ThisAndFuture
879
2
            },
880
2
            param
881
2
        );
882
2
    }
883

            
884
    #[test]
885
2
    fn param_related_start() {
886
2
        let (rem, param) = known_param::<Error>(b"RELATED=START;").unwrap();
887
2
        check_rem(rem, 1);
888
2
        assert_eq!(
889
2
            ParamValue::Related {
890
2
                related: TriggerRelationship::Start
891
2
            },
892
2
            param
893
2
        );
894
2
    }
895

            
896
    #[test]
897
2
    fn param_related_end() {
898
2
        let (rem, param) = known_param::<Error>(b"RELATED=END;").unwrap();
899
2
        check_rem(rem, 1);
900
2
        assert_eq!(
901
2
            ParamValue::Related {
902
2
                related: TriggerRelationship::End
903
2
            },
904
2
            param
905
2
        );
906
2
    }
907

            
908
    #[test]
909
2
    fn param_rel_type() {
910
2
        let (rem, param) = known_param::<Error>(b"RELTYPE=SIBLING;").unwrap();
911
2
        check_rem(rem, 1);
912
2
        assert_eq!(
913
2
            ParamValue::RelationshipType {
914
2
                relationship: RelationshipType::Sibling
915
2
            },
916
2
            param
917
2
        );
918
2
    }
919

            
920
    #[test]
921
2
    fn param_role() {
922
2
        let (rem, param) = known_param::<Error>(b"ROLE=CHAIR;").unwrap();
923
2
        check_rem(rem, 1);
924
2
        assert_eq!(ParamValue::Role { role: Role::Chair }, param);
925
2
    }
926

            
927
    #[test]
928
2
    fn param_rsvp_true() {
929
2
        let (rem, param) = known_param::<Error>(b"RSVP=TRUE;").unwrap();
930
2
        check_rem(rem, 1);
931
2
        assert_eq!(ParamValue::Rsvp { rsvp: true }, param);
932
2
    }
933

            
934
    #[test]
935
2
    fn param_rsvp_false() {
936
2
        let (rem, param) = known_param::<Error>(b"RSVP=FALSE;").unwrap();
937
2
        check_rem(rem, 1);
938
2
        assert_eq!(ParamValue::Rsvp { rsvp: false }, param);
939
2
    }
940

            
941
    #[test]
942
2
    fn param_sent_by() {
943
2
        let (rem, param) = known_param::<Error>(b"SENT-BY=\"mailto:sray@example.com\";").unwrap();
944
2
        check_rem(rem, 1);
945
2
        assert_eq!(
946
2
            ParamValue::SentBy {
947
2
                address: b"mailto:sray@example.com"
948
2
            },
949
2
            param
950
2
        );
951
2
    }
952

            
953
    #[test]
954
2
    fn param_tz_id() {
955
2
        let (rem, param) = known_param::<Error>(b"TZID=America/New_York;").unwrap();
956
2
        check_rem(rem, 1);
957
2
        assert_eq!(
958
2
            ParamValue::TimeZoneId {
959
2
                tz_id: "America/New_York".to_string(),
960
2
                unique: false,
961
2
            },
962
2
            param
963
2
        );
964
2
    }
965

            
966
    #[test]
967
2
    fn param_tz_id_unique() {
968
2
        let (rem, param) = known_param::<Error>(b"TZID=/America/New_York;").unwrap();
969
2
        check_rem(rem, 1);
970
2
        assert_eq!(
971
2
            ParamValue::TimeZoneId {
972
2
                tz_id: "America/New_York".to_string(),
973
2
                unique: true,
974
2
            },
975
2
            param
976
2
        );
977
2
    }
978

            
979
    #[test]
980
2
    fn param_value_binary() {
981
2
        let (rem, param) = known_param::<Error>(b"VALUE=BINARY;").unwrap();
982
2
        check_rem(rem, 1);
983
2
        assert_eq!(
984
2
            ParamValue::ValueType {
985
2
                value: Value::Binary
986
2
            },
987
2
            param
988
2
        );
989
2
    }
990
}