use std::collections::HashMap;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ConfgrError {
#[error("Config File IO Error: {0}")]
File(#[from] std::io::Error),
#[error("Configured filepath does not exist.")]
NoFilePath,
#[error("Config Error: {0}")]
Config(#[from] config::ConfigError),
}
pub trait Merge {
fn merge(self, other: Self) -> Self;
}
pub trait Empty {
fn empty() -> Self;
}
pub trait FromEnv {
fn from_env() -> Self;
fn get_env_keys() -> HashMap<String, String>;
}
pub trait FromFile: Sized {
fn from_file() -> Result<Self, ConfgrError>;
fn check_file() -> Result<(), ConfgrError>;
fn get_file_path() -> Option<String>;
}
pub trait Confgr
where
Self: Sized,
{
type Layer: Default + FromEnv + Merge + FromFile + From<Self> + Into<Self>;
fn load_config() -> Self {
let file_layer = match Self::deserialize_from_file() {
Ok(file_layer) => file_layer,
Err(_e) => Self::Layer::default(),
};
let default_layer = Self::Layer::default();
let env_layer = Self::Layer::from_env();
env_layer.merge(file_layer.merge(default_layer)).into()
}
fn deserialize_from_file() -> Result<Self::Layer, ConfgrError> {
Self::Layer::from_file()
}
fn check_file() -> Result<(), ConfgrError> {
Self::Layer::check_file()
}
fn get_env_keys() -> HashMap<String, String> {
Self::Layer::get_env_keys()
}
fn get_file_path() -> Option<String> {
Self::Layer::get_file_path()
}
}