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#[derive(Clone)]
142pub struct DefaultConfigurationRoot {
143 token: SharedChangeToken<CompositeChangeToken>,
144 providers: Pc<Mut<Vec<Box<dyn ConfigurationProvider>>>>,
145}
146
147impl DefaultConfigurationRoot {
148 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#[derive(Clone)]
312pub struct DefaultConfigurationSection {
313 root: Pc<dyn ConfigurationRoot>,
314 path: String,
315}
316
317impl DefaultConfigurationSection {
318 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#[derive(Default)]
416pub struct DefaultConfigurationBuilder {
417 pub sources: Vec<Box<dyn ConfigurationSource>>,
419
420 pub properties: HashMap<String, Box<dyn Any>>,
422}
423
424impl DefaultConfigurationBuilder {
425 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}