1use serde::de::{Deserialize, Deserializer};
2use serde::ser::{Serialize, Serializer};
3use std::collections::HashMap;
4use std::fmt::Debug;
5use std::ops::Deref;
6use std::str::FromStr;
7
8use error::*;
9use ser::ConfigSerializer;
10use source::Source;
11
12use path;
13use value::{Table, Value, ValueKind};
14
15#[derive(Clone, Debug)]
16enum ConfigKind {
17 Mutable {
19 defaults: HashMap<path::Expression, Value>,
20 overrides: HashMap<path::Expression, Value>,
21 sources: Vec<Box<dyn Source + Send + Sync>>,
22 },
23
24 Frozen,
27}
28
29impl Default for ConfigKind {
30 fn default() -> Self {
31 ConfigKind::Mutable {
32 defaults: HashMap::new(),
33 overrides: HashMap::new(),
34 sources: Vec::new(),
35 }
36 }
37}
38
39#[derive(Default, Clone, Debug)]
43pub struct Config {
44 kind: ConfigKind,
45
46 pub cache: Value,
48}
49
50impl Config {
51 pub fn new() -> Self {
52 Self {
53 kind: ConfigKind::default(),
54 cache: Value::new(None, Table::new()),
57 }
58 }
59
60 pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
62 where
63 T: 'static,
64 T: Source + Send + Sync,
65 {
66 match self.kind {
67 ConfigKind::Mutable {
68 ref mut sources, ..
69 } => {
70 sources.push(Box::new(source));
71 }
72
73 ConfigKind::Frozen => {
74 return Err(ConfigError::Frozen);
75 }
76 }
77
78 self.refresh()
79 }
80
81 pub fn refresh(&mut self) -> Result<&mut Config> {
87 self.cache = match self.kind {
88 ConfigKind::Mutable {
90 ref overrides,
91 ref sources,
92 ref defaults,
93 } => {
94 let mut cache: Value = HashMap::<String, Value>::new().into();
95
96 for (key, val) in defaults {
98 key.set(&mut cache, val.clone());
99 }
100
101 sources.collect_to(&mut cache)?;
103
104 for (key, val) in overrides {
106 key.set(&mut cache, val.clone());
107 }
108
109 cache
110 }
111
112 ConfigKind::Frozen => {
113 return Err(ConfigError::Frozen);
114 }
115 };
116
117 Ok(self)
118 }
119
120 pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
121 where
122 T: Into<Value>,
123 {
124 match self.kind {
125 ConfigKind::Mutable {
126 ref mut defaults, ..
127 } => {
128 defaults.insert(key.parse()?, value.into());
129 }
130
131 ConfigKind::Frozen => return Err(ConfigError::Frozen),
132 };
133
134 self.refresh()
135 }
136
137 pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
138 where
139 T: Into<Value>,
140 {
141 match self.kind {
142 ConfigKind::Mutable {
143 ref mut overrides, ..
144 } => {
145 overrides.insert(key.parse()?, value.into());
146 }
147
148 ConfigKind::Frozen => return Err(ConfigError::Frozen),
149 };
150
151 self.refresh()
152 }
153
154 pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
155 let expr: path::Expression = key.parse()?;
157
158 let value = expr.get(&self.cache).cloned();
160
161 match value {
162 Some(value) => {
163 T::deserialize(value).map_err(|e| e.extend_with_key(key))
165 }
166
167 None => Err(ConfigError::NotFound(key.into())),
168 }
169 }
170
171 pub fn get_str(&self, key: &str) -> Result<String> {
172 self.get(key).and_then(Value::into_str)
173 }
174
175 pub fn get_int(&self, key: &str) -> Result<i64> {
176 self.get(key).and_then(Value::into_int)
177 }
178
179 pub fn get_float(&self, key: &str) -> Result<f64> {
180 self.get(key).and_then(Value::into_float)
181 }
182
183 pub fn get_bool(&self, key: &str) -> Result<bool> {
184 self.get(key).and_then(Value::into_bool)
185 }
186
187 pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
188 self.get(key).and_then(Value::into_table)
189 }
190
191 pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
192 self.get(key).and_then(Value::into_array)
193 }
194
195 pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
197 T::deserialize(self)
198 }
199
200 pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
202 let mut serializer = ConfigSerializer::default();
203 from.serialize(&mut serializer)?;
204 Ok(serializer.output)
205 }
206
207 #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
208 pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
209 self.try_into()
210 }
211}
212
213impl Source for Config {
214 fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
215 Box::new((*self).clone())
216 }
217
218 fn collect(&self) -> Result<HashMap<String, Value>> {
219 self.cache.clone().into_table()
220 }
221}