1use serde_json::{Value, json};
8use std::collections::HashMap;
9use std::env;
10
11use super::ConfigError;
12use super::ConfigProvider;
13
14#[derive(Debug)]
16pub struct EnvConfigProvider {
17 prefix: String,
19 cache: HashMap<String, String>,
21}
22
23impl EnvConfigProvider {
24 pub fn new(prefix: &str) -> Self {
26 let mut provider = Self {
27 prefix: prefix.to_string(),
28 cache: HashMap::new(),
29 };
30
31 provider.refresh_cache();
33
34 provider
35 }
36
37 pub fn refresh_cache(&mut self) {
39 self.cache.clear();
40
41 for (key, value) in env::vars() {
42 if key.starts_with(&self.prefix) {
43 let config_key = key[self.prefix.len()..].to_lowercase();
45 let config_key = config_key.replace('_', ".");
47
48 self.cache.insert(config_key, value);
49 }
50 }
51 }
52
53 fn parse_value_to_json(&self, value: &str) -> Result<Value, ConfigError> {
55 if let Ok(json_value) = serde_json::from_str(value) {
57 return Ok(json_value);
58 }
59
60 if value.eq_ignore_ascii_case("true") {
64 return Ok(json!(true));
65 } else if value.eq_ignore_ascii_case("false") {
66 return Ok(json!(false));
67 }
68
69 if let Ok(int_val) = value.parse::<i64>() {
71 return Ok(json!(int_val));
72 }
73
74 if let Ok(float_val) = value.parse::<f64>() {
75 return Ok(json!(float_val));
76 }
77
78 Ok(json!(value))
80 }
81}
82
83impl Default for EnvConfigProvider {
84 fn default() -> Self {
85 Self::new("FOXY_")
86 }
87}
88
89impl ConfigProvider for EnvConfigProvider {
90 fn get_raw(&self, key: &str) -> Result<Option<Value>, ConfigError> {
91 match self.cache.get(key) {
92 Some(value) => self.parse_value_to_json(value).map(Some),
93 None => Ok(None),
94 }
95 }
96
97 fn has(&self, key: &str) -> bool {
98 self.cache.contains_key(key)
99 }
100
101 fn provider_name(&self) -> &str {
102 "env"
103 }
104}