1
pub(crate) mod access;
2
pub mod component;
3
pub mod object;
4
pub mod param;
5
pub mod property;
6

            
7
pub use access::*;
8

            
9
#[cfg(test)]
10
mod tests {
11
    use crate::common::{LanguageTag, Range, RecurFreq, RelationshipType, TimeTransparency};
12
    use crate::model::component::CalendarComponent;
13
    use crate::model::object::ICalObject;
14
    use crate::model::param::{OtherParamsBuilder, ParticipationStatusEvent};
15
    use crate::model::property::{
16
        Classification, ComponentProperty, Duration, Period, StatusEvent,
17
    };
18
    use time::Date;
19

            
20
    #[test]
21
2
    fn all_cal_props_cal_object() {
22
2
        let obj = ICalObject::builder()
23
2
            .add_product_id("-//ABC Corporation//NONSGML My Product//EN")
24
2
            .add_x_param("x-special-param", "my-value")
25
2
            .finish_property()
26
2
            .add_max_version("2.0")
27
2
            .add_x_param_values(
28
2
                "x-special-param",
29
2
                vec!["one-value".to_string(), "another-value".to_string()],
30
2
            )
31
2
            .finish_property()
32
2
            .add_calendar_scale("GREGORIAN")
33
2
            .finish_property()
34
2
            .add_method("REQUEST")
35
2
            .finish_property()
36
2
            .add_x_property("X-PROP", "X-VALUE")
37
2
            .add_iana_param("special-param", "my-value")
38
2
            .finish_property()
39
2
            .add_iana_property("IANA-PARAM", "IANA-VALUE")
40
2
            .add_iana_param_values(
41
2
                "iana-special-param",
42
2
                vec!["one-value".to_string(), "another-value".to_string()],
43
2
            )
44
2
            .finish_property()
45
2
            .build();
46
2

            
47
2
        assert_eq!(obj.properties.len(), 6);
48
2
    }
49

            
50
    #[test]
51
2
    fn x_component_cal_object() {
52
2
        let obj = ICalObject::builder()
53
2
            .add_product_id("x_component_cal_object")
54
2
            .finish_property()
55
3
            .add_x_component("X-SOME-COMPONENT", |b| {
56
2
                b.add_x_property("X-SOME-PROP", "X-SOME-VALUE")
57
2
                    .add_x_param("x-special-param", "my-value")
58
2
                    .add_iana_param("special-param", "my-value")
59
2
                    .finish_property()
60
3
            })
61
3
            .add_iana_component("IANA-SOME-COMPONENT", |b| {
62
2
                b.add_iana_property("IANA-SOME-PROP", "IANA-SOME-VALUE")
63
2
                    .add_iana_param("special-param", "my-value")
64
2
                    .add_x_param("x-special-param", "my-value")
65
2
                    .finish_property()
66
3
            })
67
2
            .build();
68
2

            
69
2
        assert_eq!(obj.components.len(), 2);
70

            
71
2
        match &obj.components[0] {
72
2
            CalendarComponent::XComponent(x) => {
73
2
                assert_eq!(x.properties.len(), 1);
74
2
                match &x.properties[0] {
75
2
                    ComponentProperty::XProperty(p) => {
76
2
                        assert_eq!(p.params.len(), 2);
77
                    }
78
                    _ => panic!("Expected XProperty"),
79
                }
80
            }
81
            _ => panic!("Expected XComponent"),
82
        }
83

            
84
2
        match &obj.components[1] {
85
2
            CalendarComponent::IanaComponent(x) => {
86
2
                assert_eq!(x.properties.len(), 1);
87
2
                match &x.properties[0] {
88
2
                    ComponentProperty::IanaProperty(p) => {
89
2
                        assert_eq!(p.params.len(), 2);
90
                    }
91
                    _ => panic!("Expected IanaProperty"),
92
                }
93
            }
94
            _ => panic!("Expected IanaComponent"),
95
        }
96
2
    }
97

            
98
    #[test]
99
2
    fn event_component_cal_object() {
100
2
        let obj = ICalObject::builder()
101
2
            .add_product_id("event_component")
102
2
            .finish_property()
103
2
            .add_event_component()
104
2
            .add_date_time_stamp(
105
2
                time::Date::from_calendar_date(1997, time::Month::September, 1).unwrap(),
106
2
                time::Time::from_hms(13, 0, 0).unwrap(),
107
2
            )
108
2
            .add_x_param("X-SOME-PROP", "X-SOME-VALUE")
109
2
            .finish_property()
110
2
            .add_unique_identifier("some-uid")
111
2
            .add_x_param("x-special-param", "my-value")
112
2
            .finish_property()
113
2
            .add_date_time_start(
114
2
                time::Date::from_calendar_date(1997, time::Month::September, 1).unwrap(),
115
2
                Some(time::Time::from_hms(14, 30, 0).unwrap()),
116
2
            )
117
2
            .add_tz_id("America/New_York", true)
118
2
            .finish_property()
119
2
            .add_classification(Classification::Private)
120
2
            .add_x_param("x-special-param", "my-value")
121
2
            .finish_property()
122
2
            .add_date_time_created(
123
2
                time::Date::from_calendar_date(1997, time::Month::September, 1).unwrap(),
124
2
                time::Time::from_hms(13, 0, 0).unwrap(),
125
2
            )
126
2
            .add_x_param("x-special-param", "my-value")
127
2
            .finish_property()
128
2
            .add_description("Event description")
129
2
            .add_alternate_representation("CID:evt.desc")
130
2
            .add_language(LanguageTag {
131
2
                language: "en".to_string(),
132
2
                region: Some("US".to_string()),
133
2
                ..Default::default()
134
2
            })
135
2
            .add_x_param("x-special-param", "my-value")
136
2
            .finish_property()
137
2
            .add_geographic_position(37.386013, -122.082932)
138
2
            .add_x_param("x-special-param", "my-value")
139
2
            .finish_property()
140
2
            .add_organizer("mailto:john@local.net")
141
2
            .add_common_name("John")
142
2
            .add_directory_entry_reference("ldap://local.net/john")
143
2
            .add_sent_by("mailto:lilith@local.net")
144
2
            .add_language(LanguageTag {
145
2
                language: "en".to_string(),
146
2
                region: Some("US".to_string()),
147
2
                ..Default::default()
148
2
            })
149
2
            .add_x_param("x-special-param", "my-value")
150
2
            .finish_property()
151
2
            .add_priority(4)
152
2
            .add_x_param("x-special-param", "my-value")
153
2
            .finish_property()
154
2
            .add_sequence(10)
155
2
            .add_x_param("x-special-param", "my-value")
156
2
            .finish_property()
157
2
            .add_request_status(&[200, 4], "Success", None)
158
2
            .add_x_param("x-special-param", "my-value")
159
2
            .finish_property()
160
2
            .add_time_transparency(TimeTransparency::Transparent)
161
2
            .add_x_param("x-special-param", "my-value")
162
2
            .finish_property()
163
2
            .add_url("http://local.net/john")
164
2
            .add_x_param("x-special-param", "my-value")
165
2
            .finish_property()
166
2
            .add_recurrence_id(
167
2
                Date::from_calendar_date(1997, time::Month::September, 1).unwrap(),
168
2
                None,
169
2
            )
170
2
            .add_tz_id("America/New_York", true)
171
2
            .add_range(Range::ThisAndFuture)
172
2
            .add_x_param("x-special-param", "my-value")
173
2
            .finish_property()
174
3
            .add_recurrence_rule(RecurFreq::Hourly, |rule| rule.set_by_hour(vec![1, 2, 3]))
175
2
            .add_x_param("x-special-param", "my-value")
176
2
            .finish_property()
177
2
            .add_date_time_end(
178
2
                Date::from_calendar_date(1997, time::Month::September, 1).unwrap(),
179
2
                Some(time::Time::from_hms(15, 30, 0).unwrap()),
180
2
            )
181
2
            .add_x_param("x-special-param", "my-value")
182
2
            .finish_property()
183
3
            .add_duration(|| Duration::days_and_time(-1, 10).hours(3).build())
184
2
            .add_x_param("x-special-param", "my-value")
185
2
            .finish_property()
186
2
            .add_attach_uri("http://local.net/john")
187
2
            .add_fmt_type("text", "plain")
188
2
            .add_x_param("x-special-param", "my-value")
189
2
            .finish_property()
190
2
            .add_attendee("mailto:horace@local.net")
191
2
            .add_members(vec!["mailto:dev-group@local.net"])
192
2
            .add_participation_status(ParticipationStatusEvent::Accepted)
193
2
            .add_x_param("x-special-param", "my-value")
194
2
            .finish_property()
195
2
            .add_categories(vec!["MEETING", "PROJECT"])
196
2
            .add_language(LanguageTag {
197
2
                language: "en".to_string(),
198
2
                region: Some("US".to_string()),
199
2
                ..Default::default()
200
2
            })
201
2
            .add_x_param("x-special-param", "my-value")
202
2
            .finish_property()
203
2
            .add_comment("Event comment")
204
2
            .add_alternate_representation("CID:evt.comment")
205
2
            .add_language(LanguageTag {
206
2
                language: "en".to_string(),
207
2
                region: Some("US".to_string()),
208
2
                ..Default::default()
209
2
            })
210
2
            .add_x_param("x-special-param", "my-value")
211
2
            .finish_property()
212
2
            .add_contact("mailto:kevin@local.net")
213
2
            .add_alternate_representation("CID:evt.contact")
214
2
            .add_language(LanguageTag {
215
2
                language: "en".to_string(),
216
2
                region: Some("US".to_string()),
217
2
                ..Default::default()
218
2
            })
219
2
            .add_x_param("x-special-param", "my-value")
220
2
            .finish_property()
221
2
            .add_exception_date_times(vec![(
222
2
                Date::from_calendar_date(1997, time::Month::September, 2).unwrap(),
223
2
                None,
224
2
                true,
225
2
            )
226
2
                .into()])
227
2
            .add_tz_id("America/New_York", true)
228
2
            .add_x_param("x-special-param", "my-value")
229
2
            .finish_property()
230
2
            .add_status(StatusEvent::Tentative)
231
2
            .add_x_param("x-special-param", "my-value")
232
2
            .finish_property()
233
2
            .add_related_to("CID:evt.related")
234
2
            .add_relationship_type(RelationshipType::Parent)
235
2
            .add_x_param("x-special-param", "my-value")
236
2
            .finish_property()
237
2
            .add_resources(vec!["EQUIPMENT", "ROOM"])
238
2
            .add_language(LanguageTag {
239
2
                language: "en".to_string(),
240
2
                region: Some("US".to_string()),
241
2
                ..Default::default()
242
2
            })
243
2
            .add_alternate_representation("CID:evt.resources")
244
2
            .add_x_param("x-special-param", "my-value")
245
2
            .finish_property()
246
2
            .add_recurrence_date_periods(vec![Period::new_start(
247
2
                Date::from_calendar_date(1997, time::Month::September, 2).unwrap(),
248
2
                time::Time::from_hms(14, 30, 0).unwrap(),
249
2
                true,
250
2
                Duration::hours(1, 1).build(),
251
2
            )])
252
2
            .add_tz_id("America/New_York", true)
253
2
            .add_x_param("x-special-param", "my-value")
254
2
            .finish_property()
255
2
            .add_last_modified(
256
2
                time::Date::from_calendar_date(1997, time::Month::September, 1).unwrap(),
257
2
                time::Time::from_hms(13, 0, 0).unwrap(),
258
2
            )
259
2
            .add_x_param("x-special-param", "my-value")
260
2
            .finish_property()
261
2
            .add_summary("Event summary")
262
2
            .add_language(LanguageTag {
263
2
                language: "en".to_string(),
264
2
                region: Some("US".to_string()),
265
2
                ..Default::default()
266
2
            })
267
2
            .add_alternate_representation("CID:evt.summary")
268
2
            .add_x_param("x-special-param", "my-value")
269
2
            .finish_property()
270
2
            .add_x_property("X-SOME-PROP", "X-SOME-VALUE")
271
2
            .add_x_param("x-special-param", "my-value")
272
2
            .finish_property()
273
2
            .add_iana_property("IANA-SOME-PROP", "IANA-SOME-VALUE")
274
2
            .add_iana_param("special-param", "my-value")
275
2
            .add_x_param("x-special-param", "my-value")
276
2
            .finish_property()
277
2
            .finish_component()
278
2
            .build();
279
2

            
280
2
        assert_eq!(obj.components.len(), 1);
281

            
282
2
        match &obj.components[0] {
283
2
            CalendarComponent::Event(e) => {
284
2
                assert_eq!(e.properties.len(), 31);
285
2
                match &e.properties[0] {
286
2
                    ComponentProperty::DateTimeStamp(p) => {
287
2
                        assert_eq!(p.params.len(), 1);
288
                    }
289
                    _ => panic!("Expected DateTimeStamp"),
290
                }
291
2
                match &e.properties[1] {
292
2
                    ComponentProperty::UniqueIdentifier(p) => {
293
2
                        assert_eq!(p.params.len(), 1);
294
                    }
295
                    _ => panic!("Expected UniqueIdentifier"),
296
                }
297
2
                match &e.properties[2] {
298
2
                    ComponentProperty::DateTimeStart(p) => {
299
2
                        assert_eq!(p.params.len(), 1);
300
                    }
301
                    _ => panic!("Expected DateTimeStart"),
302
                }
303
2
                match &e.properties[3] {
304
2
                    ComponentProperty::Classification(p) => {
305
2
                        assert_eq!(p.params.len(), 1);
306
                    }
307
                    _ => panic!("Expected Class"),
308
                }
309
2
                match &e.properties[4] {
310
2
                    ComponentProperty::DateTimeCreated(p) => {
311
2
                        assert_eq!(p.params.len(), 1);
312
                    }
313
                    _ => panic!("Expected Created"),
314
                }
315
2
                match &e.properties[5] {
316
2
                    ComponentProperty::Description(p) => {
317
2
                        assert_eq!(p.params.len(), 3);
318
                    }
319
                    _ => panic!("Expected Description"),
320
                }
321
2
                match &e.properties[6] {
322
2
                    ComponentProperty::GeographicPosition(p) => {
323
2
                        assert_eq!(p.params.len(), 1);
324
                    }
325
                    _ => panic!("Expected GeographicPosition"),
326
                }
327
2
                match &e.properties[7] {
328
2
                    ComponentProperty::Organizer(p) => {
329
2
                        assert_eq!(p.params.len(), 5);
330
                    }
331
                    _ => panic!("Expected Organizer"),
332
                }
333
2
                match &e.properties[8] {
334
2
                    ComponentProperty::Priority(p) => {
335
2
                        assert_eq!(p.params.len(), 1);
336
                    }
337
                    _ => panic!("Expected Priority"),
338
                }
339
2
                match &e.properties[9] {
340
2
                    ComponentProperty::Sequence(p) => {
341
2
                        assert_eq!(p.params.len(), 1);
342
                    }
343
                    _ => panic!("Expected Sequence"),
344
                }
345
2
                match &e.properties[10] {
346
2
                    ComponentProperty::RequestStatus(p) => {
347
2
                        assert_eq!(p.params.len(), 1);
348
                    }
349
                    _ => panic!("Expected RequestStatus"),
350
                }
351
2
                match &e.properties[11] {
352
2
                    ComponentProperty::TimeTransparency(p) => {
353
2
                        assert_eq!(p.params.len(), 1);
354
                    }
355
                    _ => panic!("Expected TimeTransparency"),
356
                }
357
2
                match &e.properties[12] {
358
2
                    ComponentProperty::Url(p) => {
359
2
                        assert_eq!(p.params.len(), 1);
360
                    }
361
                    _ => panic!("Expected Url"),
362
                }
363
2
                match &e.properties[13] {
364
2
                    ComponentProperty::RecurrenceId(p) => {
365
2
                        assert_eq!(p.params.len(), 4);
366
                    }
367
                    _ => panic!("Expected RecurrenceId"),
368
                }
369
2
                match &e.properties[14] {
370
2
                    ComponentProperty::RecurrenceRule(p) => {
371
2
                        assert_eq!(p.params.len(), 1);
372
                    }
373
                    _ => panic!("Expected RecurrenceRule"),
374
                }
375
2
                match &e.properties[15] {
376
2
                    ComponentProperty::DateTimeEnd(p) => {
377
2
                        assert_eq!(p.params.len(), 1);
378
                    }
379
                    _ => panic!("Expected DateTimeEnd"),
380
                }
381
2
                match &e.properties[16] {
382
2
                    ComponentProperty::Duration(p) => {
383
2
                        assert_eq!(p.params.len(), 1);
384
                    }
385
                    _ => panic!("Expected Duration"),
386
                }
387
2
                match &e.properties[17] {
388
2
                    ComponentProperty::Attach(p) => {
389
2
                        assert_eq!(p.params.len(), 2);
390
                    }
391
                    _ => panic!("Expected Attach"),
392
                }
393
2
                match &e.properties[18] {
394
2
                    ComponentProperty::Attendee(p) => {
395
2
                        assert_eq!(p.params.len(), 3);
396
                    }
397
                    _ => panic!("Expected Attendee"),
398
                }
399
2
                match &e.properties[19] {
400
2
                    ComponentProperty::Categories(p) => {
401
2
                        assert_eq!(p.params.len(), 2);
402
                    }
403
                    _ => panic!("Expected Categories"),
404
                }
405
2
                match &e.properties[20] {
406
2
                    ComponentProperty::Comment(p) => {
407
2
                        assert_eq!(p.params.len(), 3);
408
                    }
409
                    _ => panic!("Expected Comment"),
410
                }
411
2
                match &e.properties[21] {
412
2
                    ComponentProperty::Contact(p) => {
413
2
                        assert_eq!(p.params.len(), 3);
414
                    }
415
                    _ => panic!("Expected Contact"),
416
                }
417
2
                match &e.properties[22] {
418
2
                    ComponentProperty::ExceptionDateTimes(p) => {
419
2
                        assert_eq!(p.params.len(), 3);
420
                    }
421
                    _ => panic!("Expected ExceptionDateTimes"),
422
                }
423
2
                match &e.properties[23] {
424
2
                    ComponentProperty::Status(p) => {
425
2
                        assert_eq!(p.params.len(), 1);
426
                    }
427
                    _ => panic!("Expected Status"),
428
                }
429
2
                match &e.properties[24] {
430
2
                    ComponentProperty::RelatedTo(p) => {
431
2
                        assert_eq!(p.params.len(), 2);
432
                    }
433
                    _ => panic!("Expected RelatedTo"),
434
                }
435
2
                match &e.properties[25] {
436
2
                    ComponentProperty::Resources(p) => {
437
2
                        assert_eq!(p.params.len(), 3);
438
                    }
439
                    _ => panic!("Expected Resources"),
440
                }
441
2
                match &e.properties[26] {
442
2
                    ComponentProperty::RecurrenceDateTimes(p) => {
443
2
                        assert_eq!(p.params.len(), 3);
444
                    }
445
                    _ => panic!("Expected RecurrenceDateTimes"),
446
                }
447
2
                match &e.properties[27] {
448
2
                    ComponentProperty::LastModified(p) => {
449
2
                        assert_eq!(p.params.len(), 1);
450
                    }
451
                    _ => panic!("Expected LastModified"),
452
                }
453
2
                match &e.properties[28] {
454
2
                    ComponentProperty::Summary(p) => {
455
2
                        assert_eq!(p.params.len(), 3);
456
                    }
457
                    _ => panic!("Expected Summary"),
458
                }
459
2
                match &e.properties[29] {
460
2
                    ComponentProperty::XProperty(p) => {
461
2
                        assert_eq!(p.params.len(), 1);
462
                    }
463
                    _ => panic!("Expected XProperty"),
464
                }
465
2
                match &e.properties[30] {
466
2
                    ComponentProperty::IanaProperty(p) => {
467
2
                        assert_eq!(p.params.len(), 2);
468
                    }
469
                    _ => panic!("Expected IanaProperty"),
470
                }
471
            }
472
            _ => panic!("Expected EventComponent"),
473
        }
474
2
    }
475
}