1use error::*;
2use source::Source;
3use std::collections::HashMap;
4use std::env;
5use value::{Value, ValueKind};
6
7#[derive(Clone, Debug)]
8pub struct Environment {
9 prefix: Option<String>,
17
18 separator: Option<String>,
22
23 ignore_empty: bool,
25}
26
27impl Environment {
28 pub fn new() -> Self {
29 Environment::default()
30 }
31
32 pub fn with_prefix(s: &str) -> Self {
33 Environment {
34 prefix: Some(s.into()),
35 ..Environment::default()
36 }
37 }
38
39 pub fn prefix(mut self, s: &str) -> Self {
40 self.prefix = Some(s.into());
41 self
42 }
43
44 pub fn separator(mut self, s: &str) -> Self {
45 self.separator = Some(s.into());
46 self
47 }
48
49 pub fn ignore_empty(mut self, ignore: bool) -> Self {
50 self.ignore_empty = ignore;
51 self
52 }
53}
54
55impl Default for Environment {
56 fn default() -> Environment {
57 Environment {
58 prefix: None,
59 separator: None,
60 ignore_empty: false,
61 }
62 }
63}
64
65impl Source for Environment {
66 fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
67 Box::new((*self).clone())
68 }
69
70 fn collect(&self) -> Result<HashMap<String, Value>> {
71 let mut m = HashMap::new();
72 let uri: String = "the environment".into();
73
74 let separator = match self.separator {
75 Some(ref separator) => separator,
76 _ => "",
77 };
78
79 let prefix_pattern = match self.prefix {
81 Some(ref prefix) => Some(prefix.clone() + "_"),
82 _ => None,
83 };
84
85 for (key, value) in env::vars() {
86 if self.ignore_empty && value.is_empty() {
88 continue;
89 }
90
91 let mut key = key.to_string();
92
93 if let Some(ref prefix_pattern) = prefix_pattern {
95 if key
96 .to_lowercase()
97 .starts_with(&prefix_pattern.to_lowercase())
98 {
99 key = key[prefix_pattern.len()..].to_string();
101 } else {
102 continue;
104 }
105 }
106
107 if !separator.is_empty() {
109 key = key.replace(separator, ".");
110 }
111
112 m.insert(
113 key.to_lowercase(),
114 Value::new(Some(&uri), ValueKind::String(value)),
115 );
116 }
117
118 Ok(m)
119 }
120}