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