use crate::config::Config;
use figment::Figment;
use figment::providers::{Env, Format, Serialized, Toml};
use serde::Deserialize;
use std::fmt::Debug;
use std::io;
use std::path::Path;
use tracing::info;
const ENVIRONMENT_VARIABLE_PREFIX: &str = "HTSGET_";
#[derive(Debug)]
pub enum Parser<'a> {
String(&'a str),
Path(&'a Path),
}
impl Parser<'_> {
pub fn deserialize_config_into<T>(&self) -> io::Result<T>
where
for<'de> T: Deserialize<'de> + Debug,
{
let config = Figment::from(Serialized::defaults(Config::default()))
.merge(match self {
Parser::String(string) => Toml::string(string),
Parser::Path(path) => Toml::file(path),
})
.merge(
Env::prefixed(ENVIRONMENT_VARIABLE_PREFIX)
.filter(|k| k != "config")
.map(|k| {
k.as_str()
.to_lowercase()
.replace("ticket_server_", "ticket_server.")
.replace("data_server_", "data_server.")
.replace("cors_", "cors.")
.replace("tls_", "tls.")
.replace("http_", "http.")
.replace("auth_", "auth.")
.into()
}),
)
.extract()
.map_err(|err| io::Error::other(format!("failed to parse config: {err}")))?;
info!(config = ?config, "config created");
Ok(config)
}
}
pub fn from_path<T>(path: &Path) -> io::Result<T>
where
for<'a> T: Deserialize<'a> + Debug,
{
Parser::Path(path).deserialize_config_into()
}
pub fn from_str<T>(str: &str) -> io::Result<T>
where
for<'a> T: Deserialize<'a> + Debug,
{
Parser::String(str).deserialize_config_into()
}