1pub trait ParseProp: Sized {
2 fn parse_prop(
3 prop: &ContentLine,
4 timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
5 default_type: &str,
6 ) -> Result<Self, ParserError>;
7}
8
9impl ParseProp for String {
10 fn parse_prop(
11 prop: &ContentLine,
12 _timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
13 _default_type: &str,
14 ) -> Result<Self, ParserError> {
15 Ok(prop.value.to_owned())
16 }
17}
18
19impl ParseProp for DateOrDateTimeOrPeriod {
20 fn parse_prop(
21 prop: &ContentLine,
22 timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
23 default_type: &str,
24 ) -> Result<Self, ParserError> {
25 Self::parse_prop(prop, timezones, default_type)
26 }
27}
28
29impl ParseProp for CalDateOrDateTime {
30 fn parse_prop(
31 prop: &ContentLine,
32 timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
33 default_type: &str,
34 ) -> Result<Self, ParserError> {
35 Self::parse_prop(prop, timezones, default_type)
36 }
37}
38
39impl ParseProp for CalDateTime {
40 fn parse_prop(
41 prop: &ContentLine,
42 timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
43 _default_type: &str,
44 ) -> Result<Self, ParserError> {
45 Self::parse_prop(prop, timezones)
46 }
47}
48
49impl ParseProp for chrono::Duration {
50 fn parse_prop(
51 prop: &ContentLine,
52 _timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
53 _default_type: &str,
54 ) -> Result<Self, ParserError> {
55 Ok(parse_duration(&prop.value)?)
56 }
57}
58
59impl ParseProp for crate::rrule::RRule<crate::rrule::Unvalidated> {
60 fn parse_prop(
61 prop: &ContentLine,
62 _timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
63 _default_type: &str,
64 ) -> Result<Self, ParserError> {
65 Ok(crate::rrule::RRule::from_str(&prop.value)?)
66 }
67}
68
69impl<T: ParseProp> ParseProp for Vec<T> {
70 fn parse_prop(
71 prop: &ContentLine,
72 timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
73 default_type: &str,
74 ) -> Result<Self, ParserError> {
75 let mut out = vec![];
76 for value in prop.value.trim_end_matches(',').split(',') {
77 let content_line = ContentLine {
78 name: prop.name.to_owned(),
79 params: prop.params.to_owned(),
80 value: value.to_owned(),
81 };
82 out.push(T::parse_prop(&content_line, timezones, default_type)?);
83 }
84 Ok(out)
85 }
86}
87
88pub trait ICalProperty: Sized {
89 const NAME: &'static str;
90 const DEFAULT_TYPE: &'static str;
91
92 fn parse_prop(
93 prop: &ContentLine,
94 timezones: Option<&HashMap<String, Option<chrono_tz::Tz>>>,
95 ) -> Result<Self, ParserError>;
96
97 fn utc_or_local(self) -> Self;
98}
99
100macro_rules! property {
101 ($name:literal, $default_type:literal, $prop:ty) => {
102 impl crate::parser::ICalProperty for $prop {
103 const NAME: &'static str = $name;
104 const DEFAULT_TYPE: &'static str = $default_type;
105
106 #[inline]
107 fn parse_prop(
108 prop: &crate::parser::ContentLine,
109 timezones: Option<&std::collections::HashMap<String, Option<chrono_tz::Tz>>>,
110 ) -> Result<Self, crate::parser::ParserError> {
111 Ok(Self(
112 crate::parser::ParseProp::parse_prop(prop, timezones, $default_type)?,
113 prop.params.clone(),
114 ))
115 }
116
117 #[inline]
118 fn utc_or_local(self) -> Self {
119 let Self(dt, mut params) = self;
120 params.remove("TZID");
121 Self(crate::types::Value::utc_or_local(dt), params)
122 }
123 }
124 };
125
126 ($name:literal, $default_type:literal, $prop:ident, $inner:ty) => {
127 #[derive(Debug, Clone, PartialEq, Eq, derive_more::From)]
128 pub struct $prop(pub $inner, pub crate::parser::ContentLineParams);
129 crate::parser::property!($name, $default_type, $prop);
130
131 impl From<$prop> for crate::parser::ContentLine {
132 fn from(prop: $prop) -> Self {
133 let $prop(inner, mut params) = prop;
134 let value_type = crate::types::Value::value_type(&inner).unwrap_or($default_type);
135 if value_type != $default_type {
136 params.replace_param("VALUE".to_owned(), value_type.to_owned());
137 }
138 crate::parser::ContentLine {
139 name: $name.to_owned(),
140 params,
141 value: crate::types::Value::value(&inner),
142 }
143 }
144 }
145 };
146}
147use std::{collections::HashMap, str::FromStr};
148
149pub(crate) use property;
150
151use crate::{
152 ParserError,
153 parser::ContentLine,
154 types::{CalDateOrDateTime, CalDateTime, DateOrDateTimeOrPeriod, parse_duration},
155};