dinglebit_config/
env.rs

1//! Configuration from the environment variables.
2
3use std::env;
4
5use crate::Config;
6
7#[derive(Debug, PartialEq)]
8pub struct Environment {
9    prefix: String,
10}
11
12impl Environment {
13    /// Create a new environment configuration which will prefix keys
14    /// with the given prefix and an underscore (e.g. prefix = "foo"
15    /// => "foo_*"). An empty prefix will not prepend anything.
16    ///
17    /// Getting a value from the environment will try to make the key
18    /// more environment-variable-like . '.' and '/' are replaced with
19    /// '_' and everything is upper-cased. If the prefix is 'foo',
20    /// then a get for 'my.app.secret' would look for
21    /// 'FOO_MY_APP_SECRET'.
22    pub fn new(prefix: &str) -> Self {
23        let prefix = match prefix.len() > 0 {
24            true => prefix.to_owned() + "_",
25            false => "".to_string(),
26        };
27        Self { prefix: prefix }
28    }
29}
30
31impl Config for Environment {
32    /// Get a value from the environment using the given key. '.' and
33    /// '/' are replaced with '_' and everything is upper-cased. If the
34    /// prefix is 'foo', then a get for 'my.app.secret' would look for
35    /// 'FOO_MY_APP_SECRET'.
36    fn get(&self, key: &str) -> Option<String> {
37        // Make the key more environment variable like.
38        let key = self.prefix.to_owned() + key;
39        let key = key.replace(".", "_").replace("/", "_");
40        let key = key.to_uppercase();
41
42        match env::var(key) {
43            Ok(value) => Some(value),
44            Err(_) => None,
45        }
46    }
47}
48
49#[cfg(test)]
50mod tests {
51    use crate::env::Environment;
52    use crate::Config;
53    use std::env;
54
55    #[test]
56    fn new() {
57        assert_eq!(
58            Environment::new("test"),
59            Environment {
60                prefix: "test_".to_string()
61            }
62        );
63        assert_eq!(
64            Environment::new(""),
65            Environment {
66                prefix: "".to_string()
67            }
68        );
69    }
70
71    #[test]
72    fn get() {
73        let e = Environment::new("test_get");
74        env::set_var("TEST_GET_FOO_BAR", "baz");
75        assert_eq!(e.get("foo.bar"), Some("baz".to_string()));
76        assert_eq!(e.get("foo/bar"), Some("baz".to_string()));
77        env::remove_var("TEST_GET_FOO_BAR");
78        assert_eq!(e.get("foo.bar"), None);
79    }
80}