summaryrefslogtreecommitdiffstats
path: root/src/config.rs
diff options
context:
space:
mode:
authorRyan Leckey <ryan@launchbadge.com>2017-06-03 01:21:10 -0700
committerRyan Leckey <ryan@launchbadge.com>2017-06-03 01:21:10 -0700
commitc26907b3ecf2b139fe61bf1403c952b85285ae02 (patch)
tree1cb1f275e9942c08c3d6f085de63bba43c652130 /src/config.rs
parent028aaf5247dd3cd184b250afdba235d683525f97 (diff)
Add set and set_default (and deep merging)
Diffstat (limited to 'src/config.rs')
-rw-r--r--src/config.rs75
1 files changed, 68 insertions, 7 deletions
diff --git a/src/config.rs b/src/config.rs
index 4d24a1d..ad5421b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -3,14 +3,15 @@ use serde::de::Deserialize;
use error::*;
use source::Source;
-use value::Value;
+
+use value::{Value, ValueWithKey};
use path;
enum ConfigKind {
// A mutable configuration. This is the default.
Mutable {
- defaults: HashMap<String, Value>,
- overrides: HashMap<String, Value>,
+ defaults: HashMap<path::Expression, Value>,
+ overrides: HashMap<path::Expression, Value>,
sources: Vec<Box<Source + Send + Sync>>,
},
@@ -71,7 +72,29 @@ impl Config {
ref overrides,
ref sources,
ref defaults,
- } => sources[0].collect()?,
+ } => {
+ let mut cache: Value = HashMap::<String, Value>::new().into();
+
+ // Add defaults
+ for (key, val) in defaults {
+ key.set(&mut cache, val.clone());
+ }
+
+ // Add sources
+ for source in sources {
+ let props = source.collect()?;
+ for (key, val) in &props {
+ path::Expression::Identifier(key.clone()).set(&mut cache, val.clone());
+ }
+ }
+
+ // Add overrides
+ for (key, val) in overrides {
+ key.set(&mut cache, val.clone());
+ }
+
+ cache
+ },
ConfigKind::Frozen => {
return Err(ConfigError::Frozen);
@@ -81,11 +104,11 @@ impl Config {
Ok(())
}
- pub fn deserialize<T: Deserialize>(&self) -> Result<T> {
+ pub fn deserialize<'de, T: Deserialize<'de>>(&self) -> Result<T> {
return T::deserialize(self.cache.clone());
}
- pub fn get<T: Deserialize>(&self, key: &str) -> Result<T> {
+ pub fn get<'de, T: Deserialize<'de>>(&self, key: &'de str) -> Result<T> {
// Parse the key into a path expression
let expr: path::Expression = key.to_lowercase().parse()?;
@@ -95,10 +118,48 @@ impl Config {
match value {
Some(value) => {
// Deserialize the received value into the requested type
- T::deserialize(value)
+ T::deserialize(ValueWithKey::new(value, key))
}
None => Err(ConfigError::NotFound(key.into())),
}
}
+
+ pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<()>
+ where T: Into<Value>
+ {
+ match self.kind {
+ ConfigKind::Mutable {
+ ref mut defaults,
+ ..
+ } => {
+ defaults.insert(key.parse()?, value.into());
+ }
+
+ ConfigKind::Frozen => {
+ return Err(ConfigError::Frozen)
+ }
+ };
+
+ self.refresh()
+ }
+
+ pub fn set<T>(&mut self, key: &str, value: T) -> Result<()>
+ where T: Into<Value>
+ {
+ match self.kind {
+ ConfigKind::Mutable {
+ ref mut overrides,
+ ..
+ } => {
+ overrides.insert(key.parse()?, value.into());
+ }
+
+ ConfigKind::Frozen => {
+ return Err(ConfigError::Frozen)
+ }
+ };
+
+ self.refresh()
+ }
}