use error::*; use path; use std::collections::HashMap; use std::fmt::Debug; use std::str::FromStr; use value::{Value, ValueKind}; /// Describes a generic _source_ of configuration properties. pub trait Source: Debug { fn clone_into_box(&self) -> Box; /// Collect all configuration properties available from this source and return /// a HashMap. fn collect(&self) -> Result>; fn collect_to(&self, cache: &mut Value) -> Result<()> { let props = match self.collect() { Ok(props) => props, Err(error) => { return Err(error); } }; for (key, val) in &props { match path::Expression::from_str(key) { // Set using the path Ok(expr) => expr.set(cache, val.clone()), // Set diretly anyway _ => path::Expression::Identifier(key.clone()).set(cache, val.clone()), } } Ok(()) } } impl Clone for Box { fn clone(&self) -> Box { self.clone_into_box() } } impl Source for Vec> { fn clone_into_box(&self) -> Box { Box::new((*self).clone()) } fn collect(&self) -> Result> { let mut cache: Value = HashMap::::new().into(); for source in self { source.collect_to(&mut cache)?; } if let ValueKind::Table(table) = cache.kind { Ok(table) } else { unreachable!(); } } } impl Source for Vec where T: Source + Sync + Send, T: Clone, T: 'static, { fn clone_into_box(&self) -> Box { Box::new((*self).clone()) } fn collect(&self) -> Result> { let mut cache: Value = HashMap::::new().into(); for source in self { source.collect_to(&mut cache)?; } if let ValueKind::Table(table) = cache.kind { Ok(table) } else { unreachable!(); } } }