use rustbreak::{deser::Yaml, FileDatabase, RustbreakError as DBError}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serenity::{ model::id::GuildId, prelude::{TypeMap, TypeMapKey}, }; use std::{collections::HashMap, path::Path}; /// GuildMap defines the guild-map type. /// It is basically a HashMap from a GuildId to a data structure. pub type GuildMap = HashMap; /// The generic DB type we will be using. pub struct DB(std::marker::PhantomData); /// A short type abbreviation for a FileDatabase. type Database = FileDatabase; impl TypeMapKey for DB { type Value = Database; } impl DB where for<'de> T: Deserialize<'de>, { /// Load the DB from a path. pub fn load_from_path(path: impl AsRef) -> Result, DBError> { Database::::load_from_path(path) } /// Insert into a ShareMap. pub fn insert_into(data: &mut TypeMap, path: impl AsRef) -> Result<(), DBError> { let db = Database::::load_from_path_or_default(path)?; data.insert::>(db); Ok(()) } /// Open a previously inserted DB. pub fn open(data: &TypeMap) -> DBWriteGuard { data.get::().expect("DB initialized").into() } } /// The write guard for our FileDatabase. /// It wraps the FileDatabase in a write-on-drop lock. #[derive(Debug)] pub struct DBWriteGuard<'a, T> where T: Send + Sync + Clone + std::fmt::Debug + Serialize + DeserializeOwned, { db: &'a Database, needs_save: bool, } impl<'a, T> From<&'a Database> for DBWriteGuard<'a, T> where T: Send + Sync + Clone + std::fmt::Debug + Serialize + DeserializeOwned, { fn from(v: &'a Database) -> Self { DBWriteGuard { db: v, needs_save: false, } } } impl<'a, T> DBWriteGuard<'a, T> where T: Send + Sync + Clone + std::fmt::Debug + Serialize + DeserializeOwned, { /// Borrows the FileDatabase. pub fn borrow(&self) -> Result, DBError> { self.db.borrow_data() } /// Borrows the FileDatabase for writing. pub fn borrow_mut(&mut self) -> Result, DBError> { self.needs_save = true; self.db.borrow_data_mut() } } impl<'a, T> Drop for DBWriteGuard<'a, T> where T: Send + Sync + Clone + std::fmt::Debug + Serialize + DeserializeOwned, { fn drop(&mut self) { if self.needs_save { if let Err(e) = self.db.save() { dbg!(e); } } } }