1
use crate::convert::{convert_string, ToModel};
2
use crate::model::component::{
3
    AlarmComponent, DaylightComponent, EventComponent, FreeBusyComponent, JournalComponent,
4
    StandardComponent, TimeZoneComponent, ToDoComponent,
5
};
6
use crate::model::property::ComponentProperty;
7
use crate::parser::types::ContentLine;
8

            
9
impl ToModel for crate::parser::types::CalendarComponent<'_> {
10
    type Model = crate::model::component::CalendarComponent;
11

            
12
422
    fn to_model(&self) -> anyhow::Result<Self::Model> {
13
422
        match self {
14
140
            crate::parser::types::CalendarComponent::Event { properties, alarms } => {
15
140
                let mut component = EventComponent::new();
16
140
                component.properties.reserve(properties.len());
17

            
18
1066
                for property in properties {
19
926
                    component.properties.push(property.to_model()?);
20
                }
21

            
22
140
                component.alarms.reserve(alarms.len());
23
196
                for alarm in alarms {
24
56
                    component.alarms.push(alarm.to_model()?);
25
                }
26

            
27
140
                Ok(crate::model::component::CalendarComponent::Event(component))
28
            }
29
24
            crate::parser::types::CalendarComponent::ToDo { properties, alarms } => {
30
24
                let mut component = ToDoComponent::new();
31
24
                component.properties.reserve(properties.len());
32

            
33
356
                for property in properties {
34
332
                    component.properties.push(property.to_model()?);
35
                }
36

            
37
24
                component.alarms.reserve(alarms.len());
38
30
                for alarm in alarms {
39
6
                    component.alarms.push(alarm.to_model()?);
40
                }
41

            
42
24
                Ok(crate::model::component::CalendarComponent::ToDo(component))
43
            }
44
14
            crate::parser::types::CalendarComponent::Journal { properties } => {
45
14
                let mut journal = JournalComponent::new();
46
14
                journal.properties.reserve(properties.len());
47

            
48
226
                for property in properties {
49
212
                    journal.properties.push(property.to_model()?);
50
                }
51

            
52
14
                Ok(crate::model::component::CalendarComponent::Journal(journal))
53
            }
54
16
            crate::parser::types::CalendarComponent::FreeBusy { properties } => {
55
16
                let mut free_busy = FreeBusyComponent::new();
56
16
                free_busy.properties.reserve(properties.len());
57

            
58
164
                for property in properties {
59
148
                    free_busy.properties.push(property.to_model()?);
60
                }
61

            
62
16
                Ok(crate::model::component::CalendarComponent::FreeBusy(
63
16
                    free_busy,
64
16
                ))
65
            }
66
38
            crate::parser::types::CalendarComponent::Standard { properties } => {
67
38
                let mut standard = StandardComponent::new();
68
38
                standard.properties.reserve(properties.len());
69

            
70
218
                for property in properties {
71
180
                    standard.properties.push(property.to_model()?);
72
                }
73

            
74
38
                Ok(crate::model::component::CalendarComponent::Standard(
75
38
                    standard,
76
38
                ))
77
            }
78
38
            crate::parser::types::CalendarComponent::Daylight { properties } => {
79
38
                let mut daylight = DaylightComponent::new();
80
38
                daylight.properties.reserve(properties.len());
81

            
82
236
                for property in properties {
83
198
                    daylight.properties.push(property.to_model()?);
84
                }
85

            
86
38
                Ok(crate::model::component::CalendarComponent::Daylight(
87
38
                    daylight,
88
38
                ))
89
            }
90
            crate::parser::types::CalendarComponent::TimeZone {
91
38
                properties,
92
38
                components,
93
38
            } => {
94
38
                let mut timezone = TimeZoneComponent::new();
95
38
                timezone.properties.reserve(properties.len());
96

            
97
122
                for property in properties {
98
84
                    timezone.properties.push(property.to_model()?);
99
                }
100

            
101
38
                timezone.components.reserve(components.len());
102
114
                for component in components {
103
76
                    timezone.components.push(component.to_model()?);
104
                }
105

            
106
38
                Ok(crate::model::component::CalendarComponent::TimeZone(
107
38
                    timezone,
108
38
                ))
109
            }
110
62
            crate::parser::types::CalendarComponent::Alarm { properties } => {
111
62
                let mut alarm = AlarmComponent::new();
112
62
                alarm.properties.reserve(properties.len());
113

            
114
398
                for property in properties {
115
336
                    alarm.properties.push(property.to_model()?);
116
                }
117

            
118
62
                Ok(crate::model::component::CalendarComponent::Alarm(alarm))
119
            }
120
10
            crate::parser::types::CalendarComponent::IanaComp { name, lines } => {
121
10
                let mut component =
122
10
                    crate::model::component::IanaComponent::new(convert_string(name));
123
10
                component.properties.reserve(lines.len());
124
10

            
125
10
                map_unknown_lines(lines, &mut component.properties)?;
126

            
127
10
                Ok(crate::model::component::CalendarComponent::IanaComponent(
128
10
                    component,
129
10
                ))
130
            }
131
42
            crate::parser::types::CalendarComponent::XComp { name, lines } => {
132
42
                let mut component = crate::model::component::XComponent::new(convert_string(name));
133
42
                component.properties.reserve(lines.len());
134
42

            
135
42
                map_unknown_lines(lines, &mut component.properties)?;
136

            
137
42
                Ok(crate::model::component::CalendarComponent::XComponent(
138
42
                    component,
139
42
                ))
140
            }
141
        }
142
422
    }
143
}
144

            
145
52
fn map_unknown_lines(
146
52
    lines: &Vec<ContentLine>,
147
52
    component_properties: &mut Vec<ComponentProperty>,
148
52
) -> anyhow::Result<()> {
149
116
    for line in lines {
150
64
        let m = line.to_model()?;
151
64
        if m.name.starts_with("X-") || m.name.starts_with("x-") {
152
14
            component_properties.push(ComponentProperty::XProperty(
153
14
                crate::model::property::XProperty {
154
14
                    name: m.name,
155
14
                    value: m.value,
156
14
                    params: m.params,
157
14
                },
158
14
            ));
159
50
        } else {
160
50
            component_properties.push(ComponentProperty::IanaProperty(m));
161
50
        }
162
    }
163

            
164
52
    Ok(())
165
52
}