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