phlow_engine/
variable.rs

1use regex::Regex;
2use valu3::{
3    prelude::{NumberBehavior, StringBehavior},
4    value::Value,
5};
6
7#[derive(Debug, PartialEq)]
8pub struct Variable {
9    value: Value,
10}
11
12impl Variable {
13    pub fn new(value: Value) -> Self {
14        Self { value }
15    }
16
17    pub fn get(&self) -> &Value {
18        &self.value
19    }
20
21    pub fn equal(&self, other: &Variable) -> bool {
22        match (self, other) {
23            (
24                Variable {
25                    value: Value::Number(left),
26                    ..
27                },
28                Variable {
29                    value: Value::Number(right),
30                    ..
31                },
32            ) => {
33                if left.is_float() {
34                    left.to_f64() == right.to_f64()
35                } else {
36                    left.to_i64() == right.to_i64()
37                }
38            }
39            _ => self.get() == other.get(),
40        }
41    }
42
43    pub fn greater_than(&self, other: &Variable) -> bool {
44        match (self, other) {
45            (
46                Variable {
47                    value: Value::Number(left),
48                    ..
49                },
50                Variable {
51                    value: Value::Number(right),
52                    ..
53                },
54            ) => {
55                if left.is_float() {
56                    left.to_f64() > right.to_f64()
57                } else {
58                    left.to_i64() > right.to_i64()
59                }
60            }
61            _ => self.get() > other.get(),
62        }
63    }
64
65    pub fn less_than(&self, other: &Variable) -> bool {
66        match (self, other) {
67            (
68                Variable {
69                    value: Value::Number(left),
70                    ..
71                },
72                Variable {
73                    value: Value::Number(right),
74                    ..
75                },
76            ) => {
77                if left.is_float() {
78                    left.to_f64() < right.to_f64()
79                } else {
80                    left.to_i64() < right.to_i64()
81                }
82            }
83            _ => self.get() < other.get(),
84        }
85    }
86
87    pub fn greater_than_or_equal(&self, other: &Variable) -> bool {
88        match (self, other) {
89            (
90                Variable {
91                    value: Value::Number(left),
92                    ..
93                },
94                Variable {
95                    value: Value::Number(right),
96                    ..
97                },
98            ) => {
99                if left.is_float() {
100                    left.to_f64() <= right.to_f64()
101                } else {
102                    left.to_i64() <= right.to_i64()
103                }
104            }
105            _ => self.get() < other.get(),
106        }
107    }
108
109    pub fn less_than_or_equal(&self, other: &Variable) -> bool {
110        match (self, other) {
111            (
112                Variable {
113                    value: Value::Number(left),
114                    ..
115                },
116                Variable {
117                    value: Value::Number(right),
118                    ..
119                },
120            ) => {
121                if left.is_float() {
122                    left.to_f64() >= right.to_f64()
123                } else {
124                    left.to_i64() >= right.to_i64()
125                }
126            }
127            _ => self.get() < other.get(),
128        }
129    }
130
131    pub fn contains(&self, other: &Variable) -> bool {
132        if self.get().is_string() && other.get().is_string() {
133            let target = self.get().as_str();
134            let other = other.get().as_str();
135
136            return target.contains(other);
137        } else if self.get().is_array() && other.get().is_array() {
138            let target = match self.get().as_array() {
139                Some(array) => array,
140                None => return false,
141            };
142            let other = match other.get().as_array() {
143                Some(array) => array,
144                None => return false,
145            };
146
147            return target
148                .into_iter()
149                .any(|x| other.into_iter().any(|y| x == y));
150        }
151
152        return false;
153    }
154
155    pub fn starts_with(&self, other: &Variable) -> bool {
156        if self.get().is_string() && other.get().is_string() {
157            let target = self.get().as_str();
158            let other = other.get().as_str();
159
160            return target.starts_with(other);
161        }
162
163        return false;
164    }
165
166    pub fn ends_with(&self, other: &Variable) -> bool {
167        if self.get().is_string() && other.get().is_string() {
168            let target = self.get().as_str();
169            let other = other.get().as_str();
170
171            return target.ends_with(other);
172        }
173
174        return false;
175    }
176
177    pub fn regex(&self, other: &Variable) -> bool {
178        if self.get().is_string() && other.get().is_string() {
179            let target = self.get().as_str();
180            let other = other.get().as_str();
181
182            return match Regex::new(other) {
183                Ok(re) => re.is_match(target),
184                Err(_) => false,
185            };
186        }
187
188        return false;
189    }
190}
191
192#[cfg(test)]
193mod test {
194    use super::*;
195    use valu3::value::Value;
196
197    #[test]
198    fn test_variable_get() {
199        let value = Value::from(10i64);
200        let variable = Variable::new(value.clone());
201
202        assert_eq!(variable.get(), &value);
203    }
204
205    #[test]
206    fn test_variable_equal() {
207        let value = Value::from(10i64);
208        let variable = Variable::new(value.clone());
209
210        assert!(variable.equal(&Variable::new(value.clone())));
211    }
212
213    #[test]
214    fn test_variable_greater_than() {
215        let value = Value::from(10i64);
216        let variable = Variable::new(value.clone());
217
218        assert!(variable.greater_than(&Variable::new(Value::from(5i64))));
219    }
220
221    #[test]
222    fn test_variable_less_than() {
223        let value = Value::from(10i64);
224        let variable = Variable::new(value.clone());
225
226        assert!(variable.less_than(&Variable::new(Value::from(20i64))));
227    }
228
229    #[test]
230    fn test_variable_greater_than_or_equal() {
231        let value = Value::from(10i64);
232        let variable = Variable::new(value.clone());
233
234        assert!(variable.greater_than_or_equal(&Variable::new(Value::from(10i64))));
235    }
236
237    #[test]
238    fn test_variable_less_than_or_equal() {
239        let value = Value::from(10i64);
240        let variable = Variable::new(value.clone());
241
242        assert!(variable.less_than_or_equal(&Variable::new(Value::from(10i64))));
243    }
244
245    #[test]
246    fn test_variable_array_contains() {
247        let value = Value::from(vec![
248            Value::from(1i64),
249            Value::from(2i64),
250            Value::from(3i64),
251        ]);
252        let variable = Variable::new(value.clone());
253        let expected = Variable::new(Value::from(vec![Value::from(2i64)]));
254
255        assert!(variable.contains(&expected));
256    }
257
258    #[test]
259    fn test_variable_string_contains() {
260        let value = Value::from("hello");
261        let variable = Variable::new(value.clone());
262        let expected = Variable::new(Value::from("ell"));
263
264        assert!(variable.contains(&expected));
265    }
266
267    #[test]
268    fn test_variable_string_starts_with() {
269        let value = Value::from("hello");
270        let variable = Variable::new(value.clone());
271        let expected = Variable::new(Value::from("he"));
272
273        assert!(variable.starts_with(&expected));
274    }
275
276    #[test]
277    fn test_variable_string_ends_with() {
278        let value = Value::from("hello");
279        let variable = Variable::new(value.clone());
280        let expected = Variable::new(Value::from("lo"));
281
282        assert!(variable.ends_with(&expected));
283    }
284
285    #[test]
286    fn test_variable_string_regex() {
287        let value = Value::from("hello");
288        let variable = Variable::new(value.clone());
289        let expected = Variable::new(Value::from("h.*o"));
290
291        assert!(variable.regex(&expected));
292    }
293
294    #[test]
295    fn test_variable_string_not_regex() {
296        let value = Value::from("hello");
297        let variable = Variable::new(value.clone());
298        let expected = Variable::new(Value::from("h.*z"));
299
300        assert!(!variable.regex(&expected));
301    }
302}