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

@@ -67,7 +67,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
]
[[package]]
@@ -150,9 +150,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.4.0"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223"
[[package]]
name = "cc"
@@ -171,9 +171,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.27"
version = "0.4.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f56b4c72906975ca04becb8a30e102dfecddd0c06181e3e95ddc444be28881f8"
checksum = "defd4e7873dbddba6c7c91e199c7fcb946abc4a6a4ac3195400bcfb01b5de877"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -340,6 +340,12 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
[[package]]
name = "finl_unicode"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6"
[[package]]
name = "flume"
version = "0.10.14"
@@ -572,9 +578,9 @@ dependencies = [
[[package]]
name = "itertools"
version = "0.10.5"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
dependencies = [
"either",
]
@@ -659,9 +665,9 @@ dependencies = [
[[package]]
name = "memchr"
version = "2.5.0"
version = "2.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
[[package]]
name = "minimal-lexical"
@@ -759,9 +765,9 @@ dependencies = [
[[package]]
name = "object"
version = "0.32.0"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
@@ -833,7 +839,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
]
[[package]]
@@ -973,7 +979,6 @@ dependencies = [
"anyhow",
"async-trait",
"serde",
"serde_json",
"sha2",
"sqlx",
"tokio",
@@ -982,9 +987,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.10"
version = "0.38.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed6248e1caa625eb708e266e06159f135e8c26f2bb7ceb72dc4b2766d0340964"
checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453"
dependencies = [
"bitflags 2.4.0",
"errno",
@@ -1022,7 +1027,7 @@ checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
]
[[package]]
@@ -1138,9 +1143,9 @@ dependencies = [
[[package]]
name = "sqlformat"
version = "0.2.1"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e"
checksum = "6b7b278788e7be4d0d29c0f39497a0eef3fba6bbc8e70d8bf7fde46edeaa9e85"
dependencies = [
"itertools",
"nom",
@@ -1356,10 +1361,11 @@ dependencies = [
[[package]]
name = "stringprep"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3737bde7edce97102e0e2b15365bf7a20bfdb5f60f4f9e8d7004258a51a8da"
checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6"
dependencies = [
"finl_unicode",
"unicode-bidi",
"unicode-normalization",
]
@@ -1383,9 +1389,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.29"
version = "2.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
checksum = "718fa2415bcb8d8bd775917a1bf12a7931b6dfa890753378538118181e0cb398"
dependencies = [
"proc-macro2",
"quote",
@@ -1407,22 +1413,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.47"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.47"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
]
[[package]]
@@ -1495,7 +1501,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
]
[[package]]
@@ -1511,9 +1517,9 @@ dependencies = [
[[package]]
name = "toml"
version = "0.7.6"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542"
checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
dependencies = [
"serde",
"serde_spanned",
@@ -1532,9 +1538,9 @@ dependencies = [
[[package]]
name = "toml_edit"
version = "0.19.14"
version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap",
"serde",
@@ -1564,7 +1570,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
]
[[package]]
@@ -1671,7 +1677,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
"wasm-bindgen-shared",
]
@@ -1693,7 +1699,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.29",
"syn 2.0.31",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]

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(())
}
}