use std::{ fs::{create_dir_all, exists, read, write, File}, path::{Path, PathBuf}, }; use anyhow::{Context, Result}; use serde::{Deserialize, Serialize}; const SCHIST_CACHE_DIR: &'static str = "schist"; const SCHIST_CACHE_FILENAME: &'static str = "schist_cache.toml"; #[derive(Default, Deserialize, Serialize)] pub struct Cache { pub last_open_file: Option, } pub struct CacheKeys { pub last_open_file: &'static str, } pub const CACHE_KEYS: CacheKeys = CacheKeys { last_open_file: "last_open_file", }; pub fn get_cache() -> Result { const CONTEXT: &'static str = "Failed to get cache"; let cache_filepath = get_and_touch_cache_filepath().context(CONTEXT)?; let cache_toml = read(&cache_filepath).context(CONTEXT)?; let cache_table: toml::Table = toml::from_slice(&cache_toml).context(CONTEXT)?; Ok(Cache { last_open_file: cache_table .get(&CACHE_KEYS.last_open_file.to_string()) .map(|o| o.as_str().map(str::to_string)) .flatten(), }) } pub fn put_to_cache(key: &str, value: T) -> Result<()> where toml::Value: From, { const CONTEXT: &'static str = "Failed to save cache"; let cache_filepath = get_and_touch_cache_filepath().context(CONTEXT)?; let curr_cache_toml = read(&cache_filepath).context(CONTEXT)?; let mut cache: toml::Table = toml::from_slice(&curr_cache_toml).context(CONTEXT)?; cache.insert(key.to_string(), value.into()); let new_cache_toml = toml::to_string(&cache).context(CONTEXT)?; write(cache_filepath, new_cache_toml).context(CONTEXT)?; Ok(()) } pub fn remove_from_cache(key: &str) -> Result<()> { const CONTEXT: &'static str = "Failed to remove key from cache"; let cache_filepath = get_and_touch_cache_filepath().context(CONTEXT)?; let curr_cache_toml = read(&cache_filepath).context(CONTEXT)?; let mut cache: toml::Table = toml::from_slice(&curr_cache_toml).context(CONTEXT)?; cache.remove(key); let new_cache_toml = toml::to_string(&cache).context(CONTEXT)?; write(cache_filepath, new_cache_toml).context(CONTEXT)?; Ok(()) } fn get_and_touch_cache_filepath() -> Result { let cache_dir = get_and_make_schist_cache_dir()?; let cache_filepath = cache_dir.join(Path::new(SCHIST_CACHE_FILENAME)); let does_cache_file_exist = exists(cache_filepath.clone()) .context("Failed to determine the existence of Schist's cache file")?; if !does_cache_file_exist { File::create(cache_filepath.clone()).context("Failed to create a new cache file")?; } Ok(cache_filepath) } fn get_and_make_schist_cache_dir() -> anyhow::Result { let cache_dir = dirs::cache_dir().context("Failed to get app cache directory")?; let schist_cache_dir = cache_dir.join(Path::new(SCHIST_CACHE_DIR)); create_dir_all(&schist_cache_dir).context(format!( "Failed to create app cache directory at {}", schist_cache_dir.display() ))?; println!("Found app cache directory at {:?}", schist_cache_dir); Ok(schist_cache_dir) }