1use crate::{
2 util::accumulate_child_keys, ConfigurationBuilder, ConfigurationProvider, ConfigurationSource, LoadResult, Value,
3};
4use std::collections::HashMap;
5use std::env::vars;
6
7#[derive(Default)]
9pub struct EnvironmentVariablesConfigurationProvider {
10 prefix: String,
11 data: HashMap<String, (String, Value)>,
12}
13
14impl EnvironmentVariablesConfigurationProvider {
15 pub fn new(prefix: String) -> Self {
21 Self {
22 prefix,
23 data: HashMap::with_capacity(0),
24 }
25 }
26}
27
28impl ConfigurationProvider for EnvironmentVariablesConfigurationProvider {
29 fn get(&self, key: &str) -> Option<Value> {
30 self.data.get(&key.to_uppercase()).map(|t| t.1.clone())
31 }
32
33 fn load(&mut self) -> LoadResult {
34 let mut data = HashMap::new();
35 let prefix = self.prefix.to_uppercase();
36 let prefix_len = self.prefix.len();
37
38 for (key, value) in vars() {
39 if key.to_uppercase().starts_with(&prefix) {
40 let new_key = key[prefix_len..].to_string();
41 data.insert(new_key.to_uppercase().replace("__", ":"), (new_key, value.into()));
42 }
43 }
44
45 data.shrink_to_fit();
46 self.data = data;
47 Ok(())
48 }
49
50 fn child_keys(&self, earlier_keys: &mut Vec<String>, parent_path: Option<&str>) {
51 accumulate_child_keys(&self.data, earlier_keys, parent_path)
52 }
53}
54
55#[derive(Default)]
57pub struct EnvironmentVariablesConfigurationSource {
58 pub prefix: String,
60}
61
62impl EnvironmentVariablesConfigurationSource {
63 pub fn new(prefix: &str) -> Self {
69 Self {
70 prefix: prefix.to_owned(),
71 }
72 }
73}
74
75impl ConfigurationSource for EnvironmentVariablesConfigurationSource {
76 fn build(&self, _builder: &dyn ConfigurationBuilder) -> Box<dyn ConfigurationProvider> {
77 Box::new(EnvironmentVariablesConfigurationProvider::new(self.prefix.clone()))
78 }
79}
80
81pub mod ext {
82
83 use super::*;
84
85 pub trait EnvironmentVariablesExtensions {
87 fn add_env_vars(&mut self) -> &mut Self;
89
90 fn add_env_vars_with_prefix(&mut self, prefix: &str) -> &mut Self;
97 }
98
99 impl EnvironmentVariablesExtensions for dyn ConfigurationBuilder + '_ {
100 fn add_env_vars(&mut self) -> &mut Self {
101 self.add_env_vars_with_prefix("")
102 }
103
104 fn add_env_vars_with_prefix(&mut self, prefix: &str) -> &mut Self {
105 self.add(Box::new(EnvironmentVariablesConfigurationSource::new(prefix)));
106 self
107 }
108 }
109
110 impl<T: ConfigurationBuilder> EnvironmentVariablesExtensions for T {
111 fn add_env_vars(&mut self) -> &mut Self {
112 self.add_env_vars_with_prefix("")
113 }
114
115 fn add_env_vars_with_prefix(&mut self, prefix: &str) -> &mut Self {
116 self.add(Box::new(EnvironmentVariablesConfigurationSource::new(prefix)));
117 self
118 }
119 }
120}