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