use crate::source::Source;
use crate::item::{SourceLocation, StringItem, Value};
use crate::confpath::ConfPath;
use std::ffi::{OsStr, OsString};
use std::collections::hash_map::HashMap;
use std::fmt;
use std::env;
use std::rc::Rc;
#[derive(Debug)]
struct EnvSourceLocation {
env_name: OsString
}
impl EnvSourceLocation {
pub fn new(env_name: &OsStr) -> Rc<Self> {
Rc::new(Self {
env_name: env_name.to_owned()
})
}
}
impl fmt::Display for EnvSourceLocation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "env:{}", self.env_name.to_string_lossy())
}
}
impl SourceLocation for EnvSourceLocation {}
pub struct Env {
env_mapping: HashMap<ConfPath, OsString>
}
impl Env {
pub fn new(env_mapping: &[(ConfPath, &OsStr)]) -> Box<Self> {
Box::new(Self {
env_mapping: env_mapping.iter().map(|m| (m.0.clone(), m.1.to_owned())).collect()
})
}
}
impl Source for Env {
fn get(&self, key: ConfPath) -> Option<StringItem> {
if let Some(env_name) = self.env_mapping.get(&key) {
env::var(env_name).ok().map(|v| StringItem::from(key, &[Value::new(v, EnvSourceLocation::new(env_name))]))
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Config;
use crate::error::ConfigError;
use crate::item::ValueExtractor;
use std::env;
fn prepare_test_config() -> Config{
env::set_var(OsStr::new("existing_value"), OsStr::new("existing_value"));
let mut c = Config::default();
c.add_source(Env::new(&[
(ConfPath::from(&["testA"]), OsStr::new("existing_value")),
(ConfPath::from(&["testB"]), OsStr::new("non_existant_value"))
]));
c
}
#[test]
fn existing_value() {
let c = prepare_test_config();
assert_eq!((c.get(ConfPath::from(&["testA"])).value() as Result<String, ConfigError>).unwrap(), "existing_value");
}
#[test]
#[should_panic(expected = "ValueNotFound")]
fn non_existant_env_name() {
let c = prepare_test_config();
(c.get(ConfPath::from(&["testB"])).value() as Result<String, ConfigError>).unwrap();
}
#[test]
#[should_panic(expected = "ValueNotFound")]
fn non_existant_value() {
let c = prepare_test_config();
(c.get(ConfPath::from(&["testC"])).value() as Result<String, ConfigError>).unwrap();
}
}