use crate::prelude::*; use std::io::{Read as _, Write as _}; use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; #[derive(serde::Serialize, serde::Deserialize, Default, Debug)] pub struct Db { pub access_token: Option, pub refresh_token: Option, pub iterations: Option, pub protected_key: Option, pub ciphers: Vec, } impl Db { pub fn new() -> Self { Self::default() } pub fn load(email: &str) -> Result { let mut fh = std::fs::File::open(Self::filename(email)) .context(crate::error::LoadDb)?; let mut json = String::new(); fh.read_to_string(&mut json).context(crate::error::LoadDb)?; let slf: Self = serde_json::from_str(&json).context(crate::error::LoadDbJson)?; Ok(slf) } pub async fn load_async(email: &str) -> Result { let mut fh = tokio::fs::File::open(Self::filename(email)) .await .context(crate::error::LoadDbAsync)?; let mut json = String::new(); fh.read_to_string(&mut json) .await .context(crate::error::LoadDbAsync)?; let slf: Self = serde_json::from_str(&json).context(crate::error::LoadDbJson)?; Ok(slf) } // XXX need to make this atomic pub fn save(&self, email: &str) -> Result<()> { let filename = Self::filename(email); std::fs::create_dir_all(filename.parent().unwrap()) .context(crate::error::SaveDb)?; let mut fh = std::fs::File::create(filename).context(crate::error::SaveDb)?; fh.write_all( serde_json::to_string(self) .context(crate::error::SaveDbJson)? .as_bytes(), ) .context(crate::error::SaveDb)?; Ok(()) } // XXX need to make this atomic pub async fn save_async(&self, email: &str) -> Result<()> { let filename = Self::filename(email); tokio::fs::create_dir_all(filename.parent().unwrap()) .await .context(crate::error::SaveDbAsync)?; let mut fh = tokio::fs::File::create(filename) .await .context(crate::error::SaveDbAsync)?; fh.write_all( serde_json::to_string(self) .context(crate::error::SaveDbJson)? .as_bytes(), ) .await .context(crate::error::SaveDbAsync)?; Ok(()) } pub fn remove(email: &str) -> Result<()> { let filename = Self::filename(email); std::fs::remove_file(filename).context(crate::error::RemoveDb)?; Ok(()) } fn filename(email: &str) -> std::path::PathBuf { crate::dirs::cache_dir().join(format!("{}.json", email)) } }