#![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 { 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> { 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()); }