use crate::*;
use std::fmt;
use std::ops::Deref;
use std::sync::Arc;
#[derive(Default)]
pub struct ConfigBuilder {
providers: Vec<Box<dyn ConfigurationProvider>>,
}
impl ConfigBuilder {
pub fn new() -> Self {
Self {
providers: Vec::new(),
}
}
}
struct ConfigRoot {
providers: Vec<Box<dyn ConfigurationProvider>>,
}
#[derive(Clone)]
pub struct Config {
root: Arc<ConfigRoot>,
}
impl fmt::Debug for Config {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn debug_build<'a, 'b, C: Configuration>(config: &C, builder: &mut fmt::DebugMap<'a, 'b>) {
for s in config.sections() {
match s.value() {
None => {}
Some(v) => {
builder.entry(&s.path(), &v);
}
}
debug_build(&s, builder);
}
}
let mut m = f.debug_map();
debug_build(self, &mut m);
m.finish()
}
}
trait ConfigExt: Configuration {
fn child_sections(&self, key: &ConfigKey) -> Self::Sections;
fn get_owned_section(&self, key: ConfigKey) -> Self::Section;
}
#[doc(hidden)]
impl Configuration for Arc<ConfigRoot> {
type Section = ConfigSection;
type Sections = std::vec::IntoIter<Self::Section>;
fn get<K: Into<ConfigKey>>(&self, key: K) -> Option<&str> {
self.deref().get(&key.into())
}
fn get_section<K: Into<ConfigKey>>(&self, key: K) -> Self::Section {
let path = key.into();
let key = path.section_key();
let value = self.get(&path).map(ToOwned::to_owned);
let root = self.clone();
ConfigSection {
root,
key,
path,
value,
}
}
fn sections(&self) -> Self::Sections {
self.child_sections(&ConfigKey::empty())
}
}
#[doc(hidden)]
impl ConfigExt for Arc<ConfigRoot> {
fn get_owned_section(&self, path: ConfigKey) -> Self::Section {
let key = path.section_key();
let value = self.get(&path).map(ToOwned::to_owned);
let root = self.clone();
ConfigSection {
root,
key,
path,
value,
}
}
fn child_sections(&self, key: &ConfigKey) -> Self::Sections {
let mut section_names = HashSet::new();
for provider in self.providers.iter() {
provider.get_child_keys(&key, &mut section_names);
}
let collected: Vec<_> = section_names
.into_iter()
.map(|name| {
let path = key.combine(name);
self.get_owned_section(path)
})
.collect();
collected.into_iter()
}
}
#[derive(Clone)]
pub struct ConfigSection {
root: Arc<ConfigRoot>,
key: ConfigKey,
path: ConfigKey,
value: Option<String>,
}
impl ConfigRoot {
fn get(&self, key: &ConfigKey) -> Option<&str> {
for provider in self.providers.iter() {
let value = provider.try_get(&key);
if value.is_some() {
return value;
}
}
None
}
}
impl ConfigurationBuilder for ConfigBuilder {
type Config = Config;
fn push_provider<P: ConfigurationProvider + 'static>(mut self, source: P) -> Self {
self.providers.push(Box::new(source));
self
}
fn build(self) -> std::io::Result<Self::Config> {
Ok(Config::new(self.providers))
}
}
impl Config {
fn new(providers: Vec<Box<dyn ConfigurationProvider>>) -> Self {
let root = ConfigRoot { providers };
let root = Arc::new(root);
Config { root }
}
}
impl Configuration for ConfigSection {
type Section = ConfigSection;
type Sections = std::vec::IntoIter<Self::Section>;
#[inline]
fn get<K: Into<ConfigKey>>(&self, key: K) -> Option<&str> {
let key = self.path().combine(key);
self.root.get(key.as_ref())
}
#[inline]
fn get_section<K: Into<ConfigKey>>(&self, key: K) -> Self::Section {
let key = self.path().combine(key);
self.root.get_owned_section(key)
}
#[inline]
fn sections(&self) -> Self::Sections {
self.root.child_sections(self.key())
}
}
impl ConfigurationSection for ConfigSection {
fn key(&self) -> &ConfigKey {
&self.key
}
fn path(&self) -> &ConfigKey {
&self.path
}
fn value(&self) -> Option<&str> {
match &self.value {
None => None,
Some(s) => Some(s.as_ref()),
}
}
}
impl Configuration for Config {
type Section = ConfigSection;
type Sections = std::vec::IntoIter<Self::Section>;
fn get<K: Into<ConfigKey>>(&self, key: K) -> Option<&str> {
self.root.get(key)
}
fn get_section<K: Into<ConfigKey>>(&self, key: K) -> Self::Section {
self.root.get_section(key)
}
fn sections(&self) -> Self::Sections {
self.root.sections()
}
}