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);
});
}