1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
use crate::ConfigurationSection;
use tokens::ChangeToken;
/// Defines the behavior of a configuration.
pub trait Configuration {
/// Gets the configuration value.
///
/// # Arguments
///
/// * `key` - The configuration key
fn get(&self, key: &str) -> Option<&str>;
/// Gets a [configuration section](trait.ConfigurationSection.html) with the specified key.
fn section(&self, key: &str) -> Box<dyn ConfigurationSection>;
/// Gets the sequence of child [configuration sections](trait.ConfigurationSection.html).
fn children(&self) -> Vec<Box<dyn ConfigurationSection>>;
/// Returns a change token that can be used to observe when this configuration is reloaded.
fn reload_token(&self) -> Box<dyn ChangeToken>;
/// Attempts to convert the [configuration](trait.Configuration.html) as a [configuration section](trait.ConfigurationSection.html).
fn as_section(&self) -> Option<&dyn ConfigurationSection> {
None
}
/// Gets an iterator of the key/value pairs within the [configuration](trait.Configuration.html).
fn iter(&self) -> Box<dyn Iterator<Item = (String, String)>> {
self.iter_relative(false)
}
/// Gets an iterator of the key/value pairs within the [configuration](trait.Configuration.html).
///
/// # Arguments
///
/// * `make_paths_relative` - If true, the child keys returned will have the current configuration's path trimmed from the front
fn iter_relative(
&self,
make_paths_relative: bool,
) -> Box<dyn Iterator<Item = (String, String)>>;
}
/// Represents an iterator of key/value pairs for a [configuration](trait.Configuration.html).
pub struct ConfigurationIterator {
stack: Vec<Box<dyn ConfigurationSection>>,
first: Option<(String, String)>,
prefix_length: usize,
}
impl ConfigurationIterator {
/// Initializes a new configuration iterator.
///
/// # Arguments
///
/// * `configuration` - The [configuration](trait.Configuration.html) to iterate
/// * `make_paths_relative` - If true, the child keys returned will have the current configuration's path trimmed from the front
pub fn new(configuration: &dyn Configuration, make_paths_relative: bool) -> Self {
let stack: Vec<_> = configuration.children().into_iter().collect();
let mut first = None;
let mut prefix_length = 0;
if let Some(root) = configuration.as_section() {
if make_paths_relative {
prefix_length = root.path().len() + 1;
}
if !make_paths_relative {
let key = root.path()[prefix_length..].to_owned();
let value = root.value().to_owned();
first = Some((key, value));
}
}
Self {
stack,
first,
prefix_length,
}
}
}
impl Iterator for ConfigurationIterator {
type Item = (String, String);
fn next(&mut self) -> Option<Self::Item> {
if let Some(first) = self.first.take() {
return Some(first);
}
while let Some(config) = self.stack.pop() {
self.stack.extend(config.children().into_iter());
if let Some(section) = config.as_section() {
let key = section.path()[self.prefix_length..].to_owned();
let value = section.value().to_owned();
return Some((key, value));
}
}
None
}
}