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};
#[derive(Clone, Copy)]
pub struct InsertHelper {
name: crate::HelperName,
}
impl HelperDef for InsertHelper {
fn call_inner<'reg: 'rc, 'rc>(
&self,
h: &Helper<'rc>,
_: &'reg Registry<'reg>,
_: &'rc Context,
_: &mut RenderContext<'reg, 'rc>,
) -> Result<ScopedJson<'rc>, RenderError> {
let collection = h
.param(0)
.ok_or_else(|| {
RenderError::new(format!(
"Param not found for helper \"{}\": collection",
self.name
))
})?
.value();
let position = h
.param(1)
.ok_or_else(|| {
RenderError::new(format!(
"Param not found for helper \"{}\": position",
self.name
))
})?
.value();
let item = h
.param(2)
.ok_or_else(|| {
RenderError::new(format!(
"Param not found for helper \"{}\": item",
self.name
))
})?
.value();
match (collection, position) {
(Json::Array(list), Json::Number(index)) => {
let index = index.as_u64().ok_or_else(|| {
RenderError::new(format!(
"Param invalid for helper \"{}\": position must be positive number",
self.name
))
})? as usize;
if index > list.len() {
return Err(RenderError::new(format!(
"Param invalid for helper \"{}\": position out of range",
self.name
)))
}
let mut result = list.clone();
result.insert(index, item.to_owned());
Ok(Json::Array(result).into())
}
(Json::Object(map), Json::String(key)) => {
let mut result = map.clone();
result.insert(key.clone(), item.to_owned());
Ok(Json::Object(result).into())
}
_ => Err(RenderError::new(format!(
"Param invalid for helper \"{}\": unsupported insertion tuple (collection: {:?}, position: {:?})",
self.name,
collection,
position,
))),
}
}
}
pub static INSERT_HELPER: InsertHelper = InsertHelper {
name: crate::HelperName::Insert,
};
#[cfg(test)]
mod test {
#[test]
fn test_insert() {
assert_renders![
(
r##"{{ json (insert {} "foo" "foo") }}"##,
r##"{"foo":"foo"}"##
),
(
r##"{{ json (insert [1, 2] 0 "foo") }}"##,
r##"["foo",1,2]"##
),
(
r##"{{ json (insert [1, 2] 2 "foo") }}"##,
r##"[1,2,"foo"]"##
),
];
}
}