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}