dinglebit_config/
multi.rs

1//! Combine multiple configs to get configuration values from various
2//! places.
3
4use crate::Config;
5
6pub struct MultiConfig {
7    configs: Vec<Box<dyn Config>>,
8}
9
10impl MultiConfig {
11    //! Create a configuration that uses the given list of configs to
12    //! try and get values. If a value isn't found, the next config on
13    //! the list is consulted. This allows your to create a set of
14    //! configs that can override values as needed. For example,
15    //! creating a `MultiConfig` with `!vec[environment,
16    //! instance-config-file, global-config-file, default-values]`
17    //! would provide something like you'd expect in a 12-factor app.
18    pub fn new(configs: Vec<Box<dyn Config>>) -> Self {
19        Self { configs }
20    }
21}
22
23impl Config for MultiConfig {
24    fn get(&self, key: &str) -> Option<String> {
25        for config in self.configs.iter() {
26            match config.get(key) {
27                Some(value) => return Some(value),
28                None => continue,
29            };
30        }
31        None
32    }
33}
34
35#[cfg(test)]
36mod tests {
37    use crate::{multi::MultiConfig, Config};
38
39    #[test]
40    fn multi() {
41        // Create two maps
42        use std::collections::HashMap;
43        let mut m1 = HashMap::new();
44        m1.insert("foo", "bar");
45        m1.insert("bar", "baz");
46        let mut m2 = HashMap::new();
47        m2.insert("foo", "buz");
48        m2.insert("buz", "foo");
49
50        let mc = MultiConfig::new(vec![Box::new(m2), Box::new(m1)]);
51
52        assert_eq!(mc.get("foo"), Some("buz".to_string()));
53        assert_eq!(mc.get("bar"), Some("baz".to_string()));
54        assert_eq!(mc.get("buz"), Some("foo".to_string()));
55    }
56}