use std::collections::BTreeMap;
use anyhow::Result;
use serde_json::Value;
pub trait TemplateRenderer {
fn render_str(&self, template: &str, context: &Value) -> Result<String>;
fn render_value(&self, value: &Value, context: &Value) -> Result<Value>;
}
pub fn render_key_value_map(
input: Option<&BTreeMap<String, Value>>,
context: &Value,
renderer: &dyn TemplateRenderer,
) -> Result<Vec<(String, String)>> {
let mut out = Vec::new();
let Some(input) = input else {
return Ok(out);
};
for (key, value) in input {
let rendered_key = renderer.render_str(key, context)?;
let rendered_value = renderer.render_value(value, context)?;
match rendered_value {
Value::Null => {} Value::Array(values) => {
for value in values {
let s = value_to_string(value)?;
if !s.is_empty() {
out.push((rendered_key.clone(), s));
}
}
}
other => {
let s = value_to_string(other)?;
if !s.is_empty() {
out.push((rendered_key, s));
}
}
}
}
Ok(out)
}
pub fn value_to_string(value: Value) -> Result<String> {
let out = match value {
Value::Null => String::new(),
Value::Bool(v) => v.to_string(),
Value::Number(v) => v.to_string(),
Value::String(v) => v,
Value::Array(_) | Value::Object(_) => serde_json::to_string(&value)?,
};
Ok(out)
}