Skip to main content

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