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#[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 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#[derive(Clone)]
411pub struct DefaultConfigurationSection {
412 root: Pc<dyn ConfigurationRoot>,
413 path: String,
414}
415
416impl DefaultConfigurationSection {
417 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#[derive(Default)]
515pub struct DefaultConfigurationBuilder {
516 pub sources: Vec<Box<dyn ConfigurationSource>>,
518
519 pub properties: HashMap<String, Box<dyn Any>>,
521}
522
523impl DefaultConfigurationBuilder {
524 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}