use ::abc::{RenderResult, FilterResult};
use ::incrust::{Incrust, Context, Args, ex};
use ::template::{
Parsed, Mustache,
FullExpression, FilterItem,
IfStatement, ForStatement,
};
use super::evaluator::eval_expr;
pub fn text<'a>(tpl: &'a[Parsed], context: &'a Context, env: &'a Incrust) -> RenderResult {
let mut res: Vec<String> = Vec::new();
for x in tpl {
res.push(match *x {
Parsed::Text(ref txt) => txt.to_owned(),
Parsed::Comment(_) => "".to_owned(),
Parsed::Mustache(ref mus) => mustache(mus, context, env)?,
Parsed::For(ref stmt) => for_(stmt, context, env)?,
Parsed::If(ref stmt) => if_(stmt, context, env)?,
})
}
Ok(res.join(""))
}
pub fn mustache(mus: &Mustache, context: &Context, env: &Incrust) -> RenderResult {
expression(&mus.expr, context, env)
}
pub fn expression(expr: &FullExpression, context: &Context, env: &Incrust) -> RenderResult {
Ok(expr.filters.iter().fold(
Ok(eval_expr(&expr.expr, context, env)?.and_then(|val| val.to_istring())),
|result: FilterResult, filter: &FilterItem| -> FilterResult {
match result {
Err(err) => Err(err),
Ok(value) => Ok(match *filter {
FilterItem::Simple(ref id) => env.filter(id, value, context)?,
}),
}
}
)?.unwrap_or("".into()))
}
pub fn for_(stmt: &ForStatement, context: &Context, env: &Incrust) -> RenderResult {
#![cfg_attr(feature = "clippy", allow(used_underscore_binding))]
Ok(match stmt.begin.expression {
None => { println!("stmt.begin.expression is None"); "".into()},
Some(ref expr) => {
let iterable = eval_expr(&expr.expr, context, env)?;
println!(":::: iterable: {:?}", iterable);
match iterable {
None => { println!("eval_expr is None"); "".into()},
Some(iterable) => match iterable.as_iiter() {
None => { println!("iterable.as_iiter() is None"); "".into()},
Some(mut iterable) => {
let mut buf: Vec<String> = Vec::new();
let mut index = 0;
for v in iterable.ivalues() {
let local_scope: Args = hashmap!{
stmt.value_var.as_str() => v,
"index0" => ex(index),
"index" => ex(index + 1),
"first" => ex(index == 0),
"last" => ex(false), };
let local_context = Context::new(Some(context), &local_scope);
buf.push(text(&stmt.block.parsed, &local_context, env)?);
index += 1;
}
buf.join("")
}
}
}
}
})
}
pub fn if_(stmt: &IfStatement, context: &Context, env: &Incrust) -> RenderResult {
for branch in &stmt.if_branches {
if let Some(ref expr) = branch.begin.expression {
if let Some(res) = eval_expr(&expr.expr, context, env)? {
if res.to_bool() { return text(&branch.block.parsed, context, env) }
}
}
}
if let Some(ref branch) = stmt.else_branch{ return text(&branch.block.parsed, context, env) }
Ok("".into())
}