use crate::{ util::cmp_keys, Configuration, ConfigurationBuilder, ConfigurationProvider, ConfigurationSource, Value, }; use std::borrow::Borrow; use std::rc::Rc; use tokens::ChangeToken; /// Represents a chained [`ConfigurationProvider`](crate::ConfigurationProvider). pub struct ChainedConfigurationProvider { configuration: Rc, } impl ChainedConfigurationProvider { /// Initializes a new chained configuration provider. /// /// # Arguments /// /// * `configuration` - The [`Configuration`](crate::Configuration) to chain pub fn new(configuration: Rc) -> Self { Self { configuration } } } impl ConfigurationProvider for ChainedConfigurationProvider { fn get(&self, key: &str) -> Option { self.configuration.get(key) } fn reload_token(&self) -> Box { self.configuration.reload_token() } fn child_keys(&self, earlier_keys: &mut Vec, parent_path: Option<&str>) { if let Some(path) = parent_path { earlier_keys.extend( self.configuration .section(path) .children() .iter() .map(|c| c.key().to_owned()), ); } else { earlier_keys.extend( self.configuration .children() .iter() .map(|c| c.key().to_owned()), ); } earlier_keys.sort_by(|k1, k2| cmp_keys(k1, k2)); } } /// Represents a chained [`ConfigurationSource`](crate::ConfigurationSource). pub struct ChainedConfigurationSource { configuration: Rc, } impl ChainedConfigurationSource { /// Initializes a new chained configuration sources. /// /// # Arguments /// /// * `configuration` - The [`Configuration`](crate::Configuration) to chain pub fn new(configuration: Box) -> Self { Self { configuration: Rc::from(configuration), } } /// Gets the associated [`Configuration`](crate::Configuration). pub fn configuration(&self) -> &dyn Configuration { self.configuration.borrow() } } impl ConfigurationSource for ChainedConfigurationSource { fn build(&self, _builder: &dyn ConfigurationBuilder) -> Box { Box::new(ChainedConfigurationProvider::new( self.configuration.clone(), )) } } impl From> for ChainedConfigurationSource { fn from(value: Box) -> Self { Self::new(value) } } impl From> for ChainedConfigurationSource { fn from(value: Rc) -> Self { Self { configuration: value, } } } pub mod ext { use super::*; /// Defines extension methods for [`ConfigurationBuilder`](crate::ConfigurationBuilder). pub trait ChainedBuilderExtensions { /// Adds the existing configuration. /// /// # Arguments /// /// * `configuration` - The existing [`Configuration`](crate::Configuration) to add fn add_configuration(&mut self, configuration: Box) -> &mut Self; } impl ChainedBuilderExtensions for dyn ConfigurationBuilder + '_ { fn add_configuration(&mut self, configuration: Box) -> &mut Self { self.add(Box::new(ChainedConfigurationSource::new(configuration))); self } } impl ChainedBuilderExtensions for T { fn add_configuration(&mut self, configuration: Box) -> &mut Self { self.add(Box::new(ChainedConfigurationSource::new(configuration))); self } } }