1use plf::value::ValueKind;
2use plf::{Error, Kwargs, State, TeraResult, Value};
3
4pub fn format(val: Value, kwargs: Kwargs, _: &State) -> TeraResult<String> {
17 let spec = kwargs.must_get::<&str>("spec")?;
18 let fmt_str = format!("{{:{}}}", spec);
19
20 match val.kind() {
21 ValueKind::String => {
22 let s = val.as_str().unwrap();
23 formatx::formatx!(&fmt_str, s)
24 .map_err(|e| Error::message(format!("format error: {}", e)))
25 }
26 ValueKind::I64 | ValueKind::I128 | ValueKind::U64 => {
27 let n = val.as_i128().unwrap();
28 formatx::formatx!(&fmt_str, n)
29 .map_err(|e| Error::message(format!("format error: {}", e)))
30 }
31 ValueKind::U128 => {
32 let n = val.as_u128().unwrap();
33 formatx::formatx!(&fmt_str, n)
34 .map_err(|e| Error::message(format!("format error: {}", e)))
35 }
36 ValueKind::F64 => {
37 let n = val.as_number().unwrap();
38 let f = n.as_float();
39 formatx::formatx!(&fmt_str, f)
40 .map_err(|e| Error::message(format!("format error: {}", e)))
41 }
42 ValueKind::Bool => {
43 let b = val.as_bool().unwrap();
44 formatx::formatx!(&fmt_str, b)
45 .map_err(|e| Error::message(format!("format error: {}", e)))
46 }
47 _ => Err(Error::message(format!(
48 "Cannot format value of type {} with format filter",
49 val.name()
50 ))),
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use plf::{Context, Tera};
58
59 fn render(template: &str) -> String {
60 let mut tera = Tera::default();
61 tera.register_filter("format", format);
62 tera.add_raw_template("test", template).unwrap();
63 tera.render("test", &Context::new()).unwrap()
64 }
65
66 #[test]
67 fn test_float_precision() {
68 assert_eq!(render("{{ 3.14159 | format(spec='.2') }}"), "3.14");
69 assert_eq!(render("{{ 3.14159 | format(spec='.4') }}"), "3.1416");
70 }
71
72 #[test]
73 fn test_integer_padding() {
74 assert_eq!(render("{{ 42 | format(spec='05') }}"), "00042");
75 assert_eq!(render("{{ 42 | format(spec='10') }}"), " 42");
76 }
77
78 #[test]
79 fn test_string_alignment() {
80 assert_eq!(render("{{ 'hi' | format(spec='>5') }}"), " hi");
81 assert_eq!(render("{{ 'hi' | format(spec='<5') }}"), "hi ");
82 assert_eq!(render("{{ 'hi' | format(spec='^5') }}"), " hi ");
83 }
84
85 #[test]
86 fn test_sign() {
87 assert_eq!(render("{{ 42 | format(spec='+') }}"), "+42");
88 assert_eq!(render("{{ -42 | format(spec='+') }}"), "-42");
89 }
90
91 #[test]
92 fn test_bool() {
93 assert_eq!(render("{{ true | format(spec='>8') }}"), " true");
94 }
95
96 #[test]
97 fn test_combined() {
98 assert_eq!(render("{{ 42 | format(spec='>+10') }}"), " +42");
99 assert_eq!(render("{{ 3.14159 | format(spec='>10.2') }}"), " 3.14");
100 }
101}