1use crate::{ConfigurationPath, ConfigurationSection, Value};
2use tokens::ChangeToken;
3
4#[cfg_attr(feature = "async", maybe_impl::traits(Send, Sync))]
6pub trait Configuration {
7 fn get(&self, key: &str) -> Option<Value>;
13
14 fn section(&self, key: &str) -> Box<dyn ConfigurationSection>;
16
17 fn children(&self) -> Vec<Box<dyn ConfigurationSection>>;
19
20 fn reload_token(&self) -> Box<dyn ChangeToken>;
22
23 fn as_section(&self) -> Option<&dyn ConfigurationSection> {
25 None
26 }
27
28 fn iter(&self, path: Option<ConfigurationPath>) -> Box<dyn Iterator<Item = (String, Value)>>;
34}
35
36pub struct ConfigurationIterator {
38 stack: Vec<Box<dyn ConfigurationSection>>,
39 first: Option<(String, Value)>,
40 prefix_length: usize,
41}
42
43impl ConfigurationIterator {
44 pub fn new(configuration: &dyn Configuration, path: ConfigurationPath) -> Self {
51 let stack = configuration.children();
52 let mut first = None;
53 let mut prefix_length = 0;
54
55 if let Some(root) = configuration.as_section() {
56 if path == ConfigurationPath::Relative {
57 prefix_length = root.path().len() + 1;
58 } else {
59 let key = root.path()[prefix_length..].to_owned();
60 let value = root.value();
61
62 first = Some((key, value));
63 }
64 }
65
66 Self {
67 stack,
68 first,
69 prefix_length,
70 }
71 }
72}
73
74impl Iterator for ConfigurationIterator {
75 type Item = (String, Value);
76
77 fn next(&mut self) -> Option<Self::Item> {
78 if let Some(first) = self.first.take() {
79 return Some(first);
80 }
81
82 while let Some(config) = self.stack.pop() {
83 self.stack.extend(config.children());
84
85 if let Some(section) = config.as_section() {
86 let key = section.path()[self.prefix_length..].to_owned();
87 let value = section.value();
88 return Some((key, value));
89 }
90 }
91
92 None
93 }
94}