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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            
165
52
    Ok(())
166
52
}