use std::collections::HashMap;
use tera::{Map, Tera, Value};
pub fn register(env: &mut Tera) {
env.register_filter(
"entries",
|value: &Value, args: &HashMap<String, Value>| -> tera::Result<Value> {
let map = value
.as_object()
.ok_or_else(|| tera::Error::msg("entries filter: input must be a map"))?;
let descending = sort_is_descending(args)?;
let mut keys: Vec<&String> = map.keys().collect();
keys.sort();
if descending {
keys.reverse();
}
let entries: Vec<Value> = keys
.into_iter()
.map(|k| {
let mut entry = Map::with_capacity(2);
entry.insert("key".to_string(), Value::String(k.clone()));
entry.insert("value".to_string(), map[k].clone());
Value::Object(entry)
})
.collect();
Ok(Value::Array(entries))
},
);
}
fn sort_is_descending(args: &HashMap<String, Value>) -> tera::Result<bool> {
match args.get("sort") {
None => Ok(false),
Some(Value::String(s)) if s == "asc" => Ok(false),
Some(Value::String(s)) if s == "desc" => Ok(true),
Some(_) => Err(tera::Error::msg(
"entries filter: `sort` must be \"asc\" or \"desc\"",
)),
}
}