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