1use super::handlebars_ext::HandlebarsExt;
2use handlebars::{HelperDef, RenderError, Renderable};
3use serde_json::Value;
4use std::{
5 collections::HashMap,
6 sync::{Arc, RwLock},
7};
8
9pub const GET_HELPER: &str = "get";
10pub const SET_HELPER: &str = "set";
11pub const CLEAR_HELPER: &str = "clear";
12pub const IF_SET_HELPER: &str = "if_set";
13pub const WITH_SET_HELPER: &str = "with_set";
14
15pub struct GetHelper {
40 values: Arc<RwLock<HashMap<String, Value>>>,
41}
42
43impl GetHelper {
44 pub fn new(values: &Arc<RwLock<HashMap<String, Value>>>) -> Self {
45 Self { values: values.clone() }
46 }
47}
48
49impl HelperDef for GetHelper {
50 fn call_inner<'reg: 'rc, 'rc>(
51 &self,
52 h: &handlebars::Helper<'reg, 'rc>,
53 _: &'reg handlebars::Handlebars<'reg>,
54 _: &'rc handlebars::Context,
55 _: &mut handlebars::RenderContext<'reg, 'rc>,
56 ) -> Result<handlebars::ScopedJson<'reg, 'rc>, RenderError> {
57 h.ensure_arguments_count(1, GET_HELPER)?;
58 let key = h.get_param_as_str_or_fail(0, GET_HELPER)?.to_string();
59 let value = get_value(&self.values, &key, GET_HELPER)?;
60 match value {
61 Some(v) => Ok(v.into()),
62 None => Err(RenderError::new(format!(
63 "Value is not set for key `{}` in `{}` helper.",
64 key, GET_HELPER
65 ))),
66 }
67 }
68}
69
70pub struct SetHelper {
73 values: Arc<RwLock<HashMap<String, Value>>>,
74}
75
76impl SetHelper {
77 pub fn new(values: &Arc<RwLock<HashMap<String, Value>>>) -> Self {
78 Self { values: values.clone() }
79 }
80}
81
82impl HelperDef for SetHelper {
83 fn call<'reg: 'rc, 'rc>(
84 &self,
85 h: &handlebars::Helper<'reg, 'rc>,
86 _handle: &'reg handlebars::Handlebars<'reg>,
87 _ctx: &'rc handlebars::Context,
88 _render_ctx: &mut handlebars::RenderContext<'reg, 'rc>,
89 _out: &mut dyn handlebars::Output,
90 ) -> handlebars::HelperResult {
91 h.ensure_arguments_count(2, SET_HELPER)?;
92 let key = h.get_param_as_str_or_fail(0, SET_HELPER)?.to_string();
93 let value = h.get_param_as_json_or_fail(1, SET_HELPER)?;
94 set_value(&self.values, key, value.clone(), SET_HELPER)?;
95 Ok(())
96 }
97}
98
99pub struct WithSetHelper {
110 values: Arc<RwLock<HashMap<String, Value>>>,
111}
112
113impl WithSetHelper {
114 pub fn new(values: &Arc<RwLock<HashMap<String, Value>>>) -> Self {
115 Self { values: values.clone() }
116 }
117}
118
119impl HelperDef for WithSetHelper {
120 fn call<'reg: 'rc, 'rc>(
121 &self,
122 h: &handlebars::Helper<'reg, 'rc>,
123 handle: &'reg handlebars::Handlebars<'reg>,
124 ctx: &'rc handlebars::Context,
125 render_ctx: &mut handlebars::RenderContext<'reg, 'rc>,
126 out: &mut dyn handlebars::Output,
127 ) -> handlebars::HelperResult {
128 h.ensure_arguments_count(2, WITH_SET_HELPER)?;
129 let key = h.get_param_as_str_or_fail(0, WITH_SET_HELPER)?.to_string();
130 let value = h.get_param_as_json_or_fail(1, WITH_SET_HELPER)?;
131 set_value(&self.values, key.clone(), value.clone(), WITH_SET_HELPER)?;
132
133 if let Some(t) = h.template() {
134 t.render(handle, ctx, render_ctx, out)?;
135 }
136
137 rem_value(&self.values, &key, WITH_SET_HELPER)
138 }
139}
140
141pub struct IfGetHelper {
156 values: Arc<RwLock<HashMap<String, Value>>>,
157}
158
159impl IfGetHelper {
160 pub fn new(values: &Arc<RwLock<HashMap<String, Value>>>) -> Self {
161 Self { values: values.clone() }
162 }
163}
164
165impl HelperDef for IfGetHelper {
166 fn call<'reg: 'rc, 'rc>(
167 &self,
168 h: &handlebars::Helper<'reg, 'rc>,
169 handle: &'reg handlebars::Handlebars<'reg>,
170 ctx: &'rc handlebars::Context,
171 render_ctx: &mut handlebars::RenderContext<'reg, 'rc>,
172 out: &mut dyn handlebars::Output,
173 ) -> handlebars::HelperResult {
174 h.ensure_arguments_count(1, IF_SET_HELPER)?;
175 let key = h.get_param_as_str_or_fail(0, IF_SET_HELPER)?.to_string();
176 let has_value = has_value(&self.values, &key, IF_SET_HELPER)?;
177 let temp = if has_value { h.template() } else { h.inverse() };
178 if let Some(t) = temp {
179 t.render(handle, ctx, render_ctx, out)?
180 };
181 Ok(())
182 }
183}
184
185pub struct ClearHelper {
200 values: Arc<RwLock<HashMap<String, Value>>>,
201}
202
203impl ClearHelper {
204 pub fn new(values: &Arc<RwLock<HashMap<String, Value>>>) -> Self {
205 Self { values: values.clone() }
206 }
207}
208
209impl HelperDef for ClearHelper {
210 fn call<'reg: 'rc, 'rc>(
211 &self,
212 h: &handlebars::Helper<'reg, 'rc>,
213 _: &'reg handlebars::Handlebars<'reg>,
214 _: &'rc handlebars::Context,
215 _: &mut handlebars::RenderContext<'reg, 'rc>,
216 _: &mut dyn handlebars::Output,
217 ) -> handlebars::HelperResult {
218 h.ensure_arguments_count(1, GET_HELPER)?;
219 let key = h.get_param_as_str_or_fail(0, CLEAR_HELPER)?.to_string();
220 rem_value(&self.values, &key, CLEAR_HELPER)?;
221 Ok(())
222 }
223}
224
225fn get_value(values: &Arc<RwLock<HashMap<String, Value>>>, key: &str, helper_name: &str) -> Result<Option<Value>, RenderError> {
229 let lock = values
230 .read()
231 .map_err(|_e| RenderError::new(format!("Could not acquire lock in `{}` helper", helper_name)))?;
232 Ok(lock.get(key).map(Clone::clone))
233}
234
235fn has_value(values: &Arc<RwLock<HashMap<String, Value>>>, key: &str, helper_name: &str) -> Result<bool, RenderError> {
236 let lock = values
237 .read()
238 .map_err(|_e| RenderError::new(format!("Could not acquire lock in `{}` helper", helper_name)))?;
239 Ok(lock.get(key).is_some())
240}
241
242fn set_value(values: &Arc<RwLock<HashMap<String, Value>>>, key: String, value: Value, helper_name: &str) -> Result<(), RenderError> {
243 let mut lock = values
244 .write()
245 .map_err(|_| RenderError::new(format!("Could not acquire lock in `{}` helper", helper_name)))?;
246 lock.insert(key, value);
247 Ok(())
248}
249
250fn rem_value(values: &Arc<RwLock<HashMap<String, Value>>>, key: &str, helper_name: &str) -> Result<(), RenderError> {
251 let mut lock = values
252 .write()
253 .map_err(|_| RenderError::new(format!("Could not acquire lock in `{}` helper", helper_name)))?;
254 lock.remove(key);
255 Ok(())
256}