use crate::CalendarStore; use async_trait::async_trait; use std::{collections::HashMap, sync::Arc}; pub trait PrefixedCalendarStore: CalendarStore { const PREFIX: &'static str; } #[derive(Clone)] pub struct CombinedCalendarStore { stores: HashMap<&'static str, Arc>, default: Arc, } impl CombinedCalendarStore { pub fn new(default: Arc) -> Self { Self { stores: HashMap::new(), default, } } #[must_use] pub fn with_store(mut self, store: Arc) -> Self { let store: Arc = store; self.stores.insert(CS::PREFIX, store); self } fn store_for_id(&self, id: &str) -> Arc { self.stores .iter() .find(|&(prefix, _store)| id.starts_with(prefix)) .map_or_else(|| self.default.clone(), |(_prefix, store)| store.clone()) } } #[async_trait] impl CalendarStore for CombinedCalendarStore { #[inline] async fn get_calendar( &self, principal: &str, id: &str, show_deleted: bool, ) -> Result { self.store_for_id(id) .get_calendar(principal, id, show_deleted) .await } async fn update_calendar( &self, principal: String, id: String, calendar: crate::Calendar, ) -> Result<(), crate::Error> { self.store_for_id(&id) .update_calendar(principal, id, calendar) .await } async fn insert_calendar(&self, calendar: crate::Calendar) -> Result<(), crate::Error> { self.store_for_id(&calendar.id) .insert_calendar(calendar) .await } async fn delete_calendar( &self, principal: &str, name: &str, use_trashbin: bool, ) -> Result<(), crate::Error> { self.store_for_id(name) .delete_calendar(principal, name, use_trashbin) .await } async fn restore_calendar(&self, principal: &str, name: &str) -> Result<(), crate::Error> { self.store_for_id(name) .restore_calendar(principal, name) .await } async fn sync_changes( &self, principal: &str, cal_id: &str, synctoken: i64, ) -> Result<(Vec, Vec, i64), crate::Error> { self.store_for_id(cal_id) .sync_changes(principal, cal_id, synctoken) .await } async fn import_calendar( &self, calendar: crate::Calendar, objects: Vec, merge_existing: bool, ) -> Result<(), crate::Error> { self.store_for_id(&calendar.id) .import_calendar(calendar, objects, merge_existing) .await } async fn calendar_query( &self, principal: &str, cal_id: &str, query: crate::calendar_store::CalendarQuery, ) -> Result, crate::Error> { self.store_for_id(cal_id) .calendar_query(principal, cal_id, query) .await } async fn restore_object( &self, principal: &str, cal_id: &str, object_id: &str, ) -> Result<(), crate::Error> { self.store_for_id(cal_id) .restore_object(principal, cal_id, object_id) .await } async fn calendar_metadata( &self, principal: &str, cal_id: &str, ) -> Result { self.store_for_id(cal_id) .calendar_metadata(principal, cal_id) .await } async fn get_objects( &self, principal: &str, cal_id: &str, ) -> Result, crate::Error> { self.store_for_id(cal_id) .get_objects(principal, cal_id) .await } async fn put_object( &self, principal: String, cal_id: String, object: rustical_ical::CalendarObject, overwrite: bool, ) -> Result<(), crate::Error> { self.store_for_id(&cal_id) .put_object(principal, cal_id, object, overwrite) .await } async fn delete_object( &self, principal: &str, cal_id: &str, object_id: &str, use_trashbin: bool, ) -> Result<(), crate::Error> { self.store_for_id(cal_id) .delete_object(principal, cal_id, object_id, use_trashbin) .await } async fn get_object( &self, principal: &str, cal_id: &str, object_id: &str, show_deleted: bool, ) -> Result { self.store_for_id(cal_id) .get_object(principal, cal_id, object_id, show_deleted) .await } async fn get_calendars(&self, principal: &str) -> Result, crate::Error> { let mut calendars = self.default.get_calendars(principal).await?; for store in self.stores.values() { calendars.extend(store.get_calendars(principal).await?); } Ok(calendars) } async fn get_deleted_calendars( &self, principal: &str, ) -> Result, crate::Error> { let mut calendars = self.default.get_deleted_calendars(principal).await?; for store in self.stores.values() { calendars.extend(store.get_deleted_calendars(principal).await?); } Ok(calendars) } fn is_read_only(&self, cal_id: &str) -> bool { self.store_for_id(cal_id).is_read_only(cal_id) } }