config_maint/
source.rs

1use error::*;
2use path;
3use std::collections::HashMap;
4use std::fmt::Debug;
5use std::str::FromStr;
6use value::{Value, ValueKind};
7
8/// Describes a generic _source_ of configuration properties.
9pub trait Source: Debug {
10    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync>;
11
12    /// Collect all configuration properties available from this source and return
13    /// a HashMap.
14    fn collect(&self) -> Result<HashMap<String, Value>>;
15
16    fn collect_to(&self, cache: &mut Value) -> Result<()> {
17        let props = match self.collect() {
18            Ok(props) => props,
19            Err(error) => {
20                return Err(error);
21            }
22        };
23
24        for (key, val) in &props {
25            match path::Expression::from_str(key) {
26                // Set using the path
27                Ok(expr) => expr.set(cache, val.clone()),
28
29                // Set diretly anyway
30                _ => path::Expression::Identifier(key.clone()).set(cache, val.clone()),
31            }
32        }
33
34        Ok(())
35    }
36}
37
38impl Clone for Box<dyn Source + Send + Sync> {
39    fn clone(&self) -> Box<dyn Source + Send + Sync> {
40        self.clone_into_box()
41    }
42}
43
44impl Source for Vec<Box<dyn Source + Send + Sync>> {
45    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
46        Box::new((*self).clone())
47    }
48
49    fn collect(&self) -> Result<HashMap<String, Value>> {
50        let mut cache: Value = HashMap::<String, Value>::new().into();
51
52        for source in self {
53            source.collect_to(&mut cache)?;
54        }
55
56        if let ValueKind::Table(table) = cache.kind {
57            Ok(table)
58        } else {
59            unreachable!();
60        }
61    }
62}
63
64impl<T> Source for Vec<T>
65where
66    T: Source + Sync + Send,
67    T: Clone,
68    T: 'static,
69{
70    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
71        Box::new((*self).clone())
72    }
73
74    fn collect(&self) -> Result<HashMap<String, Value>> {
75        let mut cache: Value = HashMap::<String, Value>::new().into();
76
77        for source in self {
78            source.collect_to(&mut cache)?;
79        }
80
81        if let ValueKind::Table(table) = cache.kind {
82            Ok(table)
83        } else {
84            unreachable!();
85        }
86    }
87}