use crate::parser::template; use crate::parser::DustTag; use crate::parser::Template; use crate::parser::TemplateElement; use crate::renderer::errors::CompileError; use crate::renderer::errors::RenderError; use crate::renderer::renderable::Renderable; use std::collections::HashMap; use std::ops::Index; #[derive(Clone, Debug)] pub struct CompiledTemplate<'a> { template: Template<'a>, pub name: String, } #[derive(Clone, Debug)] pub struct DustRenderer<'a> { templates: HashMap>, } pub fn compile_template<'a>( source: &'a str, name: String, ) -> Result, CompileError> { // TODO: Make this all consuming // TODO: This could use better error management let (_remaining, parsed_template) = template(source).expect("Failed to compile template"); Ok(CompiledTemplate { template: parsed_template, name: name, }) } impl<'a> DustRenderer<'a> { pub fn new() -> DustRenderer<'a> { DustRenderer { templates: HashMap::new(), } } pub fn load_source(&mut self, template: &'a CompiledTemplate) { self.templates .insert(template.name.clone(), &template.template); } pub fn render(&self, name: &str, context: &C) -> Result where C: Index<&'a str>, >::Output: Renderable, { let main_template = match self.templates.get(name) { Some(tmpl) => tmpl, None => { return Err(RenderError { message: format!("No template named {} in context", name), }); } }; self.render_template(main_template, context) } fn render_template(&self, template: &Template, context: &C) -> Result where C: Index<&'a str>, >::Output: Renderable, { let mut output = String::new(); for elem in &template.contents.elements { match elem { TemplateElement::TESpan(span) => output.push_str(span.contents), TemplateElement::TETag(dt) => { output.push_str(&self.render_tag(dt, context)?); } } } Ok(output) } fn render_tag(&self, tag: &DustTag, context: &C) -> Result where C: Index<&'a str>, >::Output: Renderable, { match tag { DustTag::DTComment(comment) => (), DustTag::DTReference(reference) => { let val = context.index("name"); return Ok(val.render()); } _ => (), // TODO: Implement the rest } Ok("".to_owned()) } }