use serde_json::{Value, json};
use std::collections::HashMap;
use std::env;
use super::ConfigError;
use super::ConfigProvider;
#[derive(Debug)]
pub struct EnvConfigProvider {
prefix: String,
cache: HashMap<String, String>,
}
impl EnvConfigProvider {
pub fn new(prefix: &str) -> Self {
let mut provider = Self {
prefix: prefix.to_string(),
cache: HashMap::new(),
};
provider.refresh_cache();
provider
}
pub fn refresh_cache(&mut self) {
self.cache.clear();
for (key, value) in env::vars() {
if key.starts_with(&self.prefix) {
let config_key = key[self.prefix.len()..].to_lowercase();
let config_key = config_key.replace('_', ".");
self.cache.insert(config_key, value);
}
}
}
fn parse_value_to_json(&self, value: &str) -> Result<Value, ConfigError> {
if let Ok(json_value) = serde_json::from_str(value) {
return Ok(json_value);
}
if value.eq_ignore_ascii_case("true") {
return Ok(json!(true));
} else if value.eq_ignore_ascii_case("false") {
return Ok(json!(false));
}
if let Ok(int_val) = value.parse::<i64>() {
return Ok(json!(int_val));
}
if let Ok(float_val) = value.parse::<f64>() {
return Ok(json!(float_val));
}
Ok(json!(value))
}
}
impl Default for EnvConfigProvider {
fn default() -> Self {
Self::new("FOXY_")
}
}
impl ConfigProvider for EnvConfigProvider {
fn get_raw(&self, key: &str) -> Result<Option<Value>, ConfigError> {
match self.cache.get(key) {
Some(value) => self.parse_value_to_json(value).map(Some),
None => Ok(None),
}
}
fn has(&self, key: &str) -> bool {
self.cache.contains_key(key)
}
fn provider_name(&self) -> &str {
"env"
}
}