use crate::{util::fmt_debug_view, *};
use std::any::Any;
use std::cell::{Cell, RefCell, UnsafeCell};
use std::collections::{HashMap, HashSet};
use std::fmt::{Debug, Formatter, Result as FormatResult};
use std::ops::Deref;
use std::rc::{Rc, Weak};
use std::sync::Mutex;
use tokens::{ChangeToken, SharedChangeToken};
struct Mediator {
sync: Mutex<String>,
token: RefCell<SharedChangeToken>,
providers: UnsafeCell<Vec<Box<dyn ConfigurationProvider>>>,
tokens: Cell<Vec<Box<dyn ChangeToken>>>,
me: Weak<Mediator>,
}
impl Mediator {
fn new(providers: Vec<Box<dyn ConfigurationProvider>>) -> Rc<Self> {
Rc::new_cyclic(|me| {
let tokens = Cell::new(Mediator::to_tokens(me, &providers));
Self {
sync: Mutex::default(),
token: RefCell::default(),
providers: UnsafeCell::new(providers),
tokens,
me: me.clone(),
}
})
}
fn to_tokens(
me: &Weak<Mediator>,
providers: &Vec<Box<dyn ConfigurationProvider>>,
) -> Vec<Box<dyn ChangeToken>> {
providers
.iter()
.filter_map(|provider| provider.reload_token())
.map(|token| {
let this: Weak<Mediator> = me.clone();
token.register(Box::new(move || this.upgrade().unwrap().raise_changed()));
token
})
.collect()
}
fn providers(&self) -> &[Box<dyn ConfigurationProvider>] {
unsafe { &*self.providers.get() }
}
fn reload(&self) {
let _unused = self.sync.lock().unwrap();
unsafe {
for provider in &mut (*self.providers.get()).iter_mut() {
provider.load();
}
}
}
fn reload_token(&self) -> Box<dyn ChangeToken> {
let token;
{
let _unused = self.sync.lock().unwrap();
token = self.token.borrow().clone();
}
Box::new(token)
}
fn raise_changed(&self) {
let tokens;
unsafe {
let _unused = self.sync.lock().unwrap();
tokens = Mediator::to_tokens(&self.me, &*self.providers.get());
}
let token = self.token.replace(SharedChangeToken::default());
self.tokens.set(tokens);
let callback = token.trigger().upgrade().unwrap();
(callback)()
}
}
#[derive(Clone)]
pub struct DefaultConfigurationRoot {
mediator: Rc<Mediator>,
}
impl DefaultConfigurationRoot {
pub fn new(mut providers: Vec<Box<dyn ConfigurationProvider>>) -> Self {
for provider in providers.iter_mut() {
provider.load();
}
Self {
mediator: Mediator::new(providers),
}
}
}
impl ConfigurationRoot for DefaultConfigurationRoot {
fn reload(&mut self) {
self.mediator.reload();
self.mediator.raise_changed()
}
fn providers(&self) -> &[Box<dyn ConfigurationProvider>] {
self.mediator.providers()
}
fn as_config(&self) -> Box<dyn Configuration> {
Box::new(self.clone())
}
}
impl Configuration for DefaultConfigurationRoot {
fn get(&self, key: &str) -> Option<&str> {
for provider in self.providers().iter().rev() {
if let Some(value) = provider.get(key) {
return Some(value);
}
}
None
}
fn section(&self, key: &str) -> Box<dyn ConfigurationSection> {
Box::new(DefaultConfigurationSection::new(
Box::new(self.clone()),
key,
))
}
fn children(&self) -> Vec<Box<dyn ConfigurationSection>> {
let keys: HashSet<_> = self
.providers()
.iter()
.fold(Vec::new(), |mut earlier_keys, provider| {
provider.child_keys(&mut earlier_keys, None);
earlier_keys
})
.into_iter()
.collect();
keys.iter().map(|key| self.section(key)).collect()
}
fn reload_token(&self) -> Box<dyn ChangeToken> {
self.mediator.reload_token()
}
fn iter_relative(
&self,
make_paths_relative: bool,
) -> Box<dyn Iterator<Item = (String, String)>> {
Box::new(ConfigurationIterator::new(self, make_paths_relative))
}
}
impl Debug for DefaultConfigurationRoot {
fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatResult {
fmt_debug_view(self, formatter)
}
}
impl Deref for DefaultConfigurationRoot {
type Target = dyn Configuration;
fn deref(&self) -> &Self::Target {
self
}
}
pub struct DefaultConfigurationSection {
root: Box<dyn ConfigurationRoot>,
path: String,
}
impl DefaultConfigurationSection {
pub fn new(root: Box<dyn ConfigurationRoot>, path: &str) -> Self {
Self {
root,
path: path.to_owned(),
}
}
#[inline]
fn subkey(&self, key: &str) -> String {
ConfigurationPath::combine(&[&self.path, key])
}
}
impl Configuration for DefaultConfigurationSection {
fn get(&self, key: &str) -> Option<&str> {
self.root.get(&self.subkey(key))
}
fn section(&self, key: &str) -> Box<dyn ConfigurationSection> {
self.root.section(&self.subkey(key))
}
fn children(&self) -> Vec<Box<dyn ConfigurationSection>> {
let keys: HashSet<_> = self
.root
.providers()
.iter()
.fold(Vec::new(), |mut earlier_keys, provider| {
provider.child_keys(&mut earlier_keys, Some(&self.path));
earlier_keys
})
.into_iter()
.collect();
keys.iter().map(|key| self.section(key)).collect()
}
fn reload_token(&self) -> Box<dyn ChangeToken> {
self.root.reload_token()
}
fn as_section(&self) -> Option<&dyn ConfigurationSection> {
Some(self)
}
fn iter_relative(
&self,
make_paths_relative: bool,
) -> Box<dyn Iterator<Item = (String, String)>> {
Box::new(ConfigurationIterator::new(self, make_paths_relative))
}
}
impl ConfigurationSection for DefaultConfigurationSection {
fn key(&self) -> &str {
ConfigurationPath::section_key(&self.path)
}
fn path(&self) -> &str {
&self.path
}
fn value(&self) -> &str {
self.root.get(&self.path).unwrap_or("")
}
}
impl Deref for DefaultConfigurationSection {
type Target = dyn Configuration;
fn deref(&self) -> &Self::Target {
self
}
}
#[derive(Default)]
pub struct DefaultConfigurationBuilder {
pub sources: Vec<Box<dyn ConfigurationSource>>,
pub properties: HashMap<String, Box<dyn Any>>,
}
impl DefaultConfigurationBuilder {
pub fn new() -> Self {
Self::default()
}
}
impl ConfigurationBuilder for DefaultConfigurationBuilder {
fn properties(&self) -> &HashMap<String, Box<dyn Any>> {
&self.properties
}
fn sources(&self) -> &[Box<dyn ConfigurationSource>] {
&self.sources
}
fn add(&mut self, source: Box<dyn ConfigurationSource>) {
self.sources.push(source)
}
fn build(&self) -> Box<dyn ConfigurationRoot> {
Box::new(DefaultConfigurationRoot::new(
self.sources.iter().map(|s| s.build(self)).collect(),
))
}
}