1 use std::fmt::Debug;
2 
3 use crate::builder::{ConfigBuilder, DefaultState};
4 use serde::de::Deserialize;
5 use serde::ser::Serialize;
6 
7 use crate::error::{ConfigError, Result};
8 use crate::map::Map;
9 use crate::path;
10 use crate::ser::ConfigSerializer;
11 use crate::source::Source;
12 use crate::value::{Table, Value};
13 
14 /// A prioritized configuration repository. It maintains a set of
15 /// configuration sources, fetches values to populate those, and provides
16 /// them according to the source's priority.
17 #[derive(Clone, Debug)]
18 pub struct Config {
19     defaults: Map<path::Expression, Value>,
20     overrides: Map<path::Expression, Value>,
21     sources: Vec<Box<dyn Source + Send + Sync>>,
22 
23     /// Root of the cached configuration.
24     pub cache: Value,
25 }
26 
27 impl Default for Config {
default() -> Self28     fn default() -> Self {
29         Self {
30             defaults: Default::default(),
31             overrides: Default::default(),
32             sources: Default::default(),
33             cache: Value::new(None, Table::new()),
34         }
35     }
36 }
37 
38 impl Config {
new(value: Value) -> Self39     pub(crate) fn new(value: Value) -> Self {
40         Self {
41             cache: value,
42             ..Self::default()
43         }
44     }
45 
46     /// Creates new [`ConfigBuilder`] instance
builder() -> ConfigBuilder<DefaultState>47     pub fn builder() -> ConfigBuilder<DefaultState> {
48         ConfigBuilder::<DefaultState>::default()
49     }
50 
51     /// Merge in a configuration property source.
52     #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
merge<T>(&mut self, source: T) -> Result<&mut Self> where T: 'static, T: Source + Send + Sync,53     pub fn merge<T>(&mut self, source: T) -> Result<&mut Self>
54     where
55         T: 'static,
56         T: Source + Send + Sync,
57     {
58         self.sources.push(Box::new(source));
59 
60         #[allow(deprecated)]
61         self.refresh()
62     }
63 
64     /// Merge in a configuration property source.
65     #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
with_merged<T>(mut self, source: T) -> Result<Self> where T: 'static, T: Source + Send + Sync,66     pub fn with_merged<T>(mut self, source: T) -> Result<Self>
67     where
68         T: 'static,
69         T: Source + Send + Sync,
70     {
71         self.sources.push(Box::new(source));
72 
73         #[allow(deprecated)]
74         self.refresh()?;
75         Ok(self)
76     }
77 
78     /// Refresh the configuration cache with fresh
79     /// data from added sources.
80     ///
81     /// Configuration is automatically refreshed after a mutation
82     /// operation (`set`, `merge`, `set_default`, etc.).
83     #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
refresh(&mut self) -> Result<&mut Self>84     pub fn refresh(&mut self) -> Result<&mut Self> {
85         self.cache = {
86             let mut cache: Value = Map::<String, Value>::new().into();
87 
88             // Add defaults
89             for (key, val) in &self.defaults {
90                 key.set(&mut cache, val.clone());
91             }
92 
93             // Add sources
94             self.sources.collect_to(&mut cache)?;
95 
96             // Add overrides
97             for (key, val) in &self.overrides {
98                 key.set(&mut cache, val.clone());
99             }
100 
101             cache
102         };
103 
104         Ok(self)
105     }
106 
107     /// Set a default `value` at `key`
108     #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Self> where T: Into<Value>,109     pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Self>
110     where
111         T: Into<Value>,
112     {
113         self.defaults.insert(key.parse()?, value.into());
114 
115         #[allow(deprecated)]
116         self.refresh()
117     }
118 
119     /// Set an overwrite
120     ///
121     /// This function sets an overwrite value.
122     /// The overwrite `value` is written to the `key` location on every `refresh()`
123     ///
124     /// # Warning
125     ///
126     /// Errors if config is frozen
127     #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
set<T>(&mut self, key: &str, value: T) -> Result<&mut Self> where T: Into<Value>,128     pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Self>
129     where
130         T: Into<Value>,
131     {
132         self.overrides.insert(key.parse()?, value.into());
133 
134         #[allow(deprecated)]
135         self.refresh()
136     }
137 
138     #[deprecated(since = "0.12.0", note = "please use 'ConfigBuilder' instead")]
set_once(&mut self, key: &str, value: Value) -> Result<()>139     pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
140         let expr: path::Expression = key.parse()?;
141 
142         // Traverse the cache using the path to (possibly) retrieve a value
143         if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
144             **val = value;
145         } else {
146             expr.set(&mut self.cache, value);
147         }
148         Ok(())
149     }
150 
get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T>151     pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
152         // Parse the key into a path expression
153         let expr: path::Expression = key.parse()?;
154 
155         // Traverse the cache using the path to (possibly) retrieve a value
156         let value = expr.get(&self.cache).cloned();
157 
158         match value {
159             Some(value) => {
160                 // Deserialize the received value into the requested type
161                 T::deserialize(value).map_err(|e| e.extend_with_key(key))
162             }
163 
164             None => Err(ConfigError::NotFound(key.into())),
165         }
166     }
167 
get_string(&self, key: &str) -> Result<String>168     pub fn get_string(&self, key: &str) -> Result<String> {
169         self.get(key).and_then(Value::into_string)
170     }
171 
get_int(&self, key: &str) -> Result<i64>172     pub fn get_int(&self, key: &str) -> Result<i64> {
173         self.get(key).and_then(Value::into_int)
174     }
175 
get_float(&self, key: &str) -> Result<f64>176     pub fn get_float(&self, key: &str) -> Result<f64> {
177         self.get(key).and_then(Value::into_float)
178     }
179 
get_bool(&self, key: &str) -> Result<bool>180     pub fn get_bool(&self, key: &str) -> Result<bool> {
181         self.get(key).and_then(Value::into_bool)
182     }
183 
get_table(&self, key: &str) -> Result<Map<String, Value>>184     pub fn get_table(&self, key: &str) -> Result<Map<String, Value>> {
185         self.get(key).and_then(Value::into_table)
186     }
187 
get_array(&self, key: &str) -> Result<Vec<Value>>188     pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
189         self.get(key).and_then(Value::into_array)
190     }
191 
192     /// Attempt to deserialize the entire configuration into the requested type.
try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T>193     pub fn try_deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
194         T::deserialize(self)
195     }
196 
197     /// Attempt to serialize the entire configuration from the given type.
try_from<T: Serialize>(from: &T) -> Result<Self>198     pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
199         let mut serializer = ConfigSerializer::default();
200         from.serialize(&mut serializer)?;
201         Ok(serializer.output)
202     }
203 
204     #[deprecated(since = "0.7.0", note = "please use 'try_deserialize' instead")]
deserialize<'de, T: Deserialize<'de>>(self) -> Result<T>205     pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
206         self.try_deserialize()
207     }
208 }
209 
210 impl Source for Config {
clone_into_box(&self) -> Box<dyn Source + Send + Sync>211     fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
212         Box::new((*self).clone())
213     }
214 
collect(&self) -> Result<Map<String, Value>>215     fn collect(&self) -> Result<Map<String, Value>> {
216         self.cache.clone().into_table()
217     }
218 }
219