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
9pub struct ChainedConfigurationProvider {
11 configuration: Rc<dyn Configuration>,
12}
13
14impl ChainedConfigurationProvider {
15 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
56pub struct ChainedConfigurationSource {
58 configuration: Rc<dyn Configuration>,
59}
60
61impl ChainedConfigurationSource {
62 pub fn new(configuration: Box<dyn Configuration>) -> Self {
68 Self {
69 configuration: Rc::from(configuration),
70 }
71 }
72
73 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 pub trait ChainedBuilderExtensions {
107 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}