codegenr_lib/helpers/
handlebars_ext.rs1use handlebars::{Helper, HelperResult, RenderError};
2use serde_json::Value;
3
4pub trait HandlebarsExt {
5 fn ensure_arguments_count(&self, count: usize, helper_name: &str) -> HelperResult;
6 fn ensure_arguments_count_max(&self, count: usize, helper_name: &str) -> HelperResult;
7 fn ensure_arguments_count_min(&self, count: usize, helper_name: &str) -> HelperResult;
8 fn get_param_as_str(&self, index: usize) -> Option<&str>;
9 fn get_param_as_str_or_fail(&self, index: usize, helper_name: &str) -> Result<&str, RenderError>;
10 fn get_param_as_json(&self, index: usize) -> Option<&Value>;
11 fn get_param_as_json_or_fail(&self, index: usize, helper_name: &str) -> Result<&Value, RenderError>;
12 fn get_param_as_array(&self, index: usize) -> Option<&Vec<Value>>;
13 fn get_param_as_array_or_fail(&self, index: usize, helper_name: &str) -> Result<&Vec<Value>, RenderError>;
14 fn get_param_as_bool(&self, index: usize) -> Option<bool>;
15 fn get_param_as_bool_or_fail(&self, index: usize, helper_name: &str) -> Result<bool, RenderError>;
16 fn get_param_as_integer(&self, index: usize) -> Option<u64>;
17}
18
19impl<'reg, 'rc> HandlebarsExt for Helper<'reg, 'rc> {
20 fn ensure_arguments_count(&self, count: usize, helper_name: &str) -> HelperResult {
21 let len = self.params().len();
22 if len != count {
23 Err(RenderError::new(format!(
24 "`{}` helper needs exactly {} arguments.",
25 helper_name, count
26 )))
27 } else {
28 Ok(())
29 }
30 }
31
32 fn ensure_arguments_count_max(&self, count: usize, helper_name: &str) -> HelperResult {
33 let len = self.params().len();
34 if len > count {
35 Err(RenderError::new(format!(
36 "`{}` helper needs at most {} arguments.",
37 helper_name, count
38 )))
39 } else {
40 Ok(())
41 }
42 }
43
44 fn ensure_arguments_count_min(&self, count: usize, helper_name: &str) -> HelperResult {
45 let len = self.params().len();
46 if len < count {
47 Err(RenderError::new(format!(
48 "`{}` helper needs at less {} arguments.",
49 helper_name, count
50 )))
51 } else {
52 Ok(())
53 }
54 }
55
56 fn get_param_as_str(&self, index: usize) -> Option<&str> {
57 if let Some(Some(s)) = self.param(index).map(|p| p.value().as_str()) {
58 Some(s)
59 } else {
60 None
61 }
62 }
63
64 fn get_param_as_str_or_fail(&self, index: usize, helper_name: &str) -> Result<&str, RenderError> {
65 self
66 .get_param_as_str(index)
67 .ok_or_else(|| RenderError::new(format!("Argument {} of `{}` helper should be a string.", index, helper_name)))
68 }
69
70 fn get_param_as_json(&self, index: usize) -> Option<&Value> {
71 self.param(index).map(|p| p.value())
72 }
73
74 fn get_param_as_json_or_fail(&self, index: usize, helper_name: &str) -> Result<&Value, RenderError> {
75 self
76 .get_param_as_json(index)
77 .ok_or_else(|| RenderError::new(format!("There should be a {} argument for `{}` helper.", index, helper_name)))
78 }
79
80 fn get_param_as_array(&self, index: usize) -> Option<&Vec<Value>> {
81 self.get_param_as_json(index).map(|value| value.as_array()).flatten()
82 }
83
84 fn get_param_as_array_or_fail(&self, index: usize, helper_name: &str) -> Result<&Vec<Value>, RenderError> {
85 match self.get_param_as_json_or_fail(index, helper_name)? {
86 Value::Array(a) => Ok(a),
87 _ => Err(RenderError::new(format!(
88 "Argument {} should be an array for `{}` helper.",
89 index, helper_name
90 ))),
91 }
92 }
93
94 fn get_param_as_bool(&self, index: usize) -> Option<bool> {
95 self.param(index).map(|p| is_truthy(p.value()))
96 }
97
98 fn get_param_as_bool_or_fail(&self, index: usize, helper_name: &str) -> Result<bool, RenderError> {
99 self
100 .get_param_as_bool(index)
101 .ok_or_else(|| RenderError::new(format!("There should be a {} argument for `{}` helper.", index, helper_name)))
102 }
103
104 fn get_param_as_integer(&self, index: usize) -> Option<u64> {
105 self.param(index).map(|p| p.value().as_u64()).flatten()
106 }
107}
108
109fn is_truthy(json: &Value) -> bool {
110 match *json {
111 Value::Bool(ref i) => *i,
112 Value::Number(ref n) => n.as_f64().map(|f| !f.is_nan()).unwrap_or(false),
113 Value::Null => false,
114 Value::String(ref i) => !i.is_empty() && i.to_lowercase() == "true",
115 Value::Array(ref i) => !i.is_empty(),
116 Value::Object(ref i) => !i.is_empty(),
117 }
118}