1use std::any::Any;
2use std::cmp::Ordering;
3use std::fmt;
4
5use dyn_clone::DynClone;
6use gitql_ast::operator::GroupComparisonOperator;
7use gitql_ast::types::DataType;
8use gitql_ast::Interval;
9
10use super::array::ArrayValue;
11use super::boolean::BoolValue;
12use super::composite::CompositeValue;
13use super::date::DateValue;
14use super::datetime::DateTimeValue;
15use super::float::FloatValue;
16use super::integer::IntValue;
17use super::interval::IntervalValue;
18use super::null::NullValue;
19use super::range::RangeValue;
20use super::text::TextValue;
21use super::time::TimeValue;
22
23dyn_clone::clone_trait_object!(Value);
24
25pub trait Value: DynClone {
27 fn literal(&self) -> String;
29
30 #[allow(clippy::borrowed_box)]
32 fn equals(&self, other: &Box<dyn Value>) -> bool;
33
34 #[allow(clippy::borrowed_box)]
37 fn compare(&self, other: &Box<dyn Value>) -> Option<Ordering>;
38
39 fn data_type(&self) -> Box<dyn DataType>;
41
42 fn as_any(&self) -> &dyn Any;
44
45 #[allow(unused_variables)]
47 #[allow(clippy::borrowed_box)]
48 fn add_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
49 Err("Unsupported operator for this type".to_string())
50 }
51
52 #[allow(unused_variables)]
54 #[allow(clippy::borrowed_box)]
55 fn sub_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
56 Err("Unsupported operator for this type".to_string())
57 }
58
59 #[allow(unused_variables)]
61 #[allow(clippy::borrowed_box)]
62 fn mul_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
63 Err("Unsupported operator for this type".to_string())
64 }
65
66 #[allow(unused_variables)]
68 #[allow(clippy::borrowed_box)]
69 fn div_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
70 Err("Unsupported operator for this type".to_string())
71 }
72
73 #[allow(unused_variables)]
75 #[allow(clippy::borrowed_box)]
76 fn rem_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
77 Err("Unsupported operator for this type".to_string())
78 }
79
80 #[allow(unused_variables)]
82 #[allow(clippy::borrowed_box)]
83 fn caret_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
84 Err("Unsupported operator for this type".to_string())
85 }
86
87 #[allow(unused_variables)]
89 #[allow(clippy::borrowed_box)]
90 fn or_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
91 Err("Unsupported operator for this type".to_string())
92 }
93
94 #[allow(unused_variables)]
96 #[allow(clippy::borrowed_box)]
97 fn and_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
98 Err("Unsupported operator for this type".to_string())
99 }
100
101 #[allow(unused_variables)]
103 #[allow(clippy::borrowed_box)]
104 fn xor_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
105 Err("Unsupported operator for this type".to_string())
106 }
107
108 #[allow(unused_variables)]
110 #[allow(clippy::borrowed_box)]
111 fn logical_or_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
112 Err("Unsupported operator for this type".to_string())
113 }
114
115 #[allow(unused_variables)]
117 #[allow(clippy::borrowed_box)]
118 fn logical_and_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
119 Err("Unsupported operator for this type".to_string())
120 }
121
122 #[allow(unused_variables)]
124 #[allow(clippy::borrowed_box)]
125 fn logical_xor_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
126 Err("Unsupported operator for this type".to_string())
127 }
128
129 #[allow(unused_variables)]
131 #[allow(clippy::borrowed_box)]
132 fn shl_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
133 Err("Unsupported operator for this type".to_string())
134 }
135
136 #[allow(unused_variables)]
138 #[allow(clippy::borrowed_box)]
139 fn shr_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
140 Err("Unsupported operator for this type".to_string())
141 }
142
143 #[allow(unused_variables)]
145 #[allow(clippy::borrowed_box)]
146 fn index_op(&self, index: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
147 Err("Unsupported operator for this type".to_string())
148 }
149
150 #[allow(unused_variables)]
152 #[allow(clippy::borrowed_box)]
153 fn slice_op(
154 &self,
155 start: &Option<Box<dyn Value>>,
156 end: &Option<Box<dyn Value>>,
157 ) -> Result<Box<dyn Value>, String> {
158 Err("Unsupported operator for this type".to_string())
159 }
160
161 #[allow(unused_variables)]
163 #[allow(clippy::borrowed_box)]
164 fn eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
165 Err("Unsupported operator for this type".to_string())
166 }
167
168 #[allow(unused_variables)]
170 #[allow(clippy::borrowed_box)]
171 fn group_eq_op(
172 &self,
173 other: &Box<dyn Value>,
174 group_op: &GroupComparisonOperator,
175 ) -> Result<Box<dyn Value>, String> {
176 Err("Unsupported operator for this type".to_string())
177 }
178
179 #[allow(unused_variables)]
181 #[allow(clippy::borrowed_box)]
182 fn bang_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
183 Err("Unsupported operator for this type".to_string())
184 }
185
186 #[allow(unused_variables)]
188 #[allow(clippy::borrowed_box)]
189 fn group_bang_eq_op(
190 &self,
191 other: &Box<dyn Value>,
192 group_op: &GroupComparisonOperator,
193 ) -> Result<Box<dyn Value>, String> {
194 Err("Unsupported operator for this type".to_string())
195 }
196
197 #[allow(unused_variables)]
199 #[allow(clippy::borrowed_box)]
200 fn null_safe_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
201 Err("Unsupported operator for this type".to_string())
202 }
203
204 #[allow(unused_variables)]
206 #[allow(clippy::borrowed_box)]
207 fn group_null_safe_eq_op(
208 &self,
209 other: &Box<dyn Value>,
210 group_op: &GroupComparisonOperator,
211 ) -> Result<Box<dyn Value>, String> {
212 Err("Unsupported operator for this type".to_string())
213 }
214
215 #[allow(unused_variables)]
217 #[allow(clippy::borrowed_box)]
218 fn gt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
219 Err("Unsupported operator for this type".to_string())
220 }
221
222 #[allow(unused_variables)]
224 #[allow(clippy::borrowed_box)]
225 fn group_gt_op(
226 &self,
227 other: &Box<dyn Value>,
228 group_op: &GroupComparisonOperator,
229 ) -> Result<Box<dyn Value>, String> {
230 Err("Unsupported operator for this type".to_string())
231 }
232
233 #[allow(unused_variables)]
235 #[allow(clippy::borrowed_box)]
236 fn gte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
237 Err("Unsupported operator for this type".to_string())
238 }
239
240 #[allow(unused_variables)]
242 #[allow(clippy::borrowed_box)]
243 fn group_gte_op(
244 &self,
245 other: &Box<dyn Value>,
246 group_op: &GroupComparisonOperator,
247 ) -> Result<Box<dyn Value>, String> {
248 Err("Unsupported operator for this type".to_string())
249 }
250
251 #[allow(unused_variables)]
253 #[allow(clippy::borrowed_box)]
254 fn lt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
255 Err("Unsupported operator for this type".to_string())
256 }
257
258 #[allow(unused_variables)]
260 #[allow(clippy::borrowed_box)]
261 fn group_lt_op(
262 &self,
263 other: &Box<dyn Value>,
264 group_op: &GroupComparisonOperator,
265 ) -> Result<Box<dyn Value>, String> {
266 Err("Unsupported operator for this type".to_string())
267 }
268
269 #[allow(unused_variables)]
271 #[allow(clippy::borrowed_box)]
272 fn lte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
273 Err("Unsupported operator for this type".to_string())
274 }
275
276 #[allow(unused_variables)]
278 #[allow(clippy::borrowed_box)]
279 fn group_lte_op(
280 &self,
281 other: &Box<dyn Value>,
282 group_op: &GroupComparisonOperator,
283 ) -> Result<Box<dyn Value>, String> {
284 Err("Unsupported operator for this type".to_string())
285 }
286
287 fn not_op(&self) -> Result<Box<dyn Value>, String> {
289 Err("Unsupported operator for this type".to_string())
290 }
291
292 fn plus_op(&self) -> Result<Box<dyn Value>, String> {
294 Err("Unsupported operator for this type".to_string())
295 }
296
297 fn neg_op(&self) -> Result<Box<dyn Value>, String> {
299 Err("Unsupported operator for this type".to_string())
300 }
301
302 fn bang_op(&self) -> Result<Box<dyn Value>, String> {
304 Err("Unsupported operator for this type".to_string())
305 }
306
307 #[allow(unused_variables)]
309 #[allow(clippy::borrowed_box)]
310 fn contains_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
311 Err("Unsupported operator for this type".to_string())
312 }
313
314 #[allow(unused_variables)]
316 #[allow(clippy::borrowed_box)]
317 fn like_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
318 Err("Unsupported operator for this type".to_string())
319 }
320
321 #[allow(unused_variables)]
323 #[allow(clippy::borrowed_box)]
324 fn glob_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
325 Err("Unsupported operator for this type".to_string())
326 }
327
328 #[allow(unused_variables)]
330 #[allow(clippy::borrowed_box)]
331 fn regexp_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
332 Err("Unsupported operator for this type".to_string())
333 }
334
335 #[allow(unused_variables)]
337 #[allow(clippy::borrowed_box)]
338 fn cast_op(&self, target_type: &Box<dyn DataType>) -> Result<Box<dyn Value>, String> {
339 Err("Unsupported operator for this type".to_string())
340 }
341}
342
343impl dyn Value {
344 pub fn is_text(&self) -> bool {
346 self.as_any().downcast_ref::<TextValue>().is_some()
347 }
348
349 pub fn as_text(&self) -> Option<String> {
352 if let Some(text_value) = self.as_any().downcast_ref::<TextValue>() {
353 return Some(text_value.value.to_string());
354 }
355 None
356 }
357
358 pub fn is_int(&self) -> bool {
360 self.as_any().downcast_ref::<IntValue>().is_some()
361 }
362
363 pub fn as_int(&self) -> Option<i64> {
366 if let Some(int_value) = self.as_any().downcast_ref::<IntValue>() {
367 return Some(int_value.value);
368 }
369 None
370 }
371
372 pub fn is_float(&self) -> bool {
374 self.as_any().downcast_ref::<FloatValue>().is_some()
375 }
376
377 pub fn as_float(&self) -> Option<f64> {
380 if let Some(float_value) = self.as_any().downcast_ref::<FloatValue>() {
381 return Some(float_value.value);
382 }
383 None
384 }
385
386 pub fn is_number(&self) -> bool {
388 self.is_int() || self.is_float()
389 }
390
391 pub fn is_bool(&self) -> bool {
393 self.as_any().downcast_ref::<BoolValue>().is_some()
394 }
395
396 pub fn as_bool(&self) -> Option<bool> {
399 if let Some(bool_value) = self.as_any().downcast_ref::<BoolValue>() {
400 return Some(bool_value.value);
401 }
402 None
403 }
404
405 pub fn is_date(&self) -> bool {
407 self.as_any().downcast_ref::<DateValue>().is_some()
408 }
409
410 pub fn as_date(&self) -> Option<i64> {
413 if let Some(date_value) = self.as_any().downcast_ref::<DateValue>() {
414 return Some(date_value.timestamp);
415 }
416 None
417 }
418
419 pub fn is_time(&self) -> bool {
421 self.as_any().downcast_ref::<TimeValue>().is_some()
422 }
423
424 pub fn as_time(&self) -> Option<String> {
427 if let Some(time_value) = self.as_any().downcast_ref::<DateValue>() {
428 return Some(time_value.timestamp.to_string());
429 }
430 None
431 }
432
433 pub fn is_date_time(&self) -> bool {
435 self.as_any().downcast_ref::<DateTimeValue>().is_some()
436 }
437
438 pub fn as_date_time(&self) -> Option<i64> {
441 if let Some(date_time_value) = self.as_any().downcast_ref::<DateTimeValue>() {
442 return Some(date_time_value.value);
443 }
444 None
445 }
446
447 pub fn is_interval(&self) -> bool {
449 self.as_any().downcast_ref::<IntervalValue>().is_some()
450 }
451
452 pub fn as_interval(&self) -> Option<Interval> {
455 if let Some(interval_value) = self.as_any().downcast_ref::<IntervalValue>() {
456 return Some(interval_value.interval.clone());
457 }
458 None
459 }
460
461 pub fn is_array(&self) -> bool {
463 self.as_any().downcast_ref::<ArrayValue>().is_some()
464 }
465
466 pub fn is_array_of(&self, condition: fn(&Box<dyn DataType>) -> bool) -> bool {
468 if let Some(array) = self.as_any().downcast_ref::<ArrayValue>() {
469 return condition(&array.base_type);
470 }
471 false
472 }
473
474 pub fn as_array(&self) -> Option<Vec<Box<dyn Value>>> {
477 if let Some(array_value) = self.as_any().downcast_ref::<ArrayValue>() {
478 return Some(array_value.values.clone());
479 }
480 None
481 }
482
483 pub fn is_range(&self) -> bool {
485 self.as_any().downcast_ref::<RangeValue>().is_some()
486 }
487
488 pub fn as_range(&self) -> Option<(Box<dyn Value>, Box<dyn Value>)> {
491 if let Some(range_value) = self.as_any().downcast_ref::<RangeValue>() {
492 return Some((range_value.lower.clone(), range_value.upper.clone()));
493 }
494 None
495 }
496
497 pub fn is_null(&self) -> bool {
499 self.as_any().downcast_ref::<NullValue>().is_some()
500 }
501
502 pub fn is_composite(&self) -> bool {
504 self.as_any().downcast_ref::<CompositeValue>().is_some()
505 }
506}
507
508impl fmt::Display for Box<dyn Value> {
509 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
510 write!(f, "{}", self.literal())
511 }
512}
513
514impl PartialEq for Box<dyn Value> {
515 fn eq(&self, other: &Self) -> bool {
516 self.equals(other)
517 }
518}
519
520impl PartialOrd for Box<dyn Value> {
521 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
522 self.compare(other)
523 }
524}