mini_template/template/
conditional.rs

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        //(var1 || var2) && var3
191        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}