1use crate::{util::cmp_keys, Configuration, ConfigurationBuilder, ConfigurationProvider, ConfigurationSource, Value};
2use std::borrow::Borrow;
3use tokens::ChangeToken;
4
5#[cfg(not(feature = "async"))]
6type Rc<T> = std::rc::Rc<T>;
7
8#[cfg(feature = "async")]
9type Rc<T> = std::sync::Arc<T>;
10
11pub struct ChainedConfigurationProvider {
13 configuration: Rc<dyn Configuration>,
14}
15
16impl ChainedConfigurationProvider {
17 pub fn new(configuration: Rc<dyn Configuration>) -> Self {
23 Self { configuration }
24 }
25}
26
27impl ConfigurationProvider for ChainedConfigurationProvider {
28 fn get(&self, key: &str) -> Option<Value> {
29 self.configuration.get(key)
30 }
31
32 fn reload_token(&self) -> Box<dyn ChangeToken> {
33 self.configuration.reload_token()
34 }
35
36 fn child_keys(&self, earlier_keys: &mut Vec<String>, parent_path: Option<&str>) {
37 if let Some(path) = parent_path {
38 earlier_keys.extend(
39 self.configuration
40 .section(path)
41 .children()
42 .iter()
43 .map(|c| c.key().to_owned()),
44 );
45 } else {
46 earlier_keys.extend(self.configuration.children().iter().map(|c| c.key().to_owned()));
47 }
48
49 earlier_keys.sort_by(|k1, k2| cmp_keys(k1, k2));
50 }
51}
52
53pub struct ChainedConfigurationSource {
55 configuration: Rc<dyn Configuration>,
56}
57
58impl ChainedConfigurationSource {
59 pub fn new(configuration: Box<dyn Configuration>) -> Self {
65 Self {
66 configuration: Rc::from(configuration),
67 }
68 }
69
70 pub fn configuration(&self) -> &dyn Configuration {
72 self.configuration.borrow()
73 }
74}
75
76impl ConfigurationSource for ChainedConfigurationSource {
77 fn build(&self, _builder: &dyn ConfigurationBuilder) -> Box<dyn ConfigurationProvider> {
78 Box::new(ChainedConfigurationProvider::new(self.configuration.clone()))
79 }
80}
81
82impl From<Box<dyn Configuration>> for ChainedConfigurationSource {
83 fn from(value: Box<dyn Configuration>) -> Self {
84 Self::new(value)
85 }
86}
87
88impl From<Rc<dyn Configuration>> for ChainedConfigurationSource {
89 fn from(value: Rc<dyn Configuration>) -> Self {
90 Self { configuration: value }
91 }
92}
93
94pub mod ext {
95
96 use super::*;
97
98 pub trait ChainedBuilderExtensions {
100 fn add_configuration(&mut self, configuration: Box<dyn Configuration>) -> &mut Self;
106 }
107
108 impl ChainedBuilderExtensions for dyn ConfigurationBuilder + '_ {
109 fn add_configuration(&mut self, configuration: Box<dyn Configuration>) -> &mut Self {
110 self.add(Box::new(ChainedConfigurationSource::new(configuration)));
111 self
112 }
113 }
114
115 impl<T: ConfigurationBuilder> ChainedBuilderExtensions for T {
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}