broxus_util/
config.rs

1use serde::Deserialize;
2
3pub fn read_config<P, T>(path: P) -> Result<T, ConfigError>
4where
5    P: AsRef<std::path::Path>,
6    for<'de> T: Deserialize<'de>,
7{
8    let data = std::fs::read_to_string(path)?;
9    let re = regex::Regex::new(r"\$\{([a-zA-Z_][0-9a-zA-Z_]*)\}").unwrap();
10    let result = re.replace_all(&data, |caps: &regex::Captures| {
11        match std::env::var(&caps[1]) {
12            Ok(value) => value,
13            Err(_) => {
14                eprintln!("WARN: Environment variable {} was not set", &caps[1]);
15                String::default()
16            }
17        }
18    });
19
20    config::Config::builder()
21        .add_source(config::File::from_str(
22            result.as_ref(),
23            config::FileFormat::Yaml,
24        ))
25        .build()
26        .map_err(ConfigError::BuildError)?
27        .try_deserialize()
28        .map_err(ConfigError::ParseError)
29}
30
31#[derive(thiserror::Error, Debug)]
32pub enum ConfigError {
33    #[error("failed to read config")]
34    UnableToRead(#[from] std::io::Error),
35    #[error("failed to build config")]
36    BuildError(#[source] config::ConfigError),
37    #[error("failed to parse config")]
38    ParseError(#[source] config::ConfigError),
39}