1mod duration;
2pub use duration::*;
3mod timezone;
4use crate::rrule::{RRule, Unvalidated};
5use itertools::Itertools;
6pub use timezone::*;
7mod date;
8mod period;
9pub use date::*;
10mod datetime;
11pub use datetime::*;
12mod dateordatetime;
13pub use dateordatetime::*;
14pub use period::*;
15mod guess_timezone;
16pub use guess_timezone::*;
17
18mod vcard;
19pub use vcard::*;
20
21#[derive(Debug, thiserror::Error, PartialEq, Eq)]
22pub enum CalDateTimeError {
23 #[error(
24 "Timezone has X-LIC-LOCATION property to specify a timezone from the Olson database, however its value {0} is invalid"
25 )]
26 InvalidOlson(String),
27 #[error("TZID {0} does not refer to a valid timezone")]
28 InvalidTZID(String),
29 #[error("Timestamp doesn't exist because of gap in local time")]
30 LocalTimeGap,
31 #[error("Datetime string {0} has an invalid format")]
32 InvalidDatetimeFormat(String),
33 #[error("Could not parse datetime {0}")]
34 ParseError(String),
35 #[error("Duration string {0} has an invalid format")]
36 InvalidDurationFormat(String),
37 #[error("Invalid period format: {0}")]
38 InvalidPeriodFormat(String),
39}
40
41pub trait Value: Sized {
42 fn utc_or_local(self) -> Self {
43 self
44 }
45
46 fn value_type(&self) -> Option<&'static str>;
47
48 fn value(&self) -> String;
49}
50
51impl Value for String {
52 fn value_type(&self) -> Option<&'static str> {
53 Some("TEXT")
54 }
55
56 fn value(&self) -> String {
57 self.to_owned()
58 }
59}
60
61impl Value for RRule<Unvalidated> {
62 fn value_type(&self) -> Option<&'static str> {
63 Some("RECUR")
64 }
65
66 fn value(&self) -> String {
67 self.to_string()
68 }
69}
70
71impl<V: Value> Value for Vec<V> {
72 fn value_type(&self) -> Option<&'static str> {
73 self.first().and_then(Value::value_type)
74 }
75
76 fn value(&self) -> String {
77 self.iter().map(Value::value).join(",")
78 }
79
80 fn utc_or_local(self) -> Self {
81 self.into_iter().map(Value::utc_or_local).collect()
82 }
83}