phlow_engine/
variable.rs

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