config/
default.rs

1use crate::{util::fmt_debug_view, *};
2use cfg_if::cfg_if;
3use std::any::Any;
4use std::borrow::Borrow;
5use std::collections::{HashMap, HashSet};
6use std::fmt::{Debug, Formatter, Result as FormatResult};
7use std::ops::Deref;
8use tokens::{ChangeToken, CompositeChangeToken, SharedChangeToken};
9
10cfg_if! {
11    if #[cfg(feature = "async")] {
12        use std::sync::Arc;
13
14        type Pc<T> = std::sync::Arc<T>;
15        type Mut<T> = std::sync::RwLock<T>;
16        type Ref<'a, T> = Arc<std::sync::RwLockReadGuard<'a, T>>;
17    } else {
18        use std::cell::Ref;
19
20        type Pc<T> = std::rc::Rc<T>;
21        type Mut<T> = std::cell::RefCell<T>;
22    }
23}
24
25struct ProviderItem<'a> {
26    index: usize,
27    name: String,
28    items: Ref<'a, Vec<Box<dyn ConfigurationProvider + 'a>>>,
29}
30
31impl<'a> ProviderItem<'a> {
32    fn new(
33        items: Ref<'a, Vec<Box<dyn ConfigurationProvider + 'a>>>,
34        index: usize,
35        name: String,
36    ) -> Self {
37        Self { index, name, items }
38    }
39}
40
41impl ConfigurationProvider for ProviderItem<'_> {
42    fn get(&self, key: &str) -> Option<Value> {
43        self.items[self.index].get(key)
44    }
45
46    fn child_keys(&self, earlier_keys: &mut Vec<String>, parent_path: Option<&str>) {
47        self.items[self.index].child_keys(earlier_keys, parent_path)
48    }
49
50    fn name(&self) -> &str {
51        &self.name
52    }
53
54    fn reload_token(&self) -> Box<dyn ChangeToken> {
55        self.items[self.index].reload_token()
56    }
57}
58
59struct ProviderIter<'a> {
60    head: usize,
61    tail: usize,
62    items: Ref<'a, Vec<Box<dyn ConfigurationProvider>>>,
63}
64
65impl<'a> ProviderIter<'a> {
66    fn new(items: Ref<'a, Vec<Box<dyn ConfigurationProvider>>>) -> Self {
67        Self {
68            head: 0,
69            tail: items.len(),
70            items,
71        }
72    }
73}
74
75impl<'a> Iterator for ProviderIter<'a> {
76    type Item = Box<dyn ConfigurationProvider + 'a>;
77
78    fn next(&mut self) -> Option<Self::Item> {
79        if self.head < self.items.len() {
80            let i = self.head;
81            let name = self.items[i].name().to_owned();
82            self.head += 1;
83
84            cfg_if! {
85                if #[cfg(feature = "async")] {
86                    Some(Box::new(ProviderItem::new(
87                        self.items.clone(),
88                        i,
89                        name,
90                    )))
91                } else {
92                    Some(Box::new(ProviderItem::new(
93                        Ref::clone(&self.items),
94                        i,
95                        name,
96                    )))
97                }
98            }
99        } else {
100            None
101        }
102    }
103}
104
105impl ExactSizeIterator for ProviderIter<'_> {
106    fn len(&self) -> usize {
107        self.items.len()
108    }
109}
110
111impl DoubleEndedIterator for ProviderIter<'_> {
112    fn next_back(&mut self) -> Option<Self::Item> {
113        if self.tail > 0 {
114            self.tail -= 1;
115            let name = self.items[self.tail].name().to_owned();
116
117            cfg_if! {
118                if #[cfg(feature = "async")] {
119                    Some(Box::new(ProviderItem::new(
120                        self.items.clone(),
121                        self.tail,
122                        name,
123                    )))
124                } else {
125                    Some(Box::new(ProviderItem::new(
126                        Ref::clone(&self.items),
127                        self.tail,
128                        name,
129                    )))
130                }
131            }
132        } else {
133            None
134        }
135    }
136}
137
138impl<'a> ConfigurationProviderIterator<'a> for ProviderIter<'a> {}
139
140/// Represents the root of a configuration.
141#[derive(Clone)]
142pub struct DefaultConfigurationRoot {
143    token: SharedChangeToken<CompositeChangeToken>,
144    providers: Pc<Mut<Vec<Box<dyn ConfigurationProvider>>>>,
145}
146
147impl DefaultConfigurationRoot {
148    /// Initializes a new root configuration.
149    ///
150    /// # Arguments
151    ///
152    /// * `providers` - The [`ConfigurationProvider`](crate::ConfigurationProvider) list used in the configuration
153    pub fn new(mut providers: Vec<Box<dyn ConfigurationProvider>>) -> Result<Self, ReloadError> {
154        let mut errors = Vec::new();
155        let mut tokens = Vec::with_capacity(providers.len());
156
157        for provider in providers.iter_mut() {
158            let result = provider.load();
159
160            if let Err(error) = result {
161                errors.push((provider.name().to_owned(), error));
162            }
163
164            tokens.push(provider.reload_token());
165        }
166
167        if errors.is_empty() {
168            Ok(Self {
169                token: SharedChangeToken::new(CompositeChangeToken::new(tokens.into_iter())),
170                providers: Pc::new(providers.into()),
171            })
172        } else {
173            Err(ReloadError::Provider(errors))
174        }
175    }
176}
177
178impl ConfigurationRoot for DefaultConfigurationRoot {
179    fn reload(&mut self) -> ReloadResult {
180        let borrowed = (Pc::strong_count(&self.providers) - 1) + Pc::weak_count(&self.providers);
181
182        cfg_if! {
183            if #[cfg(feature = "async")] {
184                let result = self.providers.try_write();
185            } else {
186                let result = self.providers.try_borrow_mut();
187            }
188        }
189
190        if let Ok(mut providers) = result {
191            let mut errors = Vec::new();
192            let mut tokens = Vec::with_capacity(providers.len());
193
194            for provider in providers.iter_mut() {
195                let result = provider.load();
196
197                if let Err(error) = result {
198                    errors.push((provider.name().to_owned(), error));
199                }
200
201                tokens.push(provider.reload_token());
202            }
203
204            let new_token = SharedChangeToken::new(CompositeChangeToken::new(tokens.into_iter()));
205            let old_token = std::mem::replace(&mut self.token, new_token);
206
207            old_token.notify();
208
209            if errors.is_empty() {
210                Ok(())
211            } else {
212                Err(ReloadError::Provider(errors))
213            }
214        } else {
215            Err(ReloadError::Borrowed(Some(borrowed)))
216        }
217    }
218
219    fn providers(&self) -> Box<dyn ConfigurationProviderIterator + '_> {
220        cfg_if! {
221            if #[cfg(feature = "async")] {
222                Box::new(ProviderIter::new(self.providers.deref().read().unwrap().into()))
223            } else {
224                Box::new(ProviderIter::new(self.providers.deref().borrow()))
225            }
226        }
227    }
228
229    fn as_config(&self) -> Box<dyn Configuration> {
230        Box::new(self.clone())
231    }
232}
233
234impl Configuration for DefaultConfigurationRoot {
235    fn get(&self, key: &str) -> Option<Value> {
236        for provider in self.providers().rev() {
237            if let Some(value) = provider.get(key) {
238                return Some(value);
239            }
240        }
241
242        None
243    }
244
245    fn section(&self, key: &str) -> Box<dyn ConfigurationSection> {
246        Box::new(DefaultConfigurationSection::new(
247            Box::new(self.clone()),
248            key,
249        ))
250    }
251
252    fn children(&self) -> Vec<Box<dyn ConfigurationSection>> {
253        self.providers()
254            .fold(Vec::new(), |mut earlier_keys, provider| {
255                provider.child_keys(&mut earlier_keys, None);
256                earlier_keys
257            })
258            .into_iter()
259            .collect::<HashSet<_>>()
260            .iter()
261            .map(|key| self.section(key))
262            .collect()
263    }
264
265    fn reload_token(&self) -> Box<dyn ChangeToken> {
266        Box::new(self.token.clone())
267    }
268
269    fn iter(&self, path: Option<ConfigurationPath>) -> Box<dyn Iterator<Item = (String, Value)>> {
270        Box::new(ConfigurationIterator::new(
271            self,
272            path.unwrap_or(ConfigurationPath::Absolute),
273        ))
274    }
275}
276
277impl Debug for DefaultConfigurationRoot {
278    fn fmt(&self, formatter: &mut Formatter<'_>) -> FormatResult {
279        fmt_debug_view(self, formatter)
280    }
281}
282
283impl<'a> AsRef<dyn Configuration + 'a> for DefaultConfigurationRoot {
284    fn as_ref(&self) -> &(dyn Configuration + 'a) {
285        self
286    }
287}
288
289impl<'a> Borrow<dyn Configuration + 'a> for DefaultConfigurationRoot {
290    fn borrow(&self) -> &(dyn Configuration + 'a) {
291        self
292    }
293}
294
295impl Deref for DefaultConfigurationRoot {
296    type Target = dyn Configuration;
297
298    fn deref(&self) -> &Self::Target {
299        self
300    }
301}
302
303cfg_if! {
304    if #[cfg(feature = "async")] {
305        unsafe impl Send for DefaultConfigurationRoot {}
306        unsafe impl Sync for DefaultConfigurationRoot {}
307    }
308}
309
310/// Represent a configuration section.
311#[derive(Clone)]
312pub struct DefaultConfigurationSection {
313    root: Pc<dyn ConfigurationRoot>,
314    path: String,
315}
316
317impl DefaultConfigurationSection {
318    /// Initializes a new configuration section.
319    ///
320    /// # Arguments
321    ///
322    /// * `root` - A reference to the [`ConfigurationRoot`](crate::ConfigurationRoot)
323    /// * `path` - The path of the configuration section
324    pub fn new(root: Box<dyn ConfigurationRoot>, path: &str) -> Self {
325        Self {
326            root: root.into(),
327            path: path.to_owned(),
328        }
329    }
330
331    #[inline]
332    fn subkey(&self, key: &str) -> String {
333        ConfigurationPath::combine(&[&self.path, key])
334    }
335}
336
337impl Configuration for DefaultConfigurationSection {
338    fn get(&self, key: &str) -> Option<Value> {
339        self.root.get(&self.subkey(key))
340    }
341
342    fn section(&self, key: &str) -> Box<dyn ConfigurationSection> {
343        self.root.section(&self.subkey(key))
344    }
345
346    fn children(&self) -> Vec<Box<dyn ConfigurationSection>> {
347        self.root
348            .providers()
349            .fold(Vec::new(), |mut earlier_keys, provider| {
350                provider.child_keys(&mut earlier_keys, Some(&self.path));
351                earlier_keys
352            })
353            .into_iter()
354            .collect::<HashSet<_>>()
355            .iter()
356            .map(|key| self.section(key))
357            .collect()
358    }
359
360    fn reload_token(&self) -> Box<dyn ChangeToken> {
361        self.root.reload_token()
362    }
363
364    fn as_section(&self) -> Option<&dyn ConfigurationSection> {
365        Some(self)
366    }
367
368    fn iter(&self, path: Option<ConfigurationPath>) -> Box<dyn Iterator<Item = (String, Value)>> {
369        Box::new(ConfigurationIterator::new(
370            self,
371            path.unwrap_or(ConfigurationPath::Absolute),
372        ))
373    }
374}
375
376impl ConfigurationSection for DefaultConfigurationSection {
377    fn key(&self) -> &str {
378        ConfigurationPath::section_key(&self.path)
379    }
380
381    fn path(&self) -> &str {
382        &self.path
383    }
384
385    fn value(&self) -> Value {
386        self.root.get(&self.path).unwrap_or_default()
387    }
388
389    fn as_config(&self) -> Box<dyn Configuration> {
390        Box::new(self.clone())
391    }
392}
393
394impl<'a> AsRef<dyn Configuration + 'a> for DefaultConfigurationSection {
395    fn as_ref(&self) -> &(dyn Configuration + 'a) {
396        self
397    }
398}
399
400impl<'a> Borrow<dyn Configuration + 'a> for DefaultConfigurationSection {
401    fn borrow(&self) -> &(dyn Configuration + 'a) {
402        self
403    }
404}
405
406impl Deref for DefaultConfigurationSection {
407    type Target = dyn Configuration;
408
409    fn deref(&self) -> &Self::Target {
410        self
411    }
412}
413
414/// Represents a configuration builder.
415#[derive(Default)]
416pub struct DefaultConfigurationBuilder {
417    /// Gets the associated configuration sources.
418    pub sources: Vec<Box<dyn ConfigurationSource>>,
419
420    /// Gets the properties that can be passed to configuration sources.
421    pub properties: HashMap<String, Box<dyn Any>>,
422}
423
424impl DefaultConfigurationBuilder {
425    /// Initializes a new, default configuration builder.
426    pub fn new() -> Self {
427        Self::default()
428    }
429}
430
431impl ConfigurationBuilder for DefaultConfigurationBuilder {
432    fn properties(&self) -> &HashMap<String, Box<dyn Any>> {
433        &self.properties
434    }
435
436    fn sources(&self) -> &[Box<dyn ConfigurationSource>] {
437        &self.sources
438    }
439
440    fn add(&mut self, source: Box<dyn ConfigurationSource>) {
441        self.sources.push(source)
442    }
443
444    fn build(&self) -> Result<Box<dyn ConfigurationRoot>, ReloadError> {
445        Ok(Box::new(DefaultConfigurationRoot::new(
446            self.sources.iter().map(|s| s.build(self)).collect(),
447        )?))
448    }
449}