gitql_core/values/
time.rs

1use std::any::Any;
2use std::cmp::Ordering;
3
4use gitql_ast::operator::GroupComparisonOperator;
5use gitql_ast::types::time::TimeType;
6use gitql_ast::types::DataType;
7
8use super::base::Value;
9use super::boolean::BoolValue;
10
11#[derive(Clone)]
12pub struct TimeValue {
13    pub value: String,
14}
15
16impl TimeValue {
17    pub fn new(time: String) -> Self {
18        TimeValue { value: time }
19    }
20}
21
22impl Value for TimeValue {
23    fn literal(&self) -> String {
24        self.value.to_string()
25    }
26
27    fn equals(&self, other: &Box<dyn Value>) -> bool {
28        if let Some(other_time) = other.as_any().downcast_ref::<TimeValue>() {
29            return self.value == other_time.value;
30        }
31        false
32    }
33
34    fn compare(&self, other: &Box<dyn Value>) -> Option<Ordering> {
35        if let Some(other_time) = other.as_any().downcast_ref::<TimeValue>() {
36            return self.value.partial_cmp(&other_time.value);
37        }
38        None
39    }
40
41    fn data_type(&self) -> Box<dyn DataType> {
42        Box::new(TimeType)
43    }
44
45    fn as_any(&self) -> &dyn Any {
46        self
47    }
48
49    fn eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
50        if let Some(other_text) = other.as_any().downcast_ref::<TimeValue>() {
51            let are_equals = self.value == other_text.value;
52            return Ok(Box::new(BoolValue { value: are_equals }));
53        }
54        Err("Unexpected type to perform `=` with".to_string())
55    }
56
57    fn group_eq_op(
58        &self,
59        other: &Box<dyn Value>,
60        group_op: &GroupComparisonOperator,
61    ) -> Result<Box<dyn Value>, String> {
62        if other.is_array_of(|element_type| element_type.is_time()) {
63            let elements = &other.as_array().unwrap();
64            let mut matches_count = 0;
65            for element in elements.iter() {
66                if self.value == element.as_time().unwrap() {
67                    matches_count += 1;
68                    if GroupComparisonOperator::Any.eq(group_op) {
69                        break;
70                    }
71                }
72            }
73
74            let result = match group_op {
75                GroupComparisonOperator::All => matches_count == elements.len(),
76                GroupComparisonOperator::Any => matches_count > 0,
77            };
78
79            return Ok(Box::new(BoolValue::new(result)));
80        }
81        Err("Unexpected type to perform `=` with".to_string())
82    }
83
84    fn bang_eq_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
85        if let Some(other_text) = other.as_any().downcast_ref::<TimeValue>() {
86            let are_equals = self.value != other_text.value;
87            return Ok(Box::new(BoolValue { value: are_equals }));
88        }
89        Err("Unexpected type to perform `!=` with".to_string())
90    }
91
92    fn group_bang_eq_op(
93        &self,
94        other: &Box<dyn Value>,
95        group_op: &GroupComparisonOperator,
96    ) -> Result<Box<dyn Value>, String> {
97        if other.is_array_of(|element_type| element_type.is_time()) {
98            let elements = &other.as_array().unwrap();
99            let mut matches_count = 0;
100            for element in elements.iter() {
101                if self.value != element.as_time().unwrap() {
102                    matches_count += 1;
103                    if GroupComparisonOperator::Any.eq(group_op) {
104                        break;
105                    }
106                }
107            }
108
109            let result = match group_op {
110                GroupComparisonOperator::All => matches_count == elements.len(),
111                GroupComparisonOperator::Any => matches_count > 0,
112            };
113
114            return Ok(Box::new(BoolValue::new(result)));
115        }
116        Err("Unexpected type to perform `!=` with".to_string())
117    }
118
119    fn gt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
120        if let Some(other_text) = other.as_any().downcast_ref::<TimeValue>() {
121            let are_equals = self.value > other_text.value;
122            return Ok(Box::new(BoolValue { value: are_equals }));
123        }
124        Err("Unexpected type to perform `>` with".to_string())
125    }
126
127    fn group_gt_op(
128        &self,
129        other: &Box<dyn Value>,
130        group_op: &GroupComparisonOperator,
131    ) -> Result<Box<dyn Value>, String> {
132        if other.is_array_of(|element_type| element_type.is_time()) {
133            let elements = &other.as_array().unwrap();
134            let mut matches_count = 0;
135            for element in elements.iter() {
136                if self.value > element.as_time().unwrap() {
137                    matches_count += 1;
138                    if GroupComparisonOperator::Any.eq(group_op) {
139                        break;
140                    }
141                }
142            }
143
144            let result = match group_op {
145                GroupComparisonOperator::All => matches_count == elements.len(),
146                GroupComparisonOperator::Any => matches_count > 0,
147            };
148
149            return Ok(Box::new(BoolValue::new(result)));
150        }
151        Err("Unexpected type to perform `>` with".to_string())
152    }
153
154    fn gte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
155        if let Some(other_text) = other.as_any().downcast_ref::<TimeValue>() {
156            let are_equals = self.value >= other_text.value;
157            return Ok(Box::new(BoolValue { value: are_equals }));
158        }
159        Err("Unexpected type to perform `>=` with".to_string())
160    }
161
162    fn group_gte_op(
163        &self,
164        other: &Box<dyn Value>,
165        group_op: &GroupComparisonOperator,
166    ) -> Result<Box<dyn Value>, String> {
167        if other.is_array_of(|element_type| element_type.is_time()) {
168            let elements = &other.as_array().unwrap();
169            let mut matches_count = 0;
170            for element in elements.iter() {
171                if self.value >= element.as_time().unwrap() {
172                    matches_count += 1;
173                    if GroupComparisonOperator::Any.eq(group_op) {
174                        break;
175                    }
176                }
177            }
178
179            let result = match group_op {
180                GroupComparisonOperator::All => matches_count == elements.len(),
181                GroupComparisonOperator::Any => matches_count > 0,
182            };
183
184            return Ok(Box::new(BoolValue::new(result)));
185        }
186        Err("Unexpected type to perform `>=` with".to_string())
187    }
188
189    fn lt_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
190        if let Some(other_text) = other.as_any().downcast_ref::<TimeValue>() {
191            let are_equals = self.value < other_text.value;
192            return Ok(Box::new(BoolValue { value: are_equals }));
193        }
194        Err("Unexpected type to perform `<` with".to_string())
195    }
196
197    fn group_lt_op(
198        &self,
199        other: &Box<dyn Value>,
200        group_op: &GroupComparisonOperator,
201    ) -> Result<Box<dyn Value>, String> {
202        if other.is_array_of(|element_type| element_type.is_time()) {
203            let elements = &other.as_array().unwrap();
204            let mut matches_count = 0;
205            for element in elements.iter() {
206                if self.value < element.as_time().unwrap() {
207                    matches_count += 1;
208                    if GroupComparisonOperator::Any.eq(group_op) {
209                        break;
210                    }
211                }
212            }
213
214            let result = match group_op {
215                GroupComparisonOperator::All => matches_count == elements.len(),
216                GroupComparisonOperator::Any => matches_count > 0,
217            };
218
219            return Ok(Box::new(BoolValue::new(result)));
220        }
221        Err("Unexpected type to perform `<` with".to_string())
222    }
223
224    fn lte_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
225        if let Some(other_text) = other.as_any().downcast_ref::<TimeValue>() {
226            let are_equals = self.value <= other_text.value;
227            return Ok(Box::new(BoolValue { value: are_equals }));
228        }
229        Err("Unexpected type to perform `<=` with".to_string())
230    }
231
232    fn group_lte_op(
233        &self,
234        other: &Box<dyn Value>,
235        group_op: &GroupComparisonOperator,
236    ) -> Result<Box<dyn Value>, String> {
237        if other.is_array_of(|element_type| element_type.is_time()) {
238            let elements = &other.as_array().unwrap();
239            let mut matches_count = 0;
240            for element in elements.iter() {
241                if self.value <= element.as_time().unwrap() {
242                    matches_count += 1;
243                    if GroupComparisonOperator::Any.eq(group_op) {
244                        break;
245                    }
246                }
247            }
248
249            let result = match group_op {
250                GroupComparisonOperator::All => matches_count == elements.len(),
251                GroupComparisonOperator::Any => matches_count > 0,
252            };
253
254            return Ok(Box::new(BoolValue::new(result)));
255        }
256        Err("Unexpected type to perform `<=` with".to_string())
257    }
258}