templar 0.5.0

Lightweight, fast, and powerful templating engine
Documentation
use super::*;

pub struct ParseTree<'a> {
    pub templar: &'a Templar,
    tree: Vec<Node>,
    current_op: Option<Operations>,
}

impl<'a> ParseTree<'a> {
    pub fn new(templar: &'a Templar) -> ParseTree<'a> {
        ParseTree {
            tree: vec![],
            current_op: None,
            templar,
        }
    }

    pub fn set_op(&mut self, op: Operations) -> Result<()> {
        if self.current_op.is_some() {
            self.finish_op()?;
        }
        self.current_op = Some(op);
        Ok(())
    }

    pub fn finish_op(&mut self) -> Result<()> {
        if let Some(ref op) = self.current_op {
            let len = self.tree.len();
            let metadata = op.metadata();
            if len < metadata.minimum_nodes as usize {
                return Err(TemplarError::ParseFailure(format!(
                    "{:?} op requires at least {} nodes",
                    op, metadata.minimum_nodes
                )));
            }
            if let Some(max) = metadata.maximum_nodes {
                if len > max as usize {
                    return Err(TemplarError::ParseFailure(format!(
                        "{:?} op has a maximum of {} nodes",
                        op, max
                    )));
                }
                while self.tree.len() < max as usize {
                    self.tree.push(Node::default())
                }
            }
            let tree = replace(&mut self.tree, vec![]);
            let node = Node::Operation(Arc::new(op.build(tree)));
            self.tree.push(node);
            self.current_op = None;
        }
        Ok(())
    }

    pub fn push(&mut self, node: Node) -> Result<()> {
        self.tree.push(node);
        if let Some(ref op) = self.current_op {
            let metadata = op.metadata();
            if metadata.maximum_nodes.is_some()
                && self.tree.len() == metadata.maximum_nodes.unwrap() as usize
            {
                return self.finish_op();
            }
        }
        Ok(())
    }

    pub fn filter(&mut self, filter: &str, args: Node) -> Result<()> {
        self.finish_op()?;
        let tree = replace(&mut self.tree, vec![]);
        let nodes = vec![tree.into(), args];
        let filter_fn = self
            .templar
            .filters
            .get(filter)
            .ok_or_else(|| TemplarError::FilterNotFound(filter.into()))?
            .clone();
        let executor = FilterExecutor::new(filter_fn);
        self.tree
            .push(Node::Operation(Arc::new(Operation::from_filter(
                filter.into(),
                executor,
                nodes,
            ))));
        Ok(())
    }

    pub fn into_node(mut self) -> Result<Node> {
        self.finish_op()?;
        Ok(self.tree.into())
    }

    pub fn into_nodes(mut self) -> Result<Vec<Node>> {
        self.finish_op()?;
        Ok(self.tree)
    }
}