use crate::{Doc, Error, Node};
#[derive(Default)]
pub struct Builder {
nodes: Vec<Node>,
scope_stack: Vec<Option<String>>
}
impl Builder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[allow(clippy::needless_pass_by_value)]
pub fn scope<L: ToString, K: ToString>(
&mut self,
begin_line: L,
term_line: Option<K>
) -> &mut Self {
self.nodes.push(Node::BeginScope(begin_line.to_string()));
if let Some(ln) = term_line {
self.scope_stack.push(Some(ln.to_string()));
} else {
self.scope_stack.push(None);
}
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn autoscope<F, L: ToString, K: ToString>(
&mut self,
begin_line: L,
term_line: Option<K>,
f: F
) -> &mut Self
where
F: FnOnce(&mut Self)
{
self.scope(begin_line, term_line);
f(self);
self.exit();
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn autoscope_if<F, L: ToString, K: ToString>(
&mut self,
pred: bool,
begin_line: L,
term_line: Option<K>,
f: F
) -> &mut Self
where
F: FnOnce(&mut Self)
{
if pred {
self.scope(begin_line, term_line);
f(self);
self.exit();
}
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn autoscope_opt<F, T, L: ToString, K: ToString>(
&mut self,
opt: Option<T>,
begin_line: L,
term_line: Option<K>,
f: F
) -> &mut Self
where
F: FnOnce(&mut Self, T)
{
if let Some(o) = opt {
self.scope(begin_line, term_line);
f(self, o);
self.exit();
}
self
}
pub fn exit(&mut self) -> &mut Self {
if let Some(s) = self.scope_stack.pop().unwrap() {
self.nodes.push(Node::EndScope(Some(s)));
} else {
self.nodes.push(Node::EndScope(None));
}
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn exit_line<L: ToString>(&mut self, line: L) -> &mut Self {
let _ = self.scope_stack.pop().unwrap();
self.nodes.push(Node::EndScope(Some(line.to_string())));
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn line<L: ToString>(&mut self, line: L) -> &mut Self {
self.nodes.push(Node::Line(line.to_string()));
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn optref<N: ToString>(&mut self, name: N) -> &mut Self {
self.nodes.push(Node::OptRef(name.to_string()));
self
}
#[allow(clippy::needless_pass_by_value)]
pub fn reqref<N: ToString>(&mut self, name: N) -> &mut Self {
self.nodes.push(Node::ReqRef(name.to_string()));
self
}
pub fn build(self) -> Result<Doc, Error> {
if self.scope_stack.is_empty() {
Ok(Doc { nodes: self.nodes })
} else {
Err(Error::BadNesting(format!(
"{} scope(s) remaining",
self.scope_stack.len()
)))
}
}
}