gitql_core/values/
float.rs1use 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 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}