outsource toml store into own file

This commit is contained in:
Lennart
2023-09-13 12:46:08 +02:00
parent 7caec0f157
commit 759c4afee9
5 changed files with 135 additions and 117 deletions

View File

@@ -1,10 +1,7 @@
use std::collections::HashMap;
use anyhow::{anyhow, Result};
use anyhow::Result;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use tokio::{fs::File, io::AsyncWriteExt};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct Event {
@@ -13,6 +10,9 @@ pub struct Event {
}
impl Event {
pub fn from_ics(uid: String, ics: String) -> Self {
Self { uid, ics }
}
pub fn get_uid(&self) -> &str {
&self.uid
}
@@ -28,14 +28,14 @@ impl Event {
}
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[derive(Debug, Default, Clone, Deserialize, Serialize)]
pub struct Calendar {
pub id: String,
pub name: Option<String>,
pub owner: String,
pub description: Option<String>,
pub color: Option<String>,
pub ics: String,
pub timezone: Option<String>,
}
impl Calendar {}
@@ -44,84 +44,10 @@ impl Calendar {}
pub trait CalendarStore: Send + Sync + 'static {
async fn get_calendar(&self, id: &str) -> Result<Calendar>;
async fn get_calendars(&self, owner: &str) -> Result<Vec<Calendar>>;
async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<()>;
async fn get_events(&self, cid: &str) -> Result<Vec<Event>>;
async fn get_event(&self, cid: &str, uid: &str) -> Result<Event>;
async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<()>;
async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<()>;
}
#[derive(Debug, Deserialize, Serialize)]
pub struct TomlCalendarStore {
calendars: HashMap<String, Calendar>,
events: HashMap<String, HashMap<String, Event>>,
path: String,
}
impl TomlCalendarStore {
pub fn new(path: String) -> Self {
TomlCalendarStore {
calendars: HashMap::new(),
events: HashMap::new(),
path,
}
}
pub async fn save(&self) -> Result<()> {
let mut file = File::create(&self.path).await?;
let output = toml::to_string_pretty(&self)?;
file.write_all(output.as_bytes()).await?;
Ok(())
}
}
#[async_trait]
impl CalendarStore for TomlCalendarStore {
async fn get_calendar(&self, id: &str) -> Result<Calendar> {
Ok(self.calendars.get(id).ok_or(anyhow!("not found"))?.clone())
}
async fn get_calendars(&self, user: &str) -> Result<Vec<Calendar>> {
Ok(self
.calendars
.values()
.filter(|Calendar { owner, .. }| owner == user)
.cloned()
.collect())
}
async fn get_events(&self, cid: &str) -> Result<Vec<Event>> {
if let Some(events) = self.events.get(cid) {
Ok(events.values().cloned().collect())
} else {
Ok(Vec::new())
}
}
async fn get_event(&self, cid: &str, uid: &str) -> Result<Event> {
let events = self.events.get(cid).ok_or(anyhow!("not found"))?;
Ok(events.get(uid).ok_or(anyhow!("not found"))?.clone())
}
async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<()> {
let events = self.events.entry(cid).or_insert(HashMap::new());
events.insert(
uid.clone(),
Event {
uid,
ics,
summary: None,
},
);
self.save().await.unwrap();
Ok(())
}
async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<()> {
if let Some(events) = self.events.get_mut(cid) {
events.remove(uid);
self.save().await?;
}
Ok(())
}
}

View File

@@ -1,2 +1,3 @@
pub mod calendar;
pub mod models;
pub mod toml_store;

View File

@@ -0,0 +1,85 @@
use crate::calendar::{Calendar, CalendarStore, Event};
use anyhow::{anyhow, Result};
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::{hash_map::Entry, HashMap};
use tokio::{fs::File, io::AsyncWriteExt};
#[derive(Debug, Deserialize, Serialize)]
pub struct TomlCalendarStore {
calendars: HashMap<String, Calendar>,
events: HashMap<String, HashMap<String, Event>>,
path: String,
}
impl TomlCalendarStore {
pub fn new(path: String) -> Self {
TomlCalendarStore {
calendars: HashMap::new(),
events: HashMap::new(),
path,
}
}
pub async fn save(&self) -> Result<()> {
let mut file = File::create(&self.path).await?;
let output = toml::to_string_pretty(&self)?;
file.write_all(output.as_bytes()).await?;
Ok(())
}
}
#[async_trait]
impl CalendarStore for TomlCalendarStore {
async fn get_calendar(&self, id: &str) -> Result<Calendar> {
Ok(self.calendars.get(id).ok_or(anyhow!("not found"))?.clone())
}
async fn get_calendars(&self, user: &str) -> Result<Vec<Calendar>> {
Ok(self
.calendars
.values()
.filter(|Calendar { owner, .. }| owner == user)
.cloned()
.collect())
}
async fn insert_calendar(&mut self, cid: String, calendar: Calendar) -> Result<()> {
match self.calendars.entry(cid) {
Entry::Occupied(_) => Err(anyhow!("calendar already exists")),
Entry::Vacant(v) => {
v.insert(calendar);
self.save().await.unwrap();
Ok(())
}
}
}
async fn get_events(&self, cid: &str) -> Result<Vec<Event>> {
if let Some(events) = self.events.get(cid) {
Ok(events.values().cloned().collect())
} else {
Ok(Vec::new())
}
}
async fn get_event(&self, cid: &str, uid: &str) -> Result<Event> {
let events = self.events.get(cid).ok_or(anyhow!("not found"))?;
Ok(events.get(uid).ok_or(anyhow!("not found"))?.clone())
}
async fn upsert_event(&mut self, cid: String, uid: String, ics: String) -> Result<()> {
let events = self.events.entry(cid).or_insert(HashMap::new());
events.insert(uid.clone(), Event::from_ics(uid, ics));
self.save().await.unwrap();
Ok(())
}
async fn delete_event(&mut self, cid: &str, uid: &str) -> Result<()> {
if let Some(events) = self.events.get_mut(cid) {
events.remove(uid);
self.save().await?;
}
Ok(())
}
}