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}