stepflow_action/
string_template.rs

1use std::collections::HashMap;
2
3
4// NOTE: This hack is pretty unreliable and can probably avoid the string re-allocations
5// In the future, if we don't replace every var, we should return an UnusedParam error
6pub fn render_template<ES>(escaped_template: &ES, params: HashMap<&'static str, ES>) -> String
7    where ES: AsRef<str>
8{
9  let mut escaped_template: &str = escaped_template.as_ref();
10  let mut result = String::new();
11
12  for (k, v) in params {
13    let mut full_key = String::with_capacity(k.len() + 4 /* {{}} */);
14    full_key.push_str("{{");
15    full_key.push_str(&k[..]);
16    full_key.push_str("}}");
17
18    result = escaped_template.replace(&full_key[..], v.as_ref());
19    escaped_template = &result[..];
20  }
21  result
22}
23
24pub trait EscapedString : AsRef<str> + std::fmt::Debug + Send + Sync + 'static {
25  fn from_unescaped(unescaped_str: &str) -> Self;
26  fn already_escaped(escaped_str: String) -> Self;
27}
28
29#[derive(Debug)]
30pub struct HtmlEscapedString(String);
31impl EscapedString for HtmlEscapedString {
32  fn from_unescaped(unescaped_str: &str) -> Self {
33    HtmlEscapedString(htmlescape::encode_attribute(unescaped_str))
34  }
35  fn already_escaped(escaped_str: String) -> Self {
36    HtmlEscapedString(escaped_str)
37  }
38}
39
40impl HtmlEscapedString {
41  pub fn len(&self) -> usize {
42    self.0.len()
43  }
44}
45
46impl AsRef<str> for HtmlEscapedString {
47    fn as_ref(&self) -> &str {
48        &(self.0)[..]
49    }
50}
51
52#[derive(Debug)]
53pub struct UriEscapedString(String);
54impl EscapedString for UriEscapedString {
55  fn from_unescaped(unescaped_str: &str) -> Self {
56    UriEscapedString(urlencoding::encode(unescaped_str))
57  }
58  fn already_escaped(escaped_str: String) -> Self {
59    UriEscapedString(escaped_str)
60  }
61}
62impl AsRef<str> for UriEscapedString {
63    fn as_ref(&self) -> &str {
64        &(self.0)[..]
65    }
66}
67
68
69#[cfg(test)]
70mod tests {
71  use std::collections::HashMap;
72  use super::render_template;
73
74  struct Escaped(&'static str);
75  impl AsRef<str> for Escaped {
76      fn as_ref(&self) -> &str {
77        self.0
78    }
79  }
80
81  #[test]
82  fn handlebars_basic() {
83    let mut params = HashMap::new();
84    params.insert("name", Escaped("bob"));
85    params.insert("value", Escaped("myvalue"));
86    let output = render_template::<Escaped>(&Escaped("name{{name}}, value{{value}}"), params);
87    assert_eq!(output, "namebob, valuemyvalue");
88  }
89}