]>
Commit | Line | Data |
---|---|---|
8bb4bdeb XL |
1 | use serde_json::value::Value as Json; |
2 | ||
416331ca XL |
3 | use crate::context::Context; |
4 | use crate::error::RenderError; | |
3dfed10e XL |
5 | use crate::helpers::HelperDef; |
6 | use crate::json::value::ScopedJson; | |
416331ca XL |
7 | use crate::registry::Registry; |
8 | use crate::render::{Helper, RenderContext}; | |
8bb4bdeb XL |
9 | |
10 | #[derive(Clone, Copy)] | |
11 | pub struct LookupHelper; | |
12 | ||
13 | impl HelperDef for LookupHelper { | |
3dfed10e | 14 | fn call_inner<'reg: 'rc, 'rc>( |
9fa01778 | 15 | &self, |
f9f354fc | 16 | h: &Helper<'reg, 'rc>, |
94222f64 | 17 | r: &'reg Registry<'reg>, |
f9f354fc XL |
18 | _: &'rc Context, |
19 | _: &mut RenderContext<'reg, 'rc>, | |
94222f64 | 20 | ) -> Result<ScopedJson<'reg, 'rc>, RenderError> { |
9fa01778 XL |
21 | let collection_value = h |
22 | .param(0) | |
23 | .ok_or_else(|| RenderError::new("Param not found for helper \"lookup\""))?; | |
24 | let index = h | |
25 | .param(1) | |
26 | .ok_or_else(|| RenderError::new("Insufficient params for helper \"lookup\""))?; | |
8bb4bdeb | 27 | |
416331ca XL |
28 | let value = match *collection_value.value() { |
29 | Json::Array(ref v) => index | |
83c7162d XL |
30 | .value() |
31 | .as_u64() | |
f9f354fc | 32 | .and_then(|u| v.get(u as usize)) |
94222f64 | 33 | .unwrap_or(&Json::Null), |
416331ca | 34 | Json::Object(ref m) => index |
83c7162d XL |
35 | .value() |
36 | .as_str() | |
37 | .and_then(|k| m.get(k)) | |
94222f64 XL |
38 | .unwrap_or(&Json::Null), |
39 | _ => &Json::Null, | |
8bb4bdeb | 40 | }; |
94222f64 XL |
41 | if r.strict_mode() && value.is_null() { |
42 | Err(RenderError::strict_error(None)) | |
43 | } else { | |
44 | Ok(value.clone().into()) | |
45 | } | |
8bb4bdeb XL |
46 | } |
47 | } | |
48 | ||
49 | pub static LOOKUP_HELPER: LookupHelper = LookupHelper; | |
50 | ||
51 | #[cfg(test)] | |
52 | mod test { | |
416331ca | 53 | use crate::registry::Registry; |
8bb4bdeb XL |
54 | |
55 | use std::collections::BTreeMap; | |
56 | ||
57 | #[test] | |
58 | fn test_lookup() { | |
59 | let mut handlebars = Registry::new(); | |
416331ca | 60 | assert!(handlebars |
f9f354fc | 61 | .register_template_string("t0", "{{#each v1}}{{lookup ../v2 @index}}{{/each}}") |
416331ca XL |
62 | .is_ok()); |
63 | assert!(handlebars | |
f9f354fc | 64 | .register_template_string("t1", "{{#each v1}}{{lookup ../v2 1}}{{/each}}") |
416331ca XL |
65 | .is_ok()); |
66 | assert!(handlebars | |
67 | .register_template_string("t2", "{{lookup kk \"a\"}}") | |
68 | .is_ok()); | |
8bb4bdeb XL |
69 | |
70 | let mut m: BTreeMap<String, Vec<u16>> = BTreeMap::new(); | |
71 | m.insert("v1".to_string(), vec![1u16, 2u16, 3u16]); | |
72 | m.insert("v2".to_string(), vec![9u16, 8u16, 7u16]); | |
73 | ||
416331ca | 74 | let m2 = btreemap! { |
8bb4bdeb XL |
75 | "kk".to_string() => btreemap!{"a".to_string() => "world".to_string()} |
76 | }; | |
77 | ||
78 | let r0 = handlebars.render("t0", &m); | |
79 | assert_eq!(r0.ok().unwrap(), "987".to_string()); | |
80 | ||
81 | let r1 = handlebars.render("t1", &m); | |
82 | assert_eq!(r1.ok().unwrap(), "888".to_string()); | |
83 | ||
84 | let r2 = handlebars.render("t2", &m2); | |
85 | assert_eq!(r2.ok().unwrap(), "world".to_string()); | |
86 | } | |
94222f64 XL |
87 | |
88 | #[test] | |
89 | fn test_strict_lookup() { | |
90 | let mut hbs = Registry::new(); | |
91 | ||
92 | assert_eq!( | |
93 | hbs.render_template("{{lookup kk 1}}", &json!({"kk": []})) | |
94 | .unwrap(), | |
95 | "" | |
96 | ); | |
97 | ||
98 | hbs.set_strict_mode(true); | |
99 | ||
100 | assert!(hbs | |
101 | .render_template("{{lookup kk 1}}", &json!({"kk": []})) | |
102 | .is_err()); | |
103 | } | |
8bb4bdeb | 104 | } |