1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use dyn_clone::DynClone;
use serde_json::Value;
use std::collections::HashMap;
use crate::{
error::HelperError,
parser::ast::Node,
render::{Context, Render},
};
pub type HelperResult<T> = std::result::Result<T, HelperError>;
pub type HelperValue = HelperResult<Option<Value>>;
pub trait Helper: Send + Sync + DynClone {
fn call<'render, 'call>(
&self,
rc: &mut Render<'render>,
ctx: &Context<'call>,
template: Option<&'render Node<'render>>,
) -> HelperValue;
}
dyn_clone::clone_trait_object!(Helper);
#[cfg(feature = "comparison-helper")]
pub mod comparison;
#[cfg(feature = "each-helper")]
pub mod each;
#[cfg(feature = "conditional-helper")]
pub mod r#if;
#[cfg(feature = "json-helper")]
pub mod json;
#[cfg(feature = "log-helper")]
pub mod log;
#[cfg(feature = "logical-helper")]
pub mod logical;
#[cfg(feature = "lookup-helper")]
pub mod lookup;
#[cfg(feature = "conditional-helper")]
pub mod unless;
#[cfg(feature = "with-helper")]
pub mod with;
#[derive(Clone, Default)]
pub struct HelperRegistry<'reg> {
helpers: HashMap<&'reg str, Box<dyn Helper + 'reg>>,
}
impl<'reg> HelperRegistry<'reg> {
pub fn new() -> Self {
let mut reg = Self {
helpers: Default::default(),
};
reg.builtins();
reg
}
fn builtins(&mut self) {
#[cfg(feature = "conditional-helper")]
self.insert("if", Box::new(r#if::If {}));
#[cfg(feature = "conditional-helper")]
self.insert("unless", Box::new(unless::Unless {}));
#[cfg(feature = "comparison-helper")]
self.insert("eq", Box::new(comparison::Equal {}));
#[cfg(feature = "comparison-helper")]
self.insert("ne", Box::new(comparison::NotEqual {}));
#[cfg(feature = "comparison-helper")]
self.insert("gt", Box::new(comparison::GreaterThan {}));
#[cfg(feature = "comparison-helper")]
self.insert("gte", Box::new(comparison::GreaterThanEqual {}));
#[cfg(feature = "comparison-helper")]
self.insert("lt", Box::new(comparison::LessThan {}));
#[cfg(feature = "comparison-helper")]
self.insert("lte", Box::new(comparison::LessThanEqual {}));
#[cfg(feature = "log-helper")]
self.insert("log", Box::new(log::Log {}));
#[cfg(feature = "lookup-helper")]
self.insert("lookup", Box::new(lookup::Lookup {}));
#[cfg(feature = "logical-helper")]
self.insert("and", Box::new(logical::And {}));
#[cfg(feature = "logical-helper")]
self.insert("or", Box::new(logical::Or {}));
#[cfg(feature = "logical-helper")]
self.insert("not", Box::new(logical::Not {}));
#[cfg(feature = "with-helper")]
self.insert("with", Box::new(with::With {}));
#[cfg(feature = "each-helper")]
self.insert("each", Box::new(each::Each {}));
#[cfg(feature = "json-helper")]
self.insert("json", Box::new(json::Json {}));
}
pub fn insert(&mut self, name: &'reg str, helper: Box<dyn Helper + 'reg>) {
self.helpers.insert(name, helper);
}
pub fn remove(&mut self, name: &'reg str) {
self.helpers.remove(name);
}
pub fn get(&self, name: &str) -> Option<&Box<dyn Helper + 'reg>> {
self.helpers.get(name)
}
}