use serde::{Deserialize, Serialize};
use std::{
path::PathBuf,
sync::{Arc, LazyLock, RwLock},
};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("failed to read or write")]
IoError(#[from] std::io::Error),
#[error("failed to serialize or deserialize")]
SerdeError(#[from] serde_json::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
static STATE: LazyLock<Arc<RwLock<PersistentState>>> =
LazyLock::new(|| Arc::new(RwLock::new(read().unwrap_or_default())));
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct PersistentState {
pub provider: String,
}
impl Default for PersistentState {
fn default() -> Self {
Self {
provider: "asimov-default-provider".into(),
}
}
}
fn get_file_path() -> Result<PathBuf> {
let current_dir = std::env::current_exe()?;
Ok(current_dir.with_file_name("persistence.json"))
}
fn read() -> Result<PersistentState> {
let path = get_file_path()?;
let file = std::fs::File::open(path)?;
let reader = std::io::BufReader::new(file);
Ok(serde_json::from_reader(reader)?)
}
fn write(state: &PersistentState) -> Result<()> {
let path = get_file_path()?;
let file = std::fs::File::create(path)?;
let writer = std::io::BufWriter::new(file);
serde_json::to_writer(writer, state)?;
Ok(())
}
pub(crate) fn get_ref() -> Arc<RwLock<PersistentState>> {
STATE.clone()
}
pub fn get() -> PersistentState {
STATE.read().unwrap().clone()
}
pub fn set<F>(x: F) -> Result<()>
where
F: FnOnce(&mut PersistentState),
{
let mut state = STATE.write().unwrap();
x(&mut state);
write(&state)
}