1
use crate::common::CalendarDateTime;
2
use crate::convert::{convert_string, ToModel};
3
use crate::model::property::{
4
    GeographicPositionPropertyValue, Period, RecurrenceDateTimesPropertyValue,
5
    RequestStatusPropertyValue, TimeZoneIdPropertyValue, TriggerValue,
6
};
7
use crate::parser::types::ContentLine;
8
use anyhow::Context;
9

            
10
mod recur;
11

            
12
impl ToModel for crate::parser::types::DateTimeStampProperty<'_> {
13
    type Model = crate::model::property::DateTimeStampProperty;
14

            
15
180
    fn to_model(&self) -> anyhow::Result<Self::Model> {
16
180
        Ok(crate::model::property::DateTimeStampProperty {
17
180
            value: (
18
180
                time::Date::from_calendar_date(
19
180
                    self.value.date.year as i32,
20
180
                    time::Month::try_from(self.value.date.month).context("Invalid month")?,
21
180
                    self.value.date.day,
22
180
                )
23
180
                .context("Invalid date")?,
24
180
                time::Time::from_hms(
25
180
                    self.value.time.hour,
26
180
                    self.value.time.minute,
27
180
                    self.value.time.second,
28
180
                )
29
180
                .context("Invalid time")?,
30
180
                self.value.time.is_utc,
31
180
            )
32
180
                .into(),
33
180
            params: self.other_params.to_model()?,
34
        })
35
180
    }
36
}
37

            
38
impl ToModel for crate::parser::types::UniqueIdentifierProperty<'_> {
39
    type Model = crate::model::property::UniqueIdentifierProperty;
40

            
41
178
    fn to_model(&self) -> anyhow::Result<Self::Model> {
42
178
        Ok(crate::model::property::UniqueIdentifierProperty {
43
178
            value: convert_string(&self.value),
44
178
            params: self.other_params.to_model()?,
45
        })
46
178
    }
47
}
48

            
49
impl ToModel for crate::parser::types::DateTimeStartProperty<'_> {
50
    type Model = crate::model::property::DateTimeStartProperty;
51

            
52
172
    fn to_model(&self) -> anyhow::Result<Self::Model> {
53
172
        let dt = self.value.to_model()?;
54

            
55
        Ok(crate::model::property::DateTimeStartProperty {
56
172
            value: dt,
57
172
            params: self.params.to_model()?,
58
        })
59
172
    }
60
}
61

            
62
impl ToModel for crate::parser::types::ClassificationProperty<'_> {
63
    type Model = crate::model::property::ClassificationProperty;
64

            
65
44
    fn to_model(&self) -> anyhow::Result<Self::Model> {
66
44
        Ok(crate::model::property::ClassificationProperty {
67
44
            value: self.value.to_model()?,
68
44
            params: self.other_params.to_model()?,
69
        })
70
44
    }
71
}
72

            
73
impl ToModel for crate::parser::types::Classification<'_> {
74
    type Model = crate::model::property::Classification;
75

            
76
44
    fn to_model(&self) -> anyhow::Result<Self::Model> {
77
44
        Ok(match self {
78
            crate::parser::types::Classification::Public => {
79
38
                crate::model::property::Classification::Public
80
            }
81
            crate::parser::types::Classification::Private => {
82
2
                crate::model::property::Classification::Private
83
            }
84
            crate::parser::types::Classification::Confidential => {
85
4
                crate::model::property::Classification::Confidential
86
            }
87
            crate::parser::types::Classification::XName(name) => {
88
                crate::model::property::Classification::XName(convert_string(name))
89
            }
90
            crate::parser::types::Classification::IanaToken(token) => {
91
                crate::model::property::Classification::IanaToken(convert_string(token))
92
            }
93
        })
94
44
    }
95
}
96

            
97
impl ToModel for crate::parser::types::DateTimeCreatedProperty<'_> {
98
    type Model = crate::model::property::CreatedProperty;
99

            
100
36
    fn to_model(&self) -> anyhow::Result<Self::Model> {
101
36
        let (date, time, is_utc) = (&self.value).try_into()?;
102

            
103
        Ok(crate::model::property::CreatedProperty {
104
36
            value: (date, time, is_utc).into(),
105
36
            params: self.other_params.to_model()?,
106
        })
107
36
    }
108
}
109

            
110
impl ToModel for crate::parser::types::DescriptionProperty<'_> {
111
    type Model = crate::model::property::DescriptionProperty;
112

            
113
102
    fn to_model(&self) -> anyhow::Result<Self::Model> {
114
102
        Ok(crate::model::property::DescriptionProperty {
115
102
            value: convert_string(&self.value),
116
102
            params: self.params.to_model()?,
117
        })
118
102
    }
119
}
120

            
121
impl ToModel for crate::parser::types::GeographicPositionProperty<'_> {
122
    type Model = crate::model::property::GeographicPositionProperty;
123

            
124
20
    fn to_model(&self) -> anyhow::Result<Self::Model> {
125
20
        Ok(crate::model::property::GeographicPositionProperty {
126
20
            value: GeographicPositionPropertyValue {
127
20
                latitude: self.latitude,
128
20
                longitude: self.longitude,
129
20
            },
130
20
            params: self.other_params.to_model()?,
131
        })
132
20
    }
133
}
134

            
135
impl ToModel for crate::parser::types::LastModifiedProperty<'_> {
136
    type Model = crate::model::property::LastModifiedProperty;
137

            
138
52
    fn to_model(&self) -> anyhow::Result<Self::Model> {
139
52
        let (date, time, is_utc) = (&self.value).try_into()?;
140

            
141
        Ok(crate::model::property::LastModifiedProperty {
142
52
            value: (date, time, is_utc).into(),
143
52
            params: self.other_params.to_model()?,
144
        })
145
52
    }
146
}
147

            
148
impl ToModel for crate::parser::types::LocationProperty<'_> {
149
    type Model = crate::model::property::LocationProperty;
150

            
151
26
    fn to_model(&self) -> anyhow::Result<Self::Model> {
152
26
        Ok(crate::model::property::LocationProperty {
153
26
            value: convert_string(&self.value),
154
26
            params: self.params.to_model()?,
155
        })
156
26
    }
157
}
158

            
159
impl ToModel for crate::parser::types::OrganizerProperty<'_> {
160
    type Model = crate::model::property::OrganizerProperty;
161

            
162
54
    fn to_model(&self) -> anyhow::Result<Self::Model> {
163
54
        Ok(crate::model::property::OrganizerProperty {
164
54
            value: convert_string(self.value),
165
54
            params: self.params.to_model()?,
166
        })
167
54
    }
168
}
169

            
170
impl ToModel for crate::parser::types::PriorityProperty<'_> {
171
    type Model = crate::model::property::PriorityProperty;
172

            
173
22
    fn to_model(&self) -> anyhow::Result<Self::Model> {
174
22
        Ok(crate::model::property::PriorityProperty {
175
22
            value: self.value,
176
22
            params: self.other_params.to_model()?,
177
        })
178
22
    }
179
}
180

            
181
impl ToModel for crate::parser::types::SequenceProperty<'_> {
182
    type Model = crate::model::property::SequenceProperty;
183

            
184
30
    fn to_model(&self) -> anyhow::Result<Self::Model> {
185
30
        Ok(crate::model::property::SequenceProperty {
186
30
            value: self.value,
187
30
            params: self.other_params.to_model()?,
188
        })
189
30
    }
190
}
191

            
192
impl ToModel for crate::parser::types::StatusProperty<'_> {
193
    type Model = crate::model::property::StatusProperty;
194

            
195
34
    fn to_model(&self) -> anyhow::Result<Self::Model> {
196
34
        Ok(crate::model::property::StatusProperty {
197
34
            value: self.value.clone(),
198
34
            params: self.other_params.to_model()?,
199
        })
200
34
    }
201
}
202

            
203
impl ToModel for crate::parser::types::SummaryProperty<'_> {
204
    type Model = crate::model::property::SummaryProperty;
205

            
206
64
    fn to_model(&self) -> anyhow::Result<Self::Model> {
207
64
        Ok(crate::model::property::SummaryProperty {
208
64
            value: convert_string(&self.value),
209
64
            params: self.params.to_model()?,
210
        })
211
64
    }
212
}
213

            
214
impl ToModel for crate::parser::types::TimeTransparencyProperty<'_> {
215
    type Model = crate::model::property::TimeTransparencyProperty;
216

            
217
16
    fn to_model(&self) -> anyhow::Result<Self::Model> {
218
16
        Ok(crate::model::property::TimeTransparencyProperty {
219
16
            value: self.value.clone(),
220
16
            params: self.other_params.to_model()?,
221
        })
222
16
    }
223
}
224

            
225
impl ToModel for crate::parser::types::UrlProperty<'_> {
226
    type Model = crate::model::property::UrlProperty;
227

            
228
44
    fn to_model(&self) -> anyhow::Result<Self::Model> {
229
44
        Ok(crate::model::property::UrlProperty {
230
44
            value: self.value.to_string(),
231
44
            params: self.other_params.to_model()?,
232
        })
233
44
    }
234
}
235

            
236
impl ToModel for crate::parser::types::RecurrenceIdProperty<'_> {
237
    type Model = crate::model::property::RecurrenceIdProperty;
238

            
239
30
    fn to_model(&self) -> anyhow::Result<Self::Model> {
240
30
        let dt = self.value.to_model()?;
241

            
242
        Ok(crate::model::property::RecurrenceIdProperty {
243
30
            value: dt,
244
30
            params: self.params.to_model()?,
245
        })
246
30
    }
247
}
248

            
249
impl ToModel for crate::parser::types::RecurrenceRuleProperty<'_> {
250
    type Model = crate::model::property::RecurrenceRuleProperty;
251

            
252
204
    fn to_model(&self) -> anyhow::Result<Self::Model> {
253
204
        Ok(crate::model::property::RecurrenceRuleProperty {
254
204
            value: self.value.to_model()?,
255
204
            params: self.other_params.to_model()?,
256
        })
257
204
    }
258
}
259

            
260
impl ToModel for crate::parser::types::DateTimeEndProperty<'_> {
261
    type Model = crate::model::property::DateTimeEndProperty;
262

            
263
40
    fn to_model(&self) -> anyhow::Result<Self::Model> {
264
40
        let dt = self.value.to_model()?;
265

            
266
        Ok(crate::model::property::DateTimeEndProperty {
267
40
            value: dt,
268
40
            params: self.params.to_model()?,
269
        })
270
40
    }
271
}
272

            
273
impl ToModel for crate::parser::types::DurationProperty<'_> {
274
    type Model = crate::model::property::DurationProperty;
275

            
276
66
    fn to_model(&self) -> anyhow::Result<Self::Model> {
277
66
        Ok(crate::model::property::DurationProperty {
278
66
            value: self.value.to_model()?,
279
66
            params: self.other_params.to_model()?,
280
        })
281
66
    }
282
}
283

            
284
impl ToModel for crate::parser::types::AttachProperty<'_> {
285
    type Model = crate::model::property::AttachProperty;
286

            
287
48
    fn to_model(&self) -> anyhow::Result<Self::Model> {
288
48
        let value = match self.value {
289
38
            crate::parser::types::AttachValue::Uri(uri) => convert_string(uri),
290
10
            crate::parser::types::AttachValue::Binary(binary) => convert_string(binary),
291
        };
292

            
293
        Ok(crate::model::property::AttachProperty {
294
48
            value,
295
48
            params: self.params.to_model()?,
296
        })
297
48
    }
298
}
299

            
300
impl ToModel for crate::parser::types::AttendeeProperty<'_> {
301
    type Model = crate::model::property::AttendeeProperty;
302

            
303
46
    fn to_model(&self) -> anyhow::Result<Self::Model> {
304
46
        Ok(crate::model::property::AttendeeProperty {
305
46
            value: convert_string(self.value),
306
46
            params: self.params.to_model()?,
307
        })
308
46
    }
309
}
310

            
311
impl ToModel for crate::parser::types::CategoriesProperty<'_> {
312
    type Model = crate::model::property::CategoriesProperty;
313

            
314
32
    fn to_model(&self) -> anyhow::Result<Self::Model> {
315
32
        Ok(crate::model::property::CategoriesProperty {
316
86
            value: self.value.iter().map(|v| convert_string(v)).collect(),
317
32
            params: self.params.to_model()?,
318
        })
319
32
    }
320
}
321

            
322
impl ToModel for crate::parser::types::CommentProperty<'_> {
323
    type Model = crate::model::property::CommentProperty;
324

            
325
38
    fn to_model(&self) -> anyhow::Result<Self::Model> {
326
38
        Ok(crate::model::property::CommentProperty {
327
38
            value: convert_string(&self.value),
328
38
            params: self.params.to_model()?,
329
        })
330
38
    }
331
}
332

            
333
impl ToModel for crate::parser::types::ContactProperty<'_> {
334
    type Model = crate::model::property::ContactProperty;
335

            
336
28
    fn to_model(&self) -> anyhow::Result<Self::Model> {
337
28
        Ok(crate::model::property::ContactProperty {
338
28
            value: convert_string(&self.value),
339
28
            params: self.params.to_model()?,
340
        })
341
28
    }
342
}
343

            
344
impl ToModel for crate::parser::types::ExceptionDateTimesProperty<'_> {
345
    type Model = crate::model::property::ExceptionDateTimesProperty;
346

            
347
20
    fn to_model(&self) -> anyhow::Result<Self::Model> {
348
20
        Ok(crate::model::property::ExceptionDateTimesProperty {
349
20
            value: self
350
20
                .value
351
20
                .iter()
352
42
                .map(|v| v.to_model())
353
20
                .collect::<Result<_, _>>()?,
354
20
            params: self.params.to_model()?,
355
        })
356
20
    }
357
}
358

            
359
impl ToModel for crate::parser::types::RequestStatusProperty<'_> {
360
    type Model = crate::model::property::RequestStatusProperty;
361

            
362
24
    fn to_model(&self) -> anyhow::Result<Self::Model> {
363
24
        Ok(crate::model::property::RequestStatusProperty {
364
24
            value: RequestStatusPropertyValue {
365
24
                status_code: self.status_code.clone(),
366
24
                description: convert_string(&self.status_description),
367
28
                exception_data: self.exception_data.as_ref().map(|v| convert_string(v)),
368
24
            },
369
24
            params: self.params.to_model()?,
370
        })
371
24
    }
372
}
373

            
374
impl ToModel for crate::parser::types::RelatedToProperty<'_> {
375
    type Model = crate::model::property::RelatedToProperty;
376

            
377
18
    fn to_model(&self) -> anyhow::Result<Self::Model> {
378
18
        Ok(crate::model::property::RelatedToProperty {
379
18
            value: convert_string(&self.value),
380
18
            params: self.params.to_model()?,
381
        })
382
18
    }
383
}
384

            
385
impl ToModel for crate::parser::types::ResourcesProperty<'_> {
386
    type Model = crate::model::property::ResourcesProperty;
387

            
388
12
    fn to_model(&self) -> anyhow::Result<Self::Model> {
389
12
        Ok(crate::model::property::ResourcesProperty {
390
38
            value: self.value.iter().map(|v| convert_string(v)).collect(),
391
12
            params: self.params.to_model()?,
392
        })
393
12
    }
394
}
395

            
396
impl ToModel for crate::parser::types::XProperty<'_> {
397
    type Model = crate::model::property::XProperty;
398

            
399
132
    fn to_model(&self) -> anyhow::Result<Self::Model> {
400
132
        Ok(crate::model::property::XProperty {
401
132
            name: convert_string(self.name),
402
132
            value: convert_string(&self.value),
403
132
            params: self.params.to_model()?,
404
        })
405
132
    }
406
}
407

            
408
impl ToModel for crate::parser::types::IanaProperty<'_> {
409
    type Model = crate::model::property::IanaProperty;
410

            
411
114
    fn to_model(&self) -> anyhow::Result<Self::Model> {
412
114
        Ok(crate::model::property::IanaProperty {
413
114
            name: convert_string(self.name),
414
114
            value: convert_string(&self.value),
415
114
            params: self.params.to_model()?,
416
        })
417
114
    }
418
}
419

            
420
impl ToModel for crate::parser::types::RecurrenceDateTimesProperty<'_> {
421
    type Model = crate::model::property::RecurrenceDateTimesProperty;
422

            
423
34
    fn to_model(&self) -> anyhow::Result<Self::Model> {
424
34
        let date_times = self.value.to_model()?;
425

            
426
71
        let (date_times, periods) = if date_times.iter().all(|dt| dt.0.is_some()) {
427
34
            (
428
71
                date_times.iter().map(|dt| dt.0.unwrap().into()).collect(),
429
34
                Vec::with_capacity(0),
430
34
            )
431
        } else if date_times.iter().all(|dt| dt.1.is_some()) {
432
            (
433
                Vec::with_capacity(0),
434
                date_times.iter().map(|dt| dt.1.clone().unwrap()).collect(),
435
            )
436
        } else {
437
            return Err(anyhow::anyhow!("Invalid recurrence date-times"));
438
        };
439

            
440
        Ok(crate::model::property::RecurrenceDateTimesProperty {
441
34
            value: if !periods.is_empty() {
442
                RecurrenceDateTimesPropertyValue::Periods(periods)
443
            } else {
444
34
                RecurrenceDateTimesPropertyValue::DateTimes(date_times)
445
            },
446
34
            params: self.params.to_model()?,
447
        })
448
34
    }
449
}
450

            
451
impl ToModel for crate::parser::types::Duration {
452
    type Model = crate::model::property::Duration;
453

            
454
118
    fn to_model(&self) -> anyhow::Result<Self::Model> {
455
118
        Ok(crate::model::property::Duration {
456
118
            sign: self.sign,
457
118
            weeks: self.weeks,
458
118
            days: self.days,
459
118
            hours: self.hours,
460
118
            minutes: self.minutes,
461
118
            seconds: self.seconds,
462
118
        })
463
118
    }
464
}
465

            
466
impl ToModel for crate::parser::types::DateOrDateTimeOrPeriod {
467
    type Model = (
468
        Option<(time::Date, Option<time::Time>, bool)>,
469
        Option<Period>,
470
    );
471

            
472
64
    fn to_model(&self) -> anyhow::Result<Self::Model> {
473
64
        match self {
474
            crate::parser::types::DateOrDateTimeOrPeriod::Date(date) => {
475
                Ok((Some((date.try_into()?, None, false)), None))
476
            }
477
64
            crate::parser::types::DateOrDateTimeOrPeriod::DateTime(date_time) => {
478
64
                let (date, time, is_utc) = date_time.try_into()?;
479
64
                Ok((Some((date, Some(time), is_utc)), None))
480
            }
481
            crate::parser::types::DateOrDateTimeOrPeriod::Period(period) => {
482
                Ok((None, Some(period.to_model()?)))
483
            }
484
        }
485
64
    }
486
}
487

            
488
impl ToModel for crate::parser::types::ProductIdProperty<'_> {
489
    type Model = crate::model::property::ProductIdProperty;
490

            
491
184
    fn to_model(&self) -> anyhow::Result<Self::Model> {
492
184
        Ok(crate::model::property::ProductIdProperty {
493
184
            value: convert_string(&self.value),
494
184
            params: self.other_params.to_model()?,
495
        })
496
184
    }
497
}
498

            
499
impl ToModel for crate::parser::types::VersionProperty<'_> {
500
    type Model = crate::model::property::VersionProperty;
501

            
502
184
    fn to_model(&self) -> anyhow::Result<Self::Model> {
503
184
        Ok(crate::model::property::VersionProperty {
504
184
            min_version: self.min_version.map(convert_string),
505
184
            max_version: convert_string(self.max_version),
506
184
            params: self.other_params.to_model()?,
507
        })
508
184
    }
509
}
510

            
511
impl ToModel for crate::parser::types::CalendarScaleProperty<'_> {
512
    type Model = crate::model::property::CalendarScaleProperty;
513

            
514
6
    fn to_model(&self) -> anyhow::Result<Self::Model> {
515
6
        Ok(crate::model::property::CalendarScaleProperty {
516
6
            value: convert_string(&self.value),
517
6
            params: self.other_params.to_model()?,
518
        })
519
6
    }
520
}
521

            
522
impl ToModel for crate::parser::types::MethodProperty<'_> {
523
    type Model = crate::model::property::MethodProperty;
524

            
525
92
    fn to_model(&self) -> anyhow::Result<Self::Model> {
526
92
        Ok(crate::model::property::MethodProperty {
527
92
            value: convert_string(self.value),
528
92
            params: self.other_params.to_model()?,
529
        })
530
92
    }
531
}
532

            
533
impl ToModel for crate::parser::types::CalendarProperty<'_> {
534
    type Model = crate::model::property::CalendarProperty;
535

            
536
466
    fn to_model(&self) -> anyhow::Result<Self::Model> {
537
466
        match self {
538
184
            crate::parser::types::CalendarProperty::ProductId(product_id) => Ok(
539
184
                crate::model::property::CalendarProperty::ProductId(product_id.to_model()?),
540
            ),
541
184
            crate::parser::types::CalendarProperty::Version(version) => Ok(
542
184
                crate::model::property::CalendarProperty::Version(version.to_model()?),
543
            ),
544
6
            crate::parser::types::CalendarProperty::CalendarScale(cal_scale) => Ok(
545
6
                crate::model::property::CalendarProperty::CalendarScale(cal_scale.to_model()?),
546
            ),
547
92
            crate::parser::types::CalendarProperty::Method(method) => Ok(
548
92
                crate::model::property::CalendarProperty::Method(method.to_model()?),
549
            ),
550
            crate::parser::types::CalendarProperty::XProperty(x_prop) => Ok(
551
                crate::model::property::CalendarProperty::XProperty(x_prop.to_model()?),
552
            ),
553
            crate::parser::types::CalendarProperty::IanaProperty(iana_prop) => Ok(
554
                crate::model::property::CalendarProperty::IanaProperty(iana_prop.to_model()?),
555
            ),
556
        }
557
466
    }
558
}
559

            
560
impl ToModel for crate::parser::types::DateTimeCompletedProperty<'_> {
561
    type Model = crate::model::property::DateTimeCompletedProperty;
562

            
563
8
    fn to_model(&self) -> anyhow::Result<Self::Model> {
564
8
        let (date, time, is_utc) = (&self.value).try_into()?;
565

            
566
        Ok(crate::model::property::DateTimeCompletedProperty {
567
8
            value: (date, time, is_utc).into(),
568
8
            params: self.other_params.to_model()?,
569
        })
570
8
    }
571
}
572

            
573
impl ToModel for crate::parser::types::PercentCompleteProperty<'_> {
574
    type Model = crate::model::property::PercentCompleteProperty;
575

            
576
10
    fn to_model(&self) -> anyhow::Result<Self::Model> {
577
10
        Ok(crate::model::property::PercentCompleteProperty {
578
10
            value: self.value,
579
10
            params: self.other_params.to_model()?,
580
        })
581
10
    }
582
}
583

            
584
impl ToModel for crate::parser::types::DateTimeDueProperty<'_> {
585
    type Model = crate::model::property::DateTimeDueProperty;
586

            
587
12
    fn to_model(&self) -> anyhow::Result<Self::Model> {
588
12
        let dt = self.value.to_model()?;
589

            
590
        Ok(crate::model::property::DateTimeDueProperty {
591
12
            value: dt,
592
12
            params: self.params.to_model()?,
593
        })
594
12
    }
595
}
596

            
597
impl ToModel for crate::parser::types::FreeBusyTimeProperty<'_> {
598
    type Model = crate::model::property::FreeBusyTimeProperty;
599

            
600
14
    fn to_model(&self) -> anyhow::Result<Self::Model> {
601
14
        Ok(crate::model::property::FreeBusyTimeProperty {
602
14
            value: self.value.to_model()?,
603
14
            params: self.params.to_model()?,
604
        })
605
14
    }
606
}
607

            
608
impl ToModel for crate::parser::types::TimeZoneIdProperty<'_> {
609
    type Model = crate::model::property::TimeZoneIdProperty;
610

            
611
36
    fn to_model(&self) -> anyhow::Result<Self::Model> {
612
36
        Ok(crate::model::property::TimeZoneIdProperty {
613
36
            value: TimeZoneIdPropertyValue {
614
36
                id: convert_string(&self.value),
615
36
                unique_registry_id: self.unique_registry_id,
616
36
            },
617
36
            params: self.other_params.to_model()?,
618
        })
619
36
    }
620
}
621

            
622
impl ToModel for crate::parser::types::TimeZoneUrlProperty<'_> {
623
    type Model = crate::model::property::TimeZoneUrlProperty;
624

            
625
12
    fn to_model(&self) -> anyhow::Result<Self::Model> {
626
12
        Ok(crate::model::property::TimeZoneUrlProperty {
627
12
            value: convert_string(self.value),
628
12
            params: self.other_params.to_model()?,
629
        })
630
12
    }
631
}
632

            
633
impl ToModel for crate::parser::types::TimeZoneOffsetProperty<'_> {
634
    type Model = crate::model::property::TimeZoneOffsetToProperty;
635

            
636
144
    fn to_model(&self) -> anyhow::Result<Self::Model> {
637
144
        Ok(crate::model::property::TimeZoneOffsetToProperty {
638
144
            value: self.value.to_model()?,
639
144
            params: self.other_params.to_model()?,
640
        })
641
144
    }
642
}
643

            
644
impl ToModel for crate::parser::types::UtcOffset {
645
    type Model = crate::model::property::TimeZoneOffset;
646

            
647
144
    fn to_model(&self) -> anyhow::Result<Self::Model> {
648
144
        Ok(crate::model::property::TimeZoneOffset {
649
144
            sign: self.sign,
650
144
            hours: self.hours as u8,
651
144
            minutes: self.minutes as u8,
652
144
            seconds: self.seconds.map(|s| s as u8),
653
144
        })
654
144
    }
655
}
656

            
657
impl ToModel for crate::parser::types::TimeZoneNameProperty<'_> {
658
    type Model = crate::model::property::TimeZoneNameProperty;
659

            
660
62
    fn to_model(&self) -> anyhow::Result<Self::Model> {
661
62
        Ok(crate::model::property::TimeZoneNameProperty {
662
62
            value: convert_string(&self.value),
663
62
            params: self.params.to_model()?,
664
        })
665
62
    }
666
}
667

            
668
impl ToModel for crate::parser::types::ActionProperty<'_> {
669
    type Model = crate::model::property::ActionProperty;
670

            
671
58
    fn to_model(&self) -> anyhow::Result<Self::Model> {
672
58
        Ok(crate::model::property::ActionProperty {
673
58
            value: self.value.to_model()?,
674
58
            params: self.other_params.to_model()?,
675
        })
676
58
    }
677
}
678

            
679
impl ToModel for crate::parser::types::Action<'_> {
680
    type Model = crate::model::property::Action;
681

            
682
58
    fn to_model(&self) -> anyhow::Result<Self::Model> {
683
58
        Ok(match self {
684
18
            crate::parser::types::Action::Audio => crate::model::property::Action::Audio,
685
24
            crate::parser::types::Action::Display => crate::model::property::Action::Display,
686
16
            crate::parser::types::Action::Email => crate::model::property::Action::Email,
687
            crate::parser::types::Action::XName(name) => {
688
                crate::model::property::Action::XName(convert_string(name))
689
            }
690
            crate::parser::types::Action::IanaToken(token) => {
691
                crate::model::property::Action::IanaToken(convert_string(token))
692
            }
693
        })
694
58
    }
695
}
696

            
697
impl ToModel for crate::parser::types::TriggerProperty<'_> {
698
    type Model = crate::model::property::TriggerProperty;
699

            
700
54
    fn to_model(&self) -> anyhow::Result<Self::Model> {
701
54
        match &self.value {
702
14
            crate::parser::types::DurationOrDateTime::DateTime(date_time) => {
703
14
                let (date, time, is_utc) = date_time.try_into()?;
704
                Ok(crate::model::property::TriggerProperty {
705
14
                    value: TriggerValue::Absolute((date, time, is_utc).into()),
706
14
                    params: self.params.to_model()?,
707
                })
708
            }
709
40
            crate::parser::types::DurationOrDateTime::Duration(duration) => {
710
40
                Ok(crate::model::property::TriggerProperty {
711
40
                    value: TriggerValue::Relative(duration.to_model()?),
712
40
                    params: self.params.to_model()?,
713
                })
714
            }
715
        }
716
54
    }
717
}
718

            
719
impl ToModel for crate::parser::types::RepeatProperty<'_> {
720
    type Model = crate::model::property::RepeatProperty;
721

            
722
46
    fn to_model(&self) -> anyhow::Result<Self::Model> {
723
46
        Ok(crate::model::property::RepeatProperty {
724
46
            value: self.value,
725
46
            params: self.other_params.to_model()?,
726
        })
727
46
    }
728
}
729

            
730
impl ToModel for crate::parser::types::ComponentProperty<'_> {
731
    type Model = crate::model::property::ComponentProperty;
732

            
733
2416
    fn to_model(&self) -> anyhow::Result<Self::Model> {
734
2416
        match self {
735
180
            crate::parser::types::ComponentProperty::DateTimeStamp(date_time_stamp) => {
736
180
                Ok(crate::model::property::ComponentProperty::DateTimeStamp(
737
180
                    date_time_stamp.to_model()?,
738
                ))
739
            }
740
178
            crate::parser::types::ComponentProperty::UniqueIdentifier(unique_identifier) => {
741
178
                Ok(crate::model::property::ComponentProperty::UniqueIdentifier(
742
178
                    unique_identifier.to_model()?,
743
                ))
744
            }
745
172
            crate::parser::types::ComponentProperty::DateTimeStart(date_time_start) => {
746
172
                Ok(crate::model::property::ComponentProperty::DateTimeStart(
747
172
                    date_time_start.to_model()?,
748
                ))
749
            }
750
44
            crate::parser::types::ComponentProperty::Classification(classification) => {
751
44
                Ok(crate::model::property::ComponentProperty::Classification(
752
44
                    classification.to_model()?,
753
                ))
754
            }
755
36
            crate::parser::types::ComponentProperty::DateTimeCreated(created) => Ok(
756
36
                crate::model::property::ComponentProperty::DateTimeCreated(created.to_model()?),
757
            ),
758
102
            crate::parser::types::ComponentProperty::Description(description) => Ok(
759
102
                crate::model::property::ComponentProperty::Description(description.to_model()?),
760
            ),
761
20
            crate::parser::types::ComponentProperty::GeographicPosition(geo_pos) => Ok(
762
20
                crate::model::property::ComponentProperty::GeographicPosition(geo_pos.to_model()?),
763
            ),
764
52
            crate::parser::types::ComponentProperty::LastModified(last_modified) => Ok(
765
52
                crate::model::property::ComponentProperty::LastModified(last_modified.to_model()?),
766
            ),
767
26
            crate::parser::types::ComponentProperty::Location(location) => Ok(
768
26
                crate::model::property::ComponentProperty::Location(location.to_model()?),
769
            ),
770
54
            crate::parser::types::ComponentProperty::Organizer(organizer) => Ok(
771
54
                crate::model::property::ComponentProperty::Organizer(organizer.to_model()?),
772
            ),
773
22
            crate::parser::types::ComponentProperty::Priority(priority) => Ok(
774
22
                crate::model::property::ComponentProperty::Priority(priority.to_model()?),
775
            ),
776
30
            crate::parser::types::ComponentProperty::Sequence(sequence) => Ok(
777
30
                crate::model::property::ComponentProperty::Sequence(sequence.to_model()?),
778
            ),
779
34
            crate::parser::types::ComponentProperty::Status(status) => Ok(
780
34
                crate::model::property::ComponentProperty::Status(status.to_model()?),
781
            ),
782
64
            crate::parser::types::ComponentProperty::Summary(summary) => Ok(
783
64
                crate::model::property::ComponentProperty::Summary(summary.to_model()?),
784
            ),
785
16
            crate::parser::types::ComponentProperty::TimeTransparency(time_transparency) => {
786
16
                Ok(crate::model::property::ComponentProperty::TimeTransparency(
787
16
                    time_transparency.to_model()?,
788
                ))
789
            }
790
44
            crate::parser::types::ComponentProperty::Url(url) => Ok(
791
44
                crate::model::property::ComponentProperty::Url(url.to_model()?),
792
            ),
793
30
            crate::parser::types::ComponentProperty::RecurrenceId(recurrence_id) => Ok(
794
30
                crate::model::property::ComponentProperty::RecurrenceId(recurrence_id.to_model()?),
795
            ),
796
204
            crate::parser::types::ComponentProperty::RecurrenceRule(recurrence_rule) => {
797
204
                Ok(crate::model::property::ComponentProperty::RecurrenceRule(
798
204
                    recurrence_rule.to_model()?,
799
                ))
800
            }
801
40
            crate::parser::types::ComponentProperty::DateTimeEnd(date_time_end) => Ok(
802
40
                crate::model::property::ComponentProperty::DateTimeEnd(date_time_end.to_model()?),
803
            ),
804
66
            crate::parser::types::ComponentProperty::Duration(duration) => Ok(
805
66
                crate::model::property::ComponentProperty::Duration(duration.to_model()?),
806
            ),
807
48
            crate::parser::types::ComponentProperty::Attach(attach) => Ok(
808
48
                crate::model::property::ComponentProperty::Attach(attach.to_model()?),
809
            ),
810
46
            crate::parser::types::ComponentProperty::Attendee(attendee) => Ok(
811
46
                crate::model::property::ComponentProperty::Attendee(attendee.to_model()?),
812
            ),
813
32
            crate::parser::types::ComponentProperty::Categories(categories) => Ok(
814
32
                crate::model::property::ComponentProperty::Categories(categories.to_model()?),
815
            ),
816
38
            crate::parser::types::ComponentProperty::Comment(comment) => Ok(
817
38
                crate::model::property::ComponentProperty::Comment(comment.to_model()?),
818
            ),
819
28
            crate::parser::types::ComponentProperty::Contact(contact) => Ok(
820
28
                crate::model::property::ComponentProperty::Contact(contact.to_model()?),
821
            ),
822
20
            crate::parser::types::ComponentProperty::ExceptionDateTimes(exception_date_times) => {
823
20
                Ok(
824
20
                    crate::model::property::ComponentProperty::ExceptionDateTimes(
825
20
                        exception_date_times.to_model()?,
826
                    ),
827
                )
828
            }
829
24
            crate::parser::types::ComponentProperty::RequestStatus(request_status) => {
830
24
                Ok(crate::model::property::ComponentProperty::RequestStatus(
831
24
                    request_status.to_model()?,
832
                ))
833
            }
834
18
            crate::parser::types::ComponentProperty::RelatedTo(related_to) => Ok(
835
18
                crate::model::property::ComponentProperty::RelatedTo(related_to.to_model()?),
836
            ),
837
12
            crate::parser::types::ComponentProperty::Resources(resources) => Ok(
838
12
                crate::model::property::ComponentProperty::Resources(resources.to_model()?),
839
            ),
840
34
            crate::parser::types::ComponentProperty::RecurrenceDateTimes(recurrence_date_times) => {
841
34
                Ok(
842
34
                    crate::model::property::ComponentProperty::RecurrenceDateTimes(
843
34
                        recurrence_date_times.to_model()?,
844
                    ),
845
                )
846
            }
847
8
            crate::parser::types::ComponentProperty::DateTimeCompleted(date_time_completed) => Ok(
848
8
                crate::model::property::ComponentProperty::DateTimeCompleted(
849
8
                    date_time_completed.to_model()?,
850
                ),
851
            ),
852
10
            crate::parser::types::ComponentProperty::PercentComplete(percent_complete) => {
853
10
                Ok(crate::model::property::ComponentProperty::PercentComplete(
854
10
                    percent_complete.to_model()?,
855
                ))
856
            }
857
12
            crate::parser::types::ComponentProperty::DateTimeDue(date_time_due) => Ok(
858
12
                crate::model::property::ComponentProperty::DateTimeDue(date_time_due.to_model()?),
859
            ),
860
14
            crate::parser::types::ComponentProperty::FreeBusyTime(free_busy_time) => Ok(
861
14
                crate::model::property::ComponentProperty::FreeBusyTime(free_busy_time.to_model()?),
862
            ),
863
36
            crate::parser::types::ComponentProperty::TimeZoneId(time_zone_id) => Ok(
864
36
                crate::model::property::ComponentProperty::TimeZoneId(time_zone_id.to_model()?),
865
            ),
866
12
            crate::parser::types::ComponentProperty::TimeZoneUrl(time_zone_url) => Ok(
867
12
                crate::model::property::ComponentProperty::TimeZoneUrl(time_zone_url.to_model()?),
868
            ),
869
72
            crate::parser::types::ComponentProperty::TimeZoneOffsetTo(time_zone_offset_to) => {
870
72
                Ok(crate::model::property::ComponentProperty::TimeZoneOffsetTo(
871
72
                    time_zone_offset_to.to_model()?,
872
                ))
873
            }
874
72
            crate::parser::types::ComponentProperty::TimeZoneOffsetFrom(time_zone_offset_from) => {
875
72
                let to = time_zone_offset_from.to_model()?;
876
72
                Ok(
877
72
                    crate::model::property::ComponentProperty::TimeZoneOffsetFrom(
878
72
                        crate::model::property::TimeZoneOffsetFromProperty {
879
72
                            value: to.value,
880
72
                            params: to.params,
881
72
                        },
882
72
                    ),
883
72
                )
884
            }
885
62
            crate::parser::types::ComponentProperty::TimeZoneName(time_zone_name) => Ok(
886
62
                crate::model::property::ComponentProperty::TimeZoneName(time_zone_name.to_model()?),
887
            ),
888
58
            crate::parser::types::ComponentProperty::Action(action) => Ok(
889
58
                crate::model::property::ComponentProperty::Action(action.to_model()?),
890
            ),
891
54
            crate::parser::types::ComponentProperty::Trigger(trigger) => Ok(
892
54
                crate::model::property::ComponentProperty::Trigger(trigger.to_model()?),
893
            ),
894
46
            crate::parser::types::ComponentProperty::RepeatCount(repeat_count) => Ok(
895
46
                crate::model::property::ComponentProperty::Repeat(repeat_count.to_model()?),
896
            ),
897
132
            crate::parser::types::ComponentProperty::XProperty(x_prop) => Ok(
898
132
                crate::model::property::ComponentProperty::XProperty(x_prop.to_model()?),
899
            ),
900
114
            crate::parser::types::ComponentProperty::IanaProperty(iana_prop) => Ok(
901
114
                crate::model::property::ComponentProperty::IanaProperty(iana_prop.to_model()?),
902
            ),
903
        }
904
2416
    }
905
}
906

            
907
impl ToModel for ContentLine<'_> {
908
    type Model = crate::model::property::IanaProperty;
909

            
910
64
    fn to_model(&self) -> anyhow::Result<Self::Model> {
911
64
        Ok(crate::model::property::IanaProperty {
912
64
            name: convert_string(self.property_name),
913
64
            value: convert_string(&self.value),
914
64
            params: self.params.to_model()?,
915
        })
916
64
    }
917
}
918

            
919
impl ToModel for crate::parser::types::Period {
920
    type Model = Period;
921

            
922
24
    fn to_model(&self) -> anyhow::Result<Self::Model> {
923
24
        Ok(Period {
924
24
            start: (&self.start).try_into()?,
925
24
            end: match &self.end {
926
12
                crate::parser::types::PeriodEnd::DateTime(date_time) => {
927
12
                    crate::model::property::PeriodEnd::DateTime(date_time.try_into()?)
928
                }
929
12
                crate::parser::types::PeriodEnd::Duration(duration) => {
930
12
                    crate::model::property::PeriodEnd::Duration(duration.to_model()?)
931
                }
932
            },
933
        })
934
24
    }
935
}
936

            
937
impl ToModel for crate::parser::types::DateOrDateTime {
938
    type Model = CalendarDateTime;
939

            
940
356
    fn to_model(&self) -> anyhow::Result<Self::Model> {
941
356
        Ok(match self {
942
22
            crate::parser::types::DateOrDateTime::Date(date) => {
943
22
                (date.try_into()?, None, false).into()
944
            }
945
334
            crate::parser::types::DateOrDateTime::DateTime(datetime) => {
946
334
                let (date, time, is_utc) = datetime.try_into()?;
947
334
                (date, Some(time), is_utc).into()
948
            }
949
        })
950
356
    }
951
}
952

            
953
impl TryFrom<&crate::parser::types::Date> for time::Date {
954
    type Error = anyhow::Error;
955

            
956
566
    fn try_from(value: &crate::parser::types::Date) -> Result<Self, Self::Error> {
957
566
        time::Date::from_calendar_date(
958
566
            value.year as i32,
959
566
            time::Month::try_from(value.month).context("Invalid month")?,
960
566
            value.day,
961
566
        )
962
566
        .context("Invalid date")
963
566
    }
964
}
965

            
966
impl TryFrom<&crate::parser::types::DateTime> for (time::Date, time::Time, bool) {
967
    type Error = anyhow::Error;
968

            
969
544
    fn try_from(value: &crate::parser::types::DateTime) -> Result<Self, Self::Error> {
970
544
        Ok((
971
544
            time::Date::try_from(&value.date)?,
972
544
            time::Time::from_hms(value.time.hour, value.time.minute, value.time.second)
973
544
                .context("Invalid time")?,
974
544
            value.time.is_utc,
975
        ))
976
544
    }
977
}