1use std::fmt::Debug;
2
3use crate::{renderer::RenderContext, variable_container::VariableContainer};
4
5use super::{
6 condition::{Condition, ConditionEval},
7 Render, Statement,
8};
9
10#[derive(Debug, PartialEq)]
11pub struct Conditional {
12 pub(crate) condition: Condition,
13 pub(crate) then_case: Vec<Statement>,
14 pub(crate) else_case: Option<Vec<Statement>>,
15}
16
17impl Render for Conditional {
18 fn render<VC: VariableContainer>(
19 &self,
20 context: &mut RenderContext<VC>,
21 buf: &mut String,
22 ) -> crate::error::Result<()> {
23 if self.condition.eval(context)? {
24 self.then_case.render(context, buf)
25 } else {
26 if let Some(e) = &self.else_case {
27 e.render(context, buf)
28 } else {
29 Ok(())
30 }
31 }
32 }
33}
34
35#[cfg(test)]
36mod tests {
37 use std::collections::HashMap;
38
39 use crate::{
40 renderer::RenderContext,
41 template::{
42 condition::{AndCondition, Condition, ConditionEval, OrCondition},
43 CalculatedValue, StorageMethod,
44 },
45 value::Value,
46 };
47
48 #[test]
49 fn eval_condition() {
50 let condition = Condition::CalculatedValue(CalculatedValue::new(
51 StorageMethod::Const(Value::Bool(true)),
52 vec![],
53 ));
54 assert!(condition
55 .eval(&RenderContext::new(&HashMap::new(), HashMap::new()))
56 .unwrap())
57 }
58
59 #[test]
60 fn eval_condition_and() {
61 let condition = AndCondition::new(vec![
62 Condition::CalculatedValue(CalculatedValue::new(StorageMethod::Variable("a"), vec![])),
63 Condition::CalculatedValue(CalculatedValue::new(StorageMethod::Variable("b"), vec![])),
64 ]);
65 let mut vars = HashMap::new();
66 vars.insert("a".to_owned(), Value::Bool(true));
67 vars.insert("b".to_owned(), Value::Bool(true));
68 assert!(condition
69 .eval(&RenderContext::new(&HashMap::new(), vars))
70 .unwrap());
71 let mut vars = HashMap::new();
72 vars.insert("a".to_owned(), Value::Bool(true));
73 vars.insert("b".to_owned(), Value::Bool(false));
74 assert!(!condition
75 .eval(&RenderContext::new(&HashMap::new(), vars))
76 .unwrap());
77 let mut vars = HashMap::new();
78 vars.insert("a".to_owned(), Value::Bool(false));
79 vars.insert("b".to_owned(), Value::Bool(true));
80 assert!(!condition
81 .eval(&RenderContext::new(&HashMap::new(), vars))
82 .unwrap());
83 let mut vars = HashMap::new();
84 vars.insert("a".to_owned(), Value::Bool(false));
85 vars.insert("b".to_owned(), Value::Bool(false));
86 assert!(!condition
87 .eval(&RenderContext::new(&HashMap::new(), vars))
88 .unwrap());
89 }
90
91 #[test]
92 fn eval_condition_or() {
93 let condition = OrCondition::new(vec![
94 Condition::CalculatedValue(CalculatedValue::new(StorageMethod::Variable("a"), vec![])),
95 Condition::CalculatedValue(CalculatedValue::new(StorageMethod::Variable("b"), vec![])),
96 ]);
97 let mut vars = HashMap::new();
98 vars.insert("a".to_owned(), Value::Bool(true));
99 vars.insert("b".to_owned(), Value::Bool(true));
100 assert!(condition
101 .eval(&RenderContext::new(&HashMap::new(), vars))
102 .unwrap());
103 let mut vars = HashMap::new();
104 vars.insert("a".to_owned(), Value::Bool(true));
105 vars.insert("b".to_owned(), Value::Bool(false));
106 assert!(condition
107 .eval(&RenderContext::new(&HashMap::new(), vars))
108 .unwrap());
109 let mut vars = HashMap::new();
110 vars.insert("a".to_owned(), Value::Bool(false));
111 vars.insert("b".to_owned(), Value::Bool(true));
112 assert!(condition
113 .eval(&RenderContext::new(&HashMap::new(), vars))
114 .unwrap());
115 let mut vars = HashMap::new();
116 vars.insert("a".to_owned(), Value::Bool(false));
117 vars.insert("b".to_owned(), Value::Bool(false));
118 assert!(!condition
119 .eval(&RenderContext::new(&HashMap::new(), vars))
120 .unwrap());
121 }
122
123 #[test]
124 fn eval_simple_bool_true() {
125 let mut vars = HashMap::new();
126 vars.insert("my_var".to_owned(), Value::Bool(true));
127 let condition = Condition::CalculatedValue(CalculatedValue::new(
128 StorageMethod::Variable("my_var"),
129 vec![],
130 ));
131 assert!(condition
132 .eval(&RenderContext::new(&HashMap::new(), vars))
133 .unwrap());
134 }
135
136 #[test]
137 fn eval_simple_bool_false() {
138 let mut vars = HashMap::new();
139 vars.insert("my_var".to_owned(), Value::Bool(false));
140 let condition = Condition::CalculatedValue(CalculatedValue::new(
141 StorageMethod::Variable("my_var"),
142 vec![],
143 ));
144 assert!(!condition
145 .eval(&RenderContext::new(&HashMap::new(), vars))
146 .unwrap());
147 }
148
149 #[test]
150 fn eval_simple_int_false() {
151 let mut vars = HashMap::new();
152 vars.insert("my_var".to_owned(), Value::Number(0.));
153 let condition = Condition::CalculatedValue(CalculatedValue::new(
154 StorageMethod::Variable("my_var"),
155 vec![],
156 ));
157 assert!(!condition
158 .eval(&RenderContext::new(&HashMap::new(), vars))
159 .unwrap());
160 }
161
162 #[test]
163 fn eval_simple_int_true_1_0() {
164 let mut vars = HashMap::new();
165 vars.insert("my_var".to_owned(), Value::Number(1.));
166 let condition = Condition::CalculatedValue(CalculatedValue::new(
167 StorageMethod::Variable("my_var"),
168 vec![],
169 ));
170 assert!(condition
171 .eval(&RenderContext::new(&HashMap::new(), vars))
172 .unwrap());
173 }
174
175 #[test]
176 fn eval_simple_int_true_10() {
177 let mut vars = HashMap::new();
178 vars.insert("my_var".to_owned(), Value::Number(10.));
179 let condition = Condition::CalculatedValue(CalculatedValue::new(
180 StorageMethod::Variable("my_var"),
181 vec![],
182 ));
183 assert!(condition
184 .eval(&RenderContext::new(&HashMap::new(), vars))
185 .unwrap());
186 }
187
188 #[test]
189 fn eval_complex_rule() {
190 let condition = Condition::and(vec![
192 Condition::or(vec![
193 Condition::CalculatedValue(CalculatedValue::new(
194 StorageMethod::Variable("var1"),
195 vec![],
196 )),
197 Condition::CalculatedValue(CalculatedValue::new(
198 StorageMethod::Variable("var2"),
199 vec![],
200 )),
201 ]),
202 Condition::CalculatedValue(CalculatedValue::new(
203 StorageMethod::Variable("var3"),
204 vec![],
205 )),
206 ]);
207 let mods = HashMap::default();
208 let mut vars = HashMap::new();
209 vars.insert("var1".to_owned(), Value::Bool(false));
210 vars.insert("var2".to_owned(), Value::Bool(false));
211 vars.insert("var3".to_owned(), Value::Bool(false));
212 assert!(!condition.eval(&RenderContext::new(&mods, vars)).unwrap());
213 let mut vars = HashMap::new();
214 vars.insert("var1".to_owned(), Value::Bool(true));
215 vars.insert("var2".to_owned(), Value::Bool(false));
216 vars.insert("var3".to_owned(), Value::Bool(false));
217 assert!(!condition.eval(&RenderContext::new(&mods, vars)).unwrap());
218 let mut vars = HashMap::new();
219 vars.insert("var1".to_owned(), Value::Bool(false));
220 vars.insert("var2".to_owned(), Value::Bool(true));
221 vars.insert("var3".to_owned(), Value::Bool(false));
222 assert!(!condition.eval(&RenderContext::new(&mods, vars)).unwrap());
223 let mut vars = HashMap::new();
224 vars.insert("var1".to_owned(), Value::Bool(true));
225 vars.insert("var2".to_owned(), Value::Bool(true));
226 vars.insert("var3".to_owned(), Value::Bool(false));
227 assert!(!condition.eval(&RenderContext::new(&mods, vars)).unwrap());
228 let mut vars = HashMap::new();
229 vars.insert("var1".to_owned(), Value::Bool(false));
230 vars.insert("var2".to_owned(), Value::Bool(false));
231 vars.insert("var3".to_owned(), Value::Bool(true));
232 assert!(!condition.eval(&RenderContext::new(&mods, vars)).unwrap());
233 let mut vars = HashMap::new();
234 vars.insert("var1".to_owned(), Value::Bool(true));
235 vars.insert("var2".to_owned(), Value::Bool(false));
236 vars.insert("var3".to_owned(), Value::Bool(true));
237 assert!(condition.eval(&RenderContext::new(&mods, vars)).unwrap());
238 let mut vars = HashMap::new();
239 vars.insert("var1".to_owned(), Value::Bool(false));
240 vars.insert("var2".to_owned(), Value::Bool(true));
241 vars.insert("var3".to_owned(), Value::Bool(true));
242 assert!(condition.eval(&RenderContext::new(&mods, vars)).unwrap());
243 let mut vars = HashMap::new();
244 vars.insert("var1".to_owned(), Value::Bool(true));
245 vars.insert("var2".to_owned(), Value::Bool(true));
246 vars.insert("var3".to_owned(), Value::Bool(true));
247 assert!(condition.eval(&RenderContext::new(&mods, vars)).unwrap());
248 }
249}