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
use std::collections::VecDeque;
use ast::Directive;
use value::Value;
#[derive(Debug)]
pub struct DirectiveIter<'a> {
cur: Option<&'a Directive>,
queue: VecDeque<&'a Directive>,
}
impl<'a> DirectiveIter<'a> {
pub fn depth_first(start: &[Directive]) -> DirectiveIter {
DirectiveIter {
cur: None,
queue: start.iter().rev().collect()
}
}
}
impl<'a> Iterator for DirectiveIter<'a> {
type Item = &'a Directive;
fn next(&mut self) -> Option<&'a Directive> {
match self.cur.take() {
Some(dir) => {
if let Some(ch) = dir.item.children() {
self.queue.extend(ch.iter().rev());
}
}
None => {}
}
match self.queue.pop_back() {
Some(x) => {
self.cur = Some(x);
return Some(x);
}
None => None,
}
}
}
pub fn visit_mutable<F>(dirs: &mut Vec<Directive>, mut f: F)
where F: FnMut(&mut Directive)
{
_visit_mutable(dirs, &mut f)
}
fn _visit_mutable<F>(dirs: &mut Vec<Directive>, f: &mut F)
where F: FnMut(&mut Directive)
{
for dir in dirs {
f(dir);
match dir.item.children_mut() {
Some(children) => _visit_mutable(children, f),
None => {}
}
}
}
pub fn replace_vars<'a, F, S>(dirs: &mut Vec<Directive>, mut f: F)
where F: FnMut(&str) -> Option<S>,
S: AsRef<str> + Into<String> + 'a,
{
let mut inner_visitor = |val: &mut Value| {
let ref mut f = f;
val.replace_vars(f);
};
visit_mutable(dirs, |dir: &mut Directive| {
let ref mut inner_visitor = inner_visitor;
dir.visit_values_mut(inner_visitor);
});
}