use crate::{
util::accumulate_child_keys, ConfigurationBuilder, ConfigurationProvider, ConfigurationSource,
LoadResult, Value,
};
use std::collections::HashMap;
use std::env::vars;
#[derive(Default)]
pub struct EnvironmentVariablesConfigurationProvider {
prefix: String,
data: HashMap<String, (String, Value)>,
}
impl EnvironmentVariablesConfigurationProvider {
pub fn new(prefix: String) -> Self {
Self {
prefix,
data: HashMap::with_capacity(0),
}
}
}
impl ConfigurationProvider for EnvironmentVariablesConfigurationProvider {
fn get(&self, key: &str) -> Option<Value> {
self.data.get(&key.to_uppercase()).map(|t| t.1.clone())
}
fn load(&mut self) -> LoadResult {
let mut data = HashMap::new();
let prefix = self.prefix.to_uppercase();
let prefix_len = self.prefix.len();
for (key, value) in vars() {
if key.to_uppercase().starts_with(&prefix) {
let new_key = key[prefix_len..].to_string();
data.insert(new_key.to_uppercase().replace("__", ":"), (new_key, value.into()));
}
}
data.shrink_to_fit();
self.data = data;
Ok(())
}
fn child_keys(&self, earlier_keys: &mut Vec<String>, parent_path: Option<&str>) {
accumulate_child_keys(&self.data, earlier_keys, parent_path)
}
}
#[derive(Default)]
pub struct EnvironmentVariablesConfigurationSource {
pub prefix: String,
}
impl EnvironmentVariablesConfigurationSource {
pub fn new(prefix: &str) -> Self {
Self {
prefix: prefix.to_owned(),
}
}
}
impl ConfigurationSource for EnvironmentVariablesConfigurationSource {
fn build(&self, _builder: &dyn ConfigurationBuilder) -> Box<dyn ConfigurationProvider> {
Box::new(EnvironmentVariablesConfigurationProvider::new(
self.prefix.clone(),
))
}
}
pub mod ext {
use super::*;
pub trait EnvironmentVariablesExtensions {
fn add_env_vars(&mut self) -> &mut Self;
fn add_env_vars_with_prefix(&mut self, prefix: &str) -> &mut Self;
}
impl EnvironmentVariablesExtensions for dyn ConfigurationBuilder + '_ {
fn add_env_vars(&mut self) -> &mut Self {
self.add_env_vars_with_prefix("")
}
fn add_env_vars_with_prefix(&mut self, prefix: &str) -> &mut Self {
self.add(Box::new(EnvironmentVariablesConfigurationSource::new(
prefix,
)));
self
}
}
impl<T: ConfigurationBuilder> EnvironmentVariablesExtensions for T {
fn add_env_vars(&mut self) -> &mut Self {
self.add_env_vars_with_prefix("")
}
fn add_env_vars_with_prefix(&mut self, prefix: &str) -> &mut Self {
self.add(Box::new(EnvironmentVariablesConfigurationSource::new(
prefix,
)));
self
}
}
}