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}