use serde::{Deserialize, Serialize};
use std::{
env, fs,
io::Result as IoResult,
path::PathBuf
};
use ron::ser::PrettyConfig;
#[derive(Clone, Copy)]
pub enum ConfigType {
Toml,
Ron
}
pub trait Config: Serialize + Default + for <'de> Deserialize<'de> {
const FILE_NAME: &'static str;
const TYPE: ConfigType = ConfigType::Toml;
fn get_save_dir() -> PathBuf;
fn get_full_path() -> PathBuf {
Self::get_save_dir().join(Self::FILE_NAME)
}
#[track_caller]
fn load() -> Self {
let file_str = if let Ok(file) = fs::read_to_string(Self::get_full_path()) {
file
}
else {
let config = Self::default();
config.save().expect("Unable to load config!");
return config;
};
match Self::TYPE {
ConfigType::Toml => {
if let Ok(cfg) = toml::from_str(&file_str) {
cfg
}
else { Self::default() }
}
ConfigType::Ron => {
if let Ok(cfg) = ron::from_str(&file_str) {
cfg
}
else { Self::default() }
}
}
}
#[track_caller]
fn save(&self) -> IoResult<()> {
let save_str = match Self::TYPE {
ConfigType::Toml => toml::to_string_pretty(&self).unwrap(),
ConfigType::Ron => {
let cfg = PrettyConfig::default();
ron::ser::to_string_pretty(&self, cfg).unwrap()
}
};
fs::create_dir_all(Self::get_save_dir())?;
fs::write(Self::get_full_path(), save_str)
}
#[track_caller]
fn get_config_root() -> PathBuf {
if let Ok(xdg_config_home) = env::var("XDG_CONFIG_HOME") {
xdg_config_home.into()
}
else {
PathBuf::from(
env::var("HOME").expect("Where is your home folder?!")
)
.join(".config")
}
}
}