use plf::value::ValueKind;
use plf::{Error, Kwargs, State, TeraResult, Value};
pub fn format(val: Value, kwargs: Kwargs, _: &State) -> TeraResult<String> {
let spec = kwargs.must_get::<&str>("spec")?;
let fmt_str = format!("{{:{}}}", spec);
match val.kind() {
ValueKind::String => {
let s = val.as_str().unwrap();
formatx::formatx!(&fmt_str, s)
.map_err(|e| Error::message(format!("format error: {}", e)))
}
ValueKind::I64 | ValueKind::I128 | ValueKind::U64 => {
let n = val.as_i128().unwrap();
formatx::formatx!(&fmt_str, n)
.map_err(|e| Error::message(format!("format error: {}", e)))
}
ValueKind::U128 => {
let n = val.as_u128().unwrap();
formatx::formatx!(&fmt_str, n)
.map_err(|e| Error::message(format!("format error: {}", e)))
}
ValueKind::F64 => {
let n = val.as_number().unwrap();
let f = n.as_float();
formatx::formatx!(&fmt_str, f)
.map_err(|e| Error::message(format!("format error: {}", e)))
}
ValueKind::Bool => {
let b = val.as_bool().unwrap();
formatx::formatx!(&fmt_str, b)
.map_err(|e| Error::message(format!("format error: {}", e)))
}
_ => Err(Error::message(format!(
"Cannot format value of type {} with format filter",
val.name()
))),
}
}
#[cfg(test)]
mod tests {
use super::*;
use plf::{Context, Tera};
fn render(template: &str) -> String {
let mut tera = Tera::default();
tera.register_filter("format", format);
tera.add_raw_template("test", template).unwrap();
tera.render("test", &Context::new()).unwrap()
}
#[test]
fn test_float_precision() {
assert_eq!(render("{{ 3.14159 | format(spec='.2') }}"), "3.14");
assert_eq!(render("{{ 3.14159 | format(spec='.4') }}"), "3.1416");
}
#[test]
fn test_integer_padding() {
assert_eq!(render("{{ 42 | format(spec='05') }}"), "00042");
assert_eq!(render("{{ 42 | format(spec='10') }}"), " 42");
}
#[test]
fn test_string_alignment() {
assert_eq!(render("{{ 'hi' | format(spec='>5') }}"), " hi");
assert_eq!(render("{{ 'hi' | format(spec='<5') }}"), "hi ");
assert_eq!(render("{{ 'hi' | format(spec='^5') }}"), " hi ");
}
#[test]
fn test_sign() {
assert_eq!(render("{{ 42 | format(spec='+') }}"), "+42");
assert_eq!(render("{{ -42 | format(spec='+') }}"), "-42");
}
#[test]
fn test_bool() {
assert_eq!(render("{{ true | format(spec='>8') }}"), " true");
}
#[test]
fn test_combined() {
assert_eq!(render("{{ 42 | format(spec='>+10') }}"), " +42");
assert_eq!(render("{{ 3.14159 | format(spec='>10.2') }}"), " 3.14");
}
}