handbar 0.0.5

Fork of Handlebars.
use serde_json::value::Value as Json;

use crate::context::Context;
use crate::error::RenderError;
use crate::helpers::HelperDef;
use crate::json::value::ScopedJson;
use crate::registry::Registry;
use crate::render::{Helper, RenderContext};

type ArrayInsertionFn = fn(Vec<Json>, Json) -> Vec<Json>;

#[derive(Clone, Copy)]
pub struct ArrayInsertionHelper {
    name: crate::HelperName,
    op: ArrayInsertionFn,
}

impl HelperDef for ArrayInsertionHelper {
    fn call_inner<'reg: 'rc, 'rc>(
        &self,
        h: &Helper<'rc>,
        _: &'reg Registry<'reg>,
        _: &'rc Context,
        _: &mut RenderContext<'reg, 'rc>,
    ) -> Result<ScopedJson<'rc>, RenderError> {
        let list = h
            .param(0)
            .ok_or_else(|| {
                RenderError::new(format!(
                    "Param not found for helper \"{}\": list",
                    self.name
                ))
            })?
            .value()
            .as_array()
            .ok_or_else(|| {
                RenderError::new(format!(
                    "Param invalid for helper \"{}\": list must be array",
                    self.name
                ))
            })?;

        let value = h
            .param(1)
            .ok_or_else(|| {
                RenderError::new(format!(
                    "Param not found for helper \"{}\": value",
                    self.name
                ))
            })?
            .value();

        let list = (self.op)(list.clone(), value.clone());
        Ok(Json::Array(list).into())
    }
}

pub static APPEND_HELPER: ArrayInsertionHelper = ArrayInsertionHelper {
    name: crate::HelperName::Append,
    op: |mut list: Vec<Json>, elem: Json| -> Vec<Json> {
        list.push(elem);
        list
    },
};

pub static PREPEND_HELPER: ArrayInsertionHelper = ArrayInsertionHelper {
    name: crate::HelperName::Append,
    op: |mut list: Vec<Json>, elem: Json| -> Vec<Json> {
        list.insert(0, elem);
        list
    },
};

#[cfg(test)]
mod test {
    #[test]
    fn test_append() {
        assert_renders![(r##"{{ json (append [0, 1] 2) }}"##, r##"[0,1,2]"##)];
    }

    #[test]
    fn test_prepend() {
        assert_renders![(r##"{{ json (prepend [0, 1] -1) }}"##, r##"[-1,0,1]"##)];
    }
}