gitql_core/values/
float.rs

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