config/
chained.rs

1use crate::{
2    util::cmp_keys, Configuration, ConfigurationBuilder, ConfigurationProvider,
3    ConfigurationSource, Value,
4};
5use std::borrow::Borrow;
6use std::rc::Rc;
7use tokens::ChangeToken;
8
9/// Represents a chained [`ConfigurationProvider`](crate::ConfigurationProvider).
10pub struct ChainedConfigurationProvider {
11    configuration: Rc<dyn Configuration>,
12}
13
14impl ChainedConfigurationProvider {
15    /// Initializes a new chained configuration provider.
16    ///
17    /// # Arguments
18    ///
19    /// * `configuration` - The [`Configuration`](crate::Configuration) to chain
20    pub fn new(configuration: Rc<dyn Configuration>) -> Self {
21        Self { configuration }
22    }
23}
24
25impl ConfigurationProvider for ChainedConfigurationProvider {
26    fn get(&self, key: &str) -> Option<Value> {
27        self.configuration.get(key)
28    }
29
30    fn reload_token(&self) -> Box<dyn ChangeToken> {
31        self.configuration.reload_token()
32    }
33
34    fn child_keys(&self, earlier_keys: &mut Vec<String>, parent_path: Option<&str>) {
35        if let Some(path) = parent_path {
36            earlier_keys.extend(
37                self.configuration
38                    .section(path)
39                    .children()
40                    .iter()
41                    .map(|c| c.key().to_owned()),
42            );
43        } else {
44            earlier_keys.extend(
45                self.configuration
46                    .children()
47                    .iter()
48                    .map(|c| c.key().to_owned()),
49            );
50        }
51
52        earlier_keys.sort_by(|k1, k2| cmp_keys(k1, k2));
53    }
54}
55
56/// Represents a chained [`ConfigurationSource`](crate::ConfigurationSource).
57pub struct ChainedConfigurationSource {
58    configuration: Rc<dyn Configuration>,
59}
60
61impl ChainedConfigurationSource {
62    /// Initializes a new chained configuration sources.
63    ///
64    /// # Arguments
65    ///
66    /// * `configuration` - The [`Configuration`](crate::Configuration) to chain
67    pub fn new(configuration: Box<dyn Configuration>) -> Self {
68        Self {
69            configuration: Rc::from(configuration),
70        }
71    }
72
73    /// Gets the associated [`Configuration`](crate::Configuration).
74    pub fn configuration(&self) -> &dyn Configuration {
75        self.configuration.borrow()
76    }
77}
78
79impl ConfigurationSource for ChainedConfigurationSource {
80    fn build(&self, _builder: &dyn ConfigurationBuilder) -> Box<dyn ConfigurationProvider> {
81        Box::new(ChainedConfigurationProvider::new(
82            self.configuration.clone(),
83        ))
84    }
85}
86
87impl From<Box<dyn Configuration>> for ChainedConfigurationSource {
88    fn from(value: Box<dyn Configuration>) -> Self {
89        Self::new(value)
90    }
91}
92
93impl From<Rc<dyn Configuration>> for ChainedConfigurationSource {
94    fn from(value: Rc<dyn Configuration>) -> Self {
95        Self {
96            configuration: value,
97        }
98    }
99}
100
101pub mod ext {
102
103    use super::*;
104
105    /// Defines extension methods for [`ConfigurationBuilder`](crate::ConfigurationBuilder).
106    pub trait ChainedBuilderExtensions {
107        /// Adds the existing configuration.
108        ///
109        /// # Arguments
110        ///
111        /// * `configuration` - The existing [`Configuration`](crate::Configuration) to add
112        fn add_configuration(&mut self, configuration: Box<dyn Configuration>) -> &mut Self;
113    }
114
115    impl ChainedBuilderExtensions for dyn ConfigurationBuilder + '_ {
116        fn add_configuration(&mut self, configuration: Box<dyn Configuration>) -> &mut Self {
117            self.add(Box::new(ChainedConfigurationSource::new(configuration)));
118            self
119        }
120    }
121
122    impl<T: ConfigurationBuilder> ChainedBuilderExtensions for T {
123        fn add_configuration(&mut self, configuration: Box<dyn Configuration>) -> &mut Self {
124            self.add(Box::new(ChainedConfigurationSource::new(configuration)));
125            self
126        }
127    }
128}