Skip to main content

rustical_store/
combined_calendar_store.rs

1use crate::{
2    Calendar, CalendarStore, CalendarStorePruneDeleted,
3    calendar_store::{CalendarQuery, CalendarReadStore, CalendarWriteStore},
4};
5use async_trait::async_trait;
6use rustical_ical::CalendarObject;
7use std::{collections::HashMap, sync::Arc};
8
9pub trait PrefixedCalendarStore: CalendarStore {
10    const PREFIX: &'static str;
11}
12
13#[derive(Clone)]
14pub struct CombinedCalendarStore {
15    stores: HashMap<&'static str, Arc<dyn CalendarStore>>,
16    default: Arc<dyn CalendarStore>,
17}
18
19impl CombinedCalendarStore {
20    pub fn new(default: Arc<dyn CalendarStore>) -> Self {
21        Self {
22            stores: HashMap::new(),
23            default,
24        }
25    }
26
27    #[must_use]
28    pub fn with_store<CS: PrefixedCalendarStore + CalendarStore + 'static>(
29        mut self,
30        store: Arc<CS>,
31    ) -> Self {
32        let store: Arc<dyn CalendarStore> = store as Arc<dyn CalendarStore>;
33        self.stores.insert(CS::PREFIX, store);
34        self
35    }
36
37    fn store_for_id(&self, id: &str) -> Arc<dyn CalendarStore> {
38        self.stores
39            .iter()
40            .find(|&(prefix, _store)| id.starts_with(prefix))
41            .map_or_else(|| self.default.clone(), |(_prefix, store)| store.clone())
42    }
43}
44
45#[async_trait]
46impl CalendarReadStore for CombinedCalendarStore {
47    #[inline]
48    async fn get_calendar(
49        &self,
50        principal: &str,
51        id: &str,
52        show_deleted: bool,
53    ) -> Result<crate::Calendar, crate::Error> {
54        self.store_for_id(id)
55            .get_calendar(principal, id, show_deleted)
56            .await
57    }
58
59    async fn sync_changes(
60        &self,
61        principal: &str,
62        cal_id: &str,
63        synctoken: i64,
64    ) -> Result<(Vec<(String, CalendarObject)>, Vec<String>, i64), crate::Error> {
65        self.store_for_id(cal_id)
66            .sync_changes(principal, cal_id, synctoken)
67            .await
68    }
69
70    async fn calendar_query(
71        &self,
72        principal: &str,
73        cal_id: &str,
74        query: CalendarQuery,
75    ) -> Result<Vec<(String, CalendarObject)>, crate::Error> {
76        self.store_for_id(cal_id)
77            .calendar_query(principal, cal_id, query)
78            .await
79    }
80
81    async fn calendar_metadata(
82        &self,
83        principal: &str,
84        cal_id: &str,
85    ) -> Result<crate::CollectionMetadata, crate::Error> {
86        self.store_for_id(cal_id)
87            .calendar_metadata(principal, cal_id)
88            .await
89    }
90
91    async fn get_objects(
92        &self,
93        principal: &str,
94        cal_id: &str,
95    ) -> Result<Vec<(String, CalendarObject)>, crate::Error> {
96        self.store_for_id(cal_id)
97            .get_objects(principal, cal_id)
98            .await
99    }
100
101    async fn get_object(
102        &self,
103        principal: &str,
104        cal_id: &str,
105        object_id: &str,
106        show_deleted: bool,
107    ) -> Result<rustical_ical::CalendarObject, crate::Error> {
108        self.store_for_id(cal_id)
109            .get_object(principal, cal_id, object_id, show_deleted)
110            .await
111    }
112
113    async fn get_calendars(&self, principal: &str) -> Result<Vec<crate::Calendar>, crate::Error> {
114        let mut calendars = self.default.get_calendars(principal).await?;
115        for store in self.stores.values() {
116            calendars.extend(store.get_calendars(principal).await?);
117        }
118        Ok(calendars)
119    }
120
121    async fn get_deleted_calendars(
122        &self,
123        principal: &str,
124    ) -> Result<Vec<crate::Calendar>, crate::Error> {
125        let mut calendars = self.default.get_deleted_calendars(principal).await?;
126        for store in self.stores.values() {
127            calendars.extend(store.get_deleted_calendars(principal).await?);
128        }
129        Ok(calendars)
130    }
131
132    fn is_read_only(&self, cal_id: &str) -> bool {
133        self.store_for_id(cal_id).is_read_only(cal_id)
134    }
135}
136
137#[async_trait]
138impl CalendarWriteStore for CombinedCalendarStore {
139    async fn update_calendar(
140        &self,
141        principal: &str,
142        id: &str,
143        calendar: Calendar,
144    ) -> Result<(), crate::Error> {
145        self.store_for_id(id)
146            .update_calendar(principal, id, calendar)
147            .await
148    }
149
150    async fn insert_calendar(&self, calendar: crate::Calendar) -> Result<(), crate::Error> {
151        self.store_for_id(&calendar.id)
152            .insert_calendar(calendar)
153            .await
154    }
155
156    async fn delete_calendar(
157        &self,
158        principal: &str,
159        name: &str,
160        use_trashbin: bool,
161    ) -> Result<(), crate::Error> {
162        self.store_for_id(name)
163            .delete_calendar(principal, name, use_trashbin)
164            .await
165    }
166
167    async fn restore_calendar(&self, principal: &str, name: &str) -> Result<(), crate::Error> {
168        self.store_for_id(name)
169            .restore_calendar(principal, name)
170            .await
171    }
172
173    async fn import_calendar(
174        &self,
175        calendar: crate::Calendar,
176        objects: Vec<CalendarObject>,
177        merge_existing: bool,
178    ) -> Result<(), crate::Error> {
179        self.store_for_id(&calendar.id)
180            .import_calendar(calendar, objects, merge_existing)
181            .await
182    }
183
184    async fn restore_object(
185        &self,
186        principal: &str,
187        cal_id: &str,
188        object_id: &str,
189    ) -> Result<(), crate::Error> {
190        self.store_for_id(cal_id)
191            .restore_object(principal, cal_id, object_id)
192            .await
193    }
194
195    async fn put_objects(
196        &self,
197        principal: &str,
198        cal_id: &str,
199        objects: Vec<(String, CalendarObject)>,
200        overwrite: bool,
201    ) -> Result<(), crate::Error> {
202        self.store_for_id(cal_id)
203            .put_objects(principal, cal_id, objects, overwrite)
204            .await
205    }
206
207    async fn delete_object(
208        &self,
209        principal: &str,
210        cal_id: &str,
211        object_id: &str,
212        use_trashbin: bool,
213    ) -> Result<(), crate::Error> {
214        self.store_for_id(cal_id)
215            .delete_object(principal, cal_id, object_id, use_trashbin)
216            .await
217    }
218}
219
220#[async_trait]
221impl CalendarStorePruneDeleted for CombinedCalendarStore {
222    async fn prune_deleted_calendars(&self, before: chrono::NaiveDate) -> Result<(), crate::Error> {
223        self.default.prune_deleted_calendars(before).await?;
224        for cal in self.stores.values() {
225            cal.prune_deleted_calendars(before).await?;
226        }
227        Ok(())
228    }
229
230    async fn prune_deleted_objects(&self, before: chrono::NaiveDate) -> Result<(), crate::Error> {
231        self.default.prune_deleted_objects(before).await?;
232        for cal in self.stores.values() {
233            cal.prune_deleted_objects(before).await?;
234        }
235        Ok(())
236    }
237}