incrust 0.2.15

Template engine inspired by Jinja2
#![feature(box_syntax)]
#![feature(specialization)]

#[macro_use]
extern crate maplit;
extern crate incrust;

use std::path::Path;

use incrust::abc::EvalResult;
use incrust::{Incrust, ex, Loader, FilesystemLoader, Type, Arg, Function, Context};
use incrust::types::abc::{AsComposable, IComposable};

#[derive(Debug, Clone)]
struct Fruit {
    title: String,
    price: f64,
}

impl Fruit {
    pub fn new(title: &str, price: f64) -> Fruit { Fruit { title: title.to_owned(), price: price } }
}

impl <'t> Type<'t> for Fruit {
    fn clone_type(&self) -> Arg<'static> {
        Arg::Owned(box self.clone())
    }
}


impl AsComposable for Fruit {
    fn try_as_composable(&self) -> Option<&IComposable> { Some(self) }
}


impl IComposable for Fruit {
    fn get_attr(&self, id: &str) -> Option<Arg> {
        match id {
            "title" => Some(ex(self.title.as_str())),
            "price" => Some(ex(self.price)),
            _ => None
        }
    }
}


#[test]
fn attributes() {
    let mut incrust = Incrust::new();
    incrust.loaders.push(FilesystemLoader::new(&Path::new("./assets/tpl/simple")));
    let sample_loader = FilesystemLoader::new(&Path::new("./assets/html/simple"));

    let sample_a = sample_loader.load("2a.html").unwrap();
    let args = hashmap!{
        "title".into() => ex("fruits"),
        "fruits".into() => ex(vec![
            ex(Fruit::new("Orange", 4.0)),
            ex(Fruit::new("Apple", 2.5)),
            ex(Fruit::new("Banana", 2.25)),
        ])
    };

    assert_eq!(sample_a, incrust.render("2a", &args).unwrap());
}


#[test]
fn invocables() {
    let mut incrust = Incrust::new();
    incrust.loaders.push(FilesystemLoader::new(&Path::new("./assets/tpl/simple")));
    let sample_loader = FilesystemLoader::new(&Path::new("./assets/html/simple"));

    fn title<'res>(_: &[Arg<'res>], _: &'res Context<'res>) -> EvalResult<Arg<'res>> {
        Ok(Some(ex("fruits")))
    }

    let sample_a = sample_loader.load("2a.html").unwrap();
    let args = hashmap!{
        "title".into() => Function::new(title),
        "fruits".into() => ex(vec![
            ex(Fruit::new("Orange", 4.0)),
            ex(Fruit::new("Apple", 2.5)),
            ex(Fruit::new("Banana", 2.25)),
        ])
    };

    assert_eq!(sample_a, incrust.render("2b", &args).unwrap());
}