use super::*;
pub trait ConfigFileType {
fn extension() -> &'static str;
fn serialize<C: Serialize, W: Write>(config: &C, writer: &mut W) -> anyhow::Result<()>;
fn deserialize<C: DeserializeOwned, R: Read>(reader: &mut R) -> anyhow::Result<C>;
}
pub trait ValueType {
type Value;
}
pub trait DefaultFileSave {}
pub trait DefaultFileLoad {}
impl<T> SerializableConfig for T
where
T: FileSystemConfig + Serialize,
{
fn save(&self) -> anyhow::Result<()> {
let dir = T::dir();
debug!("Saving config to {}", dir.to_string_lossy());
if !dir.exists() {
std::fs::create_dir_all(dir)?;
}
T::write_file()?.write_config(self)
}
}
impl<T> LoadableConfig for T
where
T: FileSystemConfig + DefaultFileLoad + DeserializeOwned,
{
fn load() -> anyhow::Result<Self>
where
Self: Sized,
{
T::read_file()?.read_config()
}
}
impl<C: FileSystemConfig + DeserializeOwned> ConfigReader<C> for File {
fn read_config(mut self) -> anyhow::Result<C> {
C::ConfigType::deserialize(&mut self)
}
}
impl<C: FileSystemConfig + Serialize> ConfigWriter<C> for File {
fn write_config(&mut self, config: &C) -> anyhow::Result<()> {
C::ConfigType::serialize(config, self)
}
}
pub trait FileSystemConfig {
type ConfigType: ConfigFileType;
const CONFIG_DIR: &'static str = ".";
const FILENAME: &'static str = DEFAULT_FILENAME;
fn dir() -> PathBuf {
std::env::var("CONFIG_DIR")
.ok()
.unwrap_or(Self::CONFIG_DIR.to_string())
.into()
}
fn read_file() -> anyhow::Result<File> {
OpenOptions::new()
.read(true)
.open(Self::dir().join(format!("{}.{}", Self::FILENAME, Self::ConfigType::extension())))
.map_err(|e| anyhow!(e))
}
fn write_file() -> anyhow::Result<File> {
OpenOptions::new()
.create(true)
.write(true)
.truncate(true)
.open(Self::dir().join(format!("{}.{}", Self::FILENAME, Self::ConfigType::extension())))
.map_err(|e| anyhow!(e))
}
}
#[cfg(feature = "ron_config")]
#[cfg(not(feature = "toml_config"))]
#[cfg(not(feature = "json_config"))]
impl<T> FileSystemConfig for T
where
T: crate::core::Actor<crate::core::NullSupervisor>,
{
type ConfigType = super::RONConfig;
}
#[cfg(feature = "toml_config")]
#[cfg(not(feature = "ron_config"))]
#[cfg(not(feature = "json_config"))]
impl<T> FileSystemConfig for T
where
T: crate::core::Actor<crate::core::NullSupervisor>,
{
type ConfigType = super::TOMLConfig;
}
#[cfg(feature = "json_config")]
#[cfg(not(feature = "ron_config"))]
#[cfg(not(feature = "toml_config"))]
impl<T> FileSystemConfig for T
where
T: crate::core::Actor<crate::core::NullSupervisor>,
{
type ConfigType = super::JSONConfig;
}