aimcal_core/
event.rs

1// SPDX-FileCopyrightText: 2025 Zexin Yuan <aim@yzx9.xyz>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use crate::LooseDateTime;
6use chrono::NaiveDateTime;
7use icalendar::Component;
8use std::{fmt::Display, str::FromStr};
9
10/// Trait representing a calendar event.
11pub trait Event {
12    /// The unique identifier for the event.
13    fn uid(&self) -> &str;
14
15    /// The summary of the event.
16    fn summary(&self) -> &str;
17
18    /// The description of the event, if available.
19    fn description(&self) -> Option<&str>;
20
21    /// The location of the event, if available.
22    fn start(&self) -> Option<LooseDateTime>;
23
24    /// The start date and time of the event, if available.
25    fn end(&self) -> Option<LooseDateTime>;
26
27    /// The status of the event, if available.
28    fn status(&self) -> Option<EventStatus>;
29}
30
31impl Event for icalendar::Event {
32    fn uid(&self) -> &str {
33        self.get_uid().unwrap_or("")
34    }
35
36    fn summary(&self) -> &str {
37        self.get_summary().unwrap_or("")
38    }
39
40    fn description(&self) -> Option<&str> {
41        self.get_description()
42    }
43
44    fn start(&self) -> Option<LooseDateTime> {
45        self.get_start().map(Into::into)
46    }
47
48    fn end(&self) -> Option<LooseDateTime> {
49        self.get_end().map(Into::into)
50    }
51
52    fn status(&self) -> Option<EventStatus> {
53        self.get_status().map(|a| EventStatus::from(&a))
54    }
55}
56
57/// Represents the status of an event, which can be tentative, confirmed, or cancelled.
58#[derive(Debug, Clone, Copy)]
59pub enum EventStatus {
60    /// The event is tentative.
61    Tentative,
62
63    /// The event is confirmed.
64    Confirmed,
65
66    /// The event is cancelled.
67    Cancelled,
68}
69
70const STATUS_TENTATIVE: &str = "TENTATIVE";
71const STATUS_CONFIRMED: &str = "CONFIRMED";
72const STATUS_CANCELLED: &str = "CANCELLED";
73
74impl AsRef<str> for EventStatus {
75    fn as_ref(&self) -> &str {
76        match self {
77            EventStatus::Tentative => STATUS_TENTATIVE,
78            EventStatus::Confirmed => STATUS_CONFIRMED,
79            EventStatus::Cancelled => STATUS_CANCELLED,
80        }
81    }
82}
83
84impl Display for EventStatus {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        write!(f, "{}", self.as_ref())
87    }
88}
89
90impl FromStr for EventStatus {
91    type Err = ();
92
93    fn from_str(value: &str) -> Result<Self, Self::Err> {
94        match value {
95            STATUS_TENTATIVE => Ok(EventStatus::Tentative),
96            STATUS_CONFIRMED => Ok(EventStatus::Confirmed),
97            STATUS_CANCELLED => Ok(EventStatus::Cancelled),
98            _ => Err(()),
99        }
100    }
101}
102
103impl From<&EventStatus> for icalendar::EventStatus {
104    fn from(status: &EventStatus) -> Self {
105        match status {
106            EventStatus::Tentative => icalendar::EventStatus::Tentative,
107            EventStatus::Confirmed => icalendar::EventStatus::Confirmed,
108            EventStatus::Cancelled => icalendar::EventStatus::Cancelled,
109        }
110    }
111}
112
113impl From<&icalendar::EventStatus> for EventStatus {
114    fn from(status: &icalendar::EventStatus) -> Self {
115        match status {
116            icalendar::EventStatus::Tentative => EventStatus::Tentative,
117            icalendar::EventStatus::Confirmed => EventStatus::Confirmed,
118            icalendar::EventStatus::Cancelled => EventStatus::Cancelled,
119        }
120    }
121}
122
123/// Represents conditions for filtering events in a calendar.
124#[derive(Debug, Clone, Copy)]
125pub struct EventConditions {
126    /// The current time to filter events.
127    pub now: NaiveDateTime,
128
129    /// Whether to include only startable events.
130    pub startable: bool,
131}