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 neg_op(&self) -> Result<Box<dyn Value>, String> {
294 Err("Unsupported operator for this type".to_string())
295 }
296
297 fn bang_op(&self) -> Result<Box<dyn Value>, String> {
299 Err("Unsupported operator for this type".to_string())
300 }
301
302 #[allow(unused_variables)]
304 #[allow(clippy::borrowed_box)]
305 fn contains_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
306 Err("Unsupported operator for this type".to_string())
307 }
308
309 #[allow(unused_variables)]
311 #[allow(clippy::borrowed_box)]
312 fn like_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
313 Err("Unsupported operator for this type".to_string())
314 }
315
316 #[allow(unused_variables)]
318 #[allow(clippy::borrowed_box)]
319 fn glob_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
320 Err("Unsupported operator for this type".to_string())
321 }
322
323 #[allow(unused_variables)]
325 #[allow(clippy::borrowed_box)]
326 fn regexp_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
327 Err("Unsupported operator for this type".to_string())
328 }
329
330 #[allow(unused_variables)]
332 #[allow(clippy::borrowed_box)]
333 fn cast_op(&self, target_type: &Box<dyn DataType>) -> Result<Box<dyn Value>, String> {
334 Err("Unsupported operator for this type".to_string())
335 }
336}
337
338impl dyn Value {
339 pub fn is_text(&self) -> bool {
341 self.as_any().downcast_ref::<TextValue>().is_some()
342 }
343
344 pub fn as_text(&self) -> Option<String> {
347 if let Some(text_value) = self.as_any().downcast_ref::<TextValue>() {
348 return Some(text_value.value.to_string());
349 }
350 None
351 }
352
353 pub fn is_int(&self) -> bool {
355 self.as_any().downcast_ref::<IntValue>().is_some()
356 }
357
358 pub fn as_int(&self) -> Option<i64> {
361 if let Some(int_value) = self.as_any().downcast_ref::<IntValue>() {
362 return Some(int_value.value);
363 }
364 None
365 }
366
367 pub fn is_float(&self) -> bool {
369 self.as_any().downcast_ref::<FloatValue>().is_some()
370 }
371
372 pub fn as_float(&self) -> Option<f64> {
375 if let Some(float_value) = self.as_any().downcast_ref::<FloatValue>() {
376 return Some(float_value.value);
377 }
378 None
379 }
380
381 pub fn is_number(&self) -> bool {
383 self.is_int() || self.is_float()
384 }
385
386 pub fn is_bool(&self) -> bool {
388 self.as_any().downcast_ref::<BoolValue>().is_some()
389 }
390
391 pub fn as_bool(&self) -> Option<bool> {
394 if let Some(bool_value) = self.as_any().downcast_ref::<BoolValue>() {
395 return Some(bool_value.value);
396 }
397 None
398 }
399
400 pub fn is_date(&self) -> bool {
402 self.as_any().downcast_ref::<DateValue>().is_some()
403 }
404
405 pub fn as_date(&self) -> Option<i64> {
408 if let Some(date_value) = self.as_any().downcast_ref::<DateValue>() {
409 return Some(date_value.timestamp);
410 }
411 None
412 }
413
414 pub fn is_time(&self) -> bool {
416 self.as_any().downcast_ref::<TimeValue>().is_some()
417 }
418
419 pub fn as_time(&self) -> Option<String> {
422 if let Some(time_value) = self.as_any().downcast_ref::<DateValue>() {
423 return Some(time_value.timestamp.to_string());
424 }
425 None
426 }
427
428 pub fn is_date_time(&self) -> bool {
430 self.as_any().downcast_ref::<DateTimeValue>().is_some()
431 }
432
433 pub fn as_date_time(&self) -> Option<i64> {
436 if let Some(date_time_value) = self.as_any().downcast_ref::<DateTimeValue>() {
437 return Some(date_time_value.value);
438 }
439 None
440 }
441
442 pub fn is_interval(&self) -> bool {
444 self.as_any().downcast_ref::<IntervalValue>().is_some()
445 }
446
447 pub fn as_interval(&self) -> Option<Interval> {
450 if let Some(interval_value) = self.as_any().downcast_ref::<IntervalValue>() {
451 return Some(interval_value.interval.clone());
452 }
453 None
454 }
455
456 pub fn is_array(&self) -> bool {
458 self.as_any().downcast_ref::<ArrayValue>().is_some()
459 }
460
461 pub fn is_array_of(&self, condition: fn(&Box<dyn DataType>) -> bool) -> bool {
463 if let Some(array) = self.as_any().downcast_ref::<ArrayValue>() {
464 return condition(&array.base_type);
465 }
466 false
467 }
468
469 pub fn as_array(&self) -> Option<Vec<Box<dyn Value>>> {
472 if let Some(array_value) = self.as_any().downcast_ref::<ArrayValue>() {
473 return Some(array_value.values.clone());
474 }
475 None
476 }
477
478 pub fn is_range(&self) -> bool {
480 self.as_any().downcast_ref::<RangeValue>().is_some()
481 }
482
483 pub fn as_range(&self) -> Option<(Box<dyn Value>, Box<dyn Value>)> {
486 if let Some(range_value) = self.as_any().downcast_ref::<RangeValue>() {
487 return Some((range_value.start.clone(), range_value.end.clone()));
488 }
489 None
490 }
491
492 pub fn is_null(&self) -> bool {
494 self.as_any().downcast_ref::<NullValue>().is_some()
495 }
496
497 pub fn is_composite(&self) -> bool {
499 self.as_any().downcast_ref::<CompositeValue>().is_some()
500 }
501}
502
503impl fmt::Display for Box<dyn Value> {
504 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
505 write!(f, "{}", self.literal())
506 }
507}
508
509impl PartialEq for Box<dyn Value> {
510 fn eq(&self, other: &Self) -> bool {
511 self.equals(other)
512 }
513}
514
515impl PartialOrd for Box<dyn Value> {
516 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
517 self.compare(other)
518 }
519}