use crate::parser::template; use crate::parser::Path; use crate::parser::Template; use crate::renderer::breadcrumb_tree::BreadcrumbTree; use crate::renderer::breadcrumb_tree::BreadcrumbTreeElement; use crate::renderer::context_element::ContextElement; use crate::renderer::context_element::IntoContextElement; use crate::renderer::errors::CompileError; use crate::renderer::tree_walking::walk_path; use std::collections::HashMap; #[derive(Clone, Debug)] pub struct DustRenderer<'a> { templates: HashMap>, } pub fn compile_template<'a>(source: &'a str) -> Result, CompileError> { let (_remaining, parsed_template) = template(source).map_err(|err| CompileError { message: "Failed to compile template".to_owned(), })?; Ok(parsed_template) } impl<'a> DustRenderer<'a> { pub fn new() -> DustRenderer<'a> { DustRenderer { templates: HashMap::new(), } } pub fn load_source(&mut self, template: &'a Template, name: String) { self.templates.insert(name, template); } /// Returns a option of a tuple of (parent, new_node_elements) /// which can then be formed into new BreadcrumbTreeNodes /// /// If None is returned, then it is a signal to simply re-use the /// existing breadcrumbs. /// /// Otherwise, the parent (which may be None, especially for /// explicit contexts) and the additional node elements (which may /// be empty) should be combined into a final BreadcrumbTreeNode fn new_breadcrumbs_section<'b>( &self, maybe_breadcrumbs: Option<&'a BreadcrumbTree>, index_context: Option<&'b dyn IntoContextElement>, injected_context: Option<&'b dyn IntoContextElement>, explicit_context: &Option>, new_context_element: Option<&'b dyn ContextElement>, ) -> Option<(Option<&'b BreadcrumbTree>, Vec>)> { // If none of the additional contexts are present, return None // to signal that the original breadcrumbs should be used // rather than incurring a copy here. match ( index_context, injected_context, explicit_context, new_context_element, ) { (None, None, None, None) => return None, _ => (), } // If there is an explicit context, then drop all the current // context let mut parent = match explicit_context { Some(_) => None, None => maybe_breadcrumbs, }; let mut new_nodes: Vec = Vec::new(); explicit_context.as_ref().map(|path| { let x = walk_path(maybe_breadcrumbs, &path.keys); x.map(|ice| ice.into_context_element(self, maybe_breadcrumbs)) .map(|val| { if val.is_truthy() { new_nodes.push(BreadcrumbTreeElement::Borrowed(val.from_context_element())) } }); }); injected_context.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx))); new_context_element .map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx.from_context_element()))); index_context.map(|ctx| new_nodes.push(BreadcrumbTreeElement::Borrowed(ctx))); Some((parent, new_nodes)) } }