use std::collections::HashMap;
use crate::{
configuration_provider::ConfigurationProvider,
value::number::Number,
value::Value,
};
pub struct EnvironmentVariablesProvider {
prefix: Option<String>,
}
impl EnvironmentVariablesProvider {
pub fn new() -> Self {
EnvironmentVariablesProvider { prefix: None }
}
pub fn prefixed(prefix: impl ToString) -> Self {
EnvironmentVariablesProvider {
prefix: Some(prefix.to_string()),
}
}
}
impl ConfigurationProvider for EnvironmentVariablesProvider {
fn provide(&self) -> Value {
let map = std::env::vars()
.filter_map(|(k, v)| {
let key = match &self.prefix {
Some(prefix) => match k.strip_prefix(prefix) {
Some(trimmed) => trimmed.to_string(),
None => return None,
},
None => k,
};
let value: Option<Value> = parse_env_var_value(&v);
Some((key, value.unwrap_or(Value::String(v))))
})
.collect::<HashMap<String, Value>>();
Value::Map(map)
}
}
fn parse_env_var_value(v: &str) -> Option<Value> {
if let Ok(parsed_value) = v.parse::<bool>() {
return Some(Value::Bool(parsed_value));
}
if let Ok(parsed_value) = v.parse::<u64>() {
return Some(Value::Number(Number::UInteger(parsed_value)));
}
if let Ok(parsed_value) = v.parse::<i64>() {
return Some(Value::Number(Number::Integer(parsed_value)));
}
if let Ok(parsed_value) = v.parse::<f64>() {
return Some(Value::Number(Number::Float(parsed_value)));
}
None
}