duster/src/renderer/renderer.rs

89 lines
2.4 KiB
Rust
Raw Normal View History

use crate::parser::template;
use crate::parser::DustTag;
use crate::parser::Template;
2020-04-11 22:25:48 +00:00
use crate::parser::TemplateElement;
use crate::renderer::errors::CompileError;
use crate::renderer::errors::RenderError;
use std::collections::HashMap;
use std::ops::Index;
#[derive(Clone, Debug)]
pub struct CompiledTemplate<'a> {
template: Template<'a>,
2020-04-11 22:25:48 +00:00
pub name: String,
}
#[derive(Clone, Debug)]
2020-04-11 00:58:55 +00:00
pub struct DustRenderer<'a> {
2020-04-11 22:25:48 +00:00
templates: HashMap<String, &'a Template<'a>>,
}
2020-04-11 22:25:48 +00:00
pub fn compile_template<'a>(
source: &'a str,
name: String,
) -> Result<CompiledTemplate<'a>, CompileError> {
// TODO: Make this all consuming
2020-04-11 22:25:48 +00:00
// TODO: This could use better error management
let (_remaining, parsed_template) = template(source).expect("Failed to compile template");
2020-04-11 22:25:48 +00:00
Ok(CompiledTemplate {
template: parsed_template,
name: name,
2020-04-11 22:25:48 +00:00
})
}
2020-04-11 00:58:55 +00:00
impl<'a> DustRenderer<'a> {
pub fn new() -> DustRenderer<'a> {
DustRenderer {
2020-04-11 22:25:48 +00:00
templates: HashMap::new(),
}
}
pub fn load_source(&mut self, template: &'a CompiledTemplate) {
2020-04-11 22:25:48 +00:00
self.templates
.insert(template.name.clone(), &template.template);
}
2020-04-11 00:58:55 +00:00
2020-04-11 22:25:48 +00:00
pub fn render<C>(&self, name: &str, context: C) -> Result<String, RenderError>
where
C: Copy,
2020-04-11 22:25:48 +00:00
{
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)
}
2020-04-11 00:58:55 +00:00
2020-04-11 22:25:48 +00:00
fn render_template<C>(&self, template: &Template, context: C) -> Result<String, RenderError>
where
C: Copy,
2020-04-11 22:25:48 +00:00
{
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)?);
}
2020-04-11 22:25:48 +00:00
}
}
Ok(output)
}
fn render_tag<C>(&self, tag: &DustTag, context: C) -> Result<String, RenderError>
where
C: Copy,
{
match tag {
DustTag::DTComment(comment) => (),
DustTag::DTReference(reference) => (),
_ => (), // TODO: Implement the rest
}
Ok("".to_owned())
}
}