codegenr_lib/helpers/
handlebars_ext.rs

1use 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}