use std::collections::HashMap;
use std::fmt;
fn render_inner(src: &str, ctx: &TemplateContext, out: &mut String) -> Result<(), TemplateError> {
let mut i = 0;
while i < src.len() {
match src[i..].find('{') {
Some(pos) => {
out.push_str(&src[i..i + pos]);
i += pos;
let end = src[i..]
.find('}')
.ok_or(TemplateError::MalformedDirective)?;
let directive = &src[i + 1..i + end];
i += end + 1;
if directive.starts_with("list:") {
let name = &directive[5..];
let body_end = find_block_end(&src[i..], "{list:", "{/list}")?;
let body = &src[i..i + body_end];
i += body_end + "{/list}".len();
let items = ctx
.lists
.get(name)
.ok_or_else(|| TemplateError::UnknownField(name.to_string()))?;
for item in items {
render_inner(body, item, out)?;
}
} else if directive.starts_with("if:") {
let name = &directive[3..];
let body_end = find_block_end(&src[i..], "{if:", "{/if}")?;
let body = &src[i..i + body_end];
i += body_end + "{/if}".len();
if ctx.conditionals.get(name).copied().unwrap_or(false) {
render_inner(body, ctx, out)?;
}
} else if directive.starts_with("include:") {
let name = &directive[8..];
let included = resolve_include(name)
.ok_or_else(|| TemplateError::IncludeNotFound(name.to_string()))?;
render_inner(included, ctx, out)?;
} else {
let val = ctx
.scalars
.get(directive)
.ok_or_else(|| TemplateError::UnknownField(directive.to_string()))?;
out.push_str(val);
}
}
None => {
out.push_str(&src[i..]);
break;
}
}
}
Ok(())
}