use std::collections::HashMap;
use serialize::json::ToJson;
use template::{Template, TemplateError};
use render::{Renderable, RenderError, RenderContext};
use helpers::{HelperDef};
use context::{Context};
use helpers;
pub struct Registry {
templates: HashMap<String, Template>,
helpers: HashMap<String, Box<HelperDef + 'static>>
}
impl Registry {
pub fn new() -> Registry {
let mut r = Registry {
templates: HashMap::new(),
helpers: HashMap::new()
};
r.register_helper("if", Box::new(helpers::IF_HELPER));
r.register_helper("unless", Box::new(helpers::UNLESS_HELPER));
r.register_helper("each", Box::new(helpers::EACH_HELPER));
r.register_helper("with", Box::new(helpers::WITH_HELPER));
r.register_helper("lookup", Box::new(helpers::LOOKUP_HELPER));
r.register_helper("raw", Box::new(helpers::RAW_HELPER));
r.register_helper(">", Box::new(helpers::INCLUDE_HELPER));
r.register_helper("block", Box::new(helpers::BLOCK_HELPER));
r.register_helper("partial", Box::new(helpers::PARTIAL_HELPER));
r.register_helper("log", Box::new(helpers::LOG_HELPER));
r
}
pub fn register_template(&mut self, name: &str, template: Template) {
self.templates.insert(name.to_string(), template);
}
pub fn register_template_string(&mut self, name: &str, tpl_str: String) -> Result<(), TemplateError>{
let t = Template::compile(tpl_str);
if let Ok(tpl) = t {
self.templates.insert(name.to_string(), tpl);
Ok(())
} else {
Err(t.err().unwrap())
}
}
pub fn register_helper(&mut self, name: &str, def: Box<HelperDef + 'static>) -> Option<Box<HelperDef + 'static>> {
self.helpers.insert(name.to_string(), def)
}
pub fn get_template(&self, name: &String) -> Option<&Template> {
self.templates.get(name)
}
pub fn get_helper(&self, name: &String) -> Option<&Box<HelperDef + 'static>> {
self.helpers.get(name)
}
pub fn get_templates(&self) -> &HashMap<String, Template> {
&self.templates
}
pub fn render<T>(&self, name: &str, ctx: &T) -> Result<String, RenderError>
where T: ToJson {
let template = self.get_template(&name.to_string());
let context = Context::wraps(ctx);
let mut render_context = RenderContext::new();
if let Some(t) = template {
(*t).render(&context, self, &mut render_context)
} else {
Err(RenderError{
desc: "Template not found."
})
}
}
}
#[cfg(test)]
mod test {
use template::{Template, Helper};
use registry::{Registry};
use render::{RenderContext, Renderable, RenderError};
use helpers::{HelperDef};
use context::{Context};
#[derive(Clone, Copy)]
struct DummyHelper;
impl HelperDef for DummyHelper {
fn call(&self, c: &Context, h: &Helper, r: &Registry, rc: &mut RenderContext) -> Result<String, RenderError> {
h.template().unwrap().render(c, r, rc)
}
}
static DUMMY_HELPER: DummyHelper = DummyHelper;
#[test]
fn test_registry_operations() {
let mut r = Registry::new();
let t = Template::compile("<h1></h1>".to_string()).ok().unwrap();
r.register_template("index", t.clone());
assert_eq!((*r.get_template(&("index".to_string())).unwrap()).to_string(),
t.to_string());
assert_eq!(r.templates.len(), 1);
r.register_helper("dummy", Box::new(DUMMY_HELPER));
assert_eq!(r.helpers.len(), 10+1);
}
}