1mod bitwise;
11mod comparison;
12mod equality;
13
14pub use bitwise::{apply_bitwise_and, apply_bitwise_and_mask};
15pub use comparison::{
16 apply_greater_equal, apply_greater_than, apply_less_equal, apply_less_than, compare_values,
17};
18pub use equality::{apply_equal, apply_not_equal};
19
20use crate::parser::ast::{Operator, Value};
21
22#[must_use]
102pub fn apply_operator(operator: &Operator, left: &Value, right: &Value) -> bool {
103 match operator {
104 Operator::Equal => apply_equal(left, right),
105 Operator::NotEqual => apply_not_equal(left, right),
106 Operator::LessThan => apply_less_than(left, right),
107 Operator::GreaterThan => apply_greater_than(left, right),
108 Operator::LessEqual => apply_less_equal(left, right),
109 Operator::GreaterEqual => apply_greater_equal(left, right),
110 Operator::BitwiseAnd => apply_bitwise_and(left, right),
111 Operator::BitwiseAndMask(mask) => apply_bitwise_and_mask(*mask, left, right),
112 }
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 fn test_apply_operator_equal() {
121 assert!(apply_operator(
123 &Operator::Equal,
124 &Value::Uint(42),
125 &Value::Uint(42)
126 ));
127 assert!(!apply_operator(
128 &Operator::Equal,
129 &Value::Uint(42),
130 &Value::Uint(24)
131 ));
132
133 assert!(apply_operator(
135 &Operator::Equal,
136 &Value::String("hello".to_string()),
137 &Value::String("hello".to_string())
138 ));
139 assert!(!apply_operator(
140 &Operator::Equal,
141 &Value::String("hello".to_string()),
142 &Value::String("world".to_string())
143 ));
144
145 assert!(apply_operator(
147 &Operator::Equal,
148 &Value::Uint(42),
149 &Value::Int(42)
150 ));
151 }
152
153 #[test]
154 fn test_apply_operator_not_equal() {
155 assert!(!apply_operator(
157 &Operator::NotEqual,
158 &Value::Uint(42),
159 &Value::Uint(42)
160 ));
161 assert!(apply_operator(
162 &Operator::NotEqual,
163 &Value::Uint(42),
164 &Value::Uint(24)
165 ));
166
167 assert!(!apply_operator(
169 &Operator::NotEqual,
170 &Value::String("hello".to_string()),
171 &Value::String("hello".to_string())
172 ));
173 assert!(apply_operator(
174 &Operator::NotEqual,
175 &Value::String("hello".to_string()),
176 &Value::String("world".to_string())
177 ));
178
179 assert!(!apply_operator(
181 &Operator::NotEqual,
182 &Value::Uint(42),
183 &Value::Int(42)
184 ));
185 }
186
187 #[test]
188 fn test_apply_operator_bitwise_and() {
189 assert!(apply_operator(
191 &Operator::BitwiseAnd,
192 &Value::Uint(0xFF),
193 &Value::Uint(0x0F)
194 ));
195 assert!(!apply_operator(
196 &Operator::BitwiseAnd,
197 &Value::Uint(0xF0),
198 &Value::Uint(0x0F)
199 ));
200
201 assert!(apply_operator(
203 &Operator::BitwiseAnd,
204 &Value::Int(-1),
205 &Value::Int(1)
206 ));
207 assert!(!apply_operator(
208 &Operator::BitwiseAnd,
209 &Value::Int(-2),
210 &Value::Int(1)
211 ));
212
213 assert!(apply_operator(
215 &Operator::BitwiseAnd,
216 &Value::Uint(0xFF),
217 &Value::Int(0x0F)
218 ));
219
220 assert!(!apply_operator(
222 &Operator::BitwiseAnd,
223 &Value::String("test".to_string()),
224 &Value::Uint(0x01)
225 ));
226 }
227
228 #[test]
229 fn test_apply_operator_all_operators_with_same_values() {
230 let test_cases = vec![
231 (Value::Uint(42), Value::Uint(42)),
233 (Value::Int(-100), Value::Int(-100)),
234 (
235 Value::String("test".to_string()),
236 Value::String("test".to_string()),
237 ),
238 (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![1, 2, 3])),
239 ];
240
241 for (left, right) in test_cases {
242 assert!(
244 apply_operator(&Operator::Equal, &left, &right),
245 "Equal should be true for same values: {left:?} == {right:?}"
246 );
247
248 assert!(
250 !apply_operator(&Operator::NotEqual, &left, &right),
251 "NotEqual should be false for same values: {left:?} != {right:?}"
252 );
253
254 let bitwise_result = apply_operator(&Operator::BitwiseAnd, &left, &right);
256 match &left {
257 Value::Uint(n) => {
258 let expected = *n != 0;
260 assert_eq!(
261 bitwise_result, expected,
262 "BitwiseAnd for Uint({n}) should be {expected}"
263 );
264 }
265 Value::Int(n) => {
266 let expected = *n != 0;
268 assert_eq!(
269 bitwise_result, expected,
270 "BitwiseAnd for Int({n}) should be {expected}"
271 );
272 }
273 _ => {
274 assert!(
276 !bitwise_result,
277 "BitwiseAnd should be false for non-integer types: {left:?}"
278 );
279 }
280 }
281 }
282 }
283
284 #[test]
285 fn test_apply_operator_all_operators_with_different_values() {
286 let test_cases = vec![
287 (Value::Uint(42), Value::Uint(24)),
289 (Value::Int(100), Value::Int(-100)),
290 (
291 Value::String("hello".to_string()),
292 Value::String("world".to_string()),
293 ),
294 (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![4, 5, 6])),
295 (Value::Uint(42), Value::String("42".to_string())),
297 (Value::Int(42), Value::Bytes(vec![42])),
298 ];
299
300 for (left, right) in test_cases {
301 assert!(
303 !apply_operator(&Operator::Equal, &left, &right),
304 "Equal should be false for different values: {left:?} == {right:?}"
305 );
306
307 assert!(
309 apply_operator(&Operator::NotEqual, &left, &right),
310 "NotEqual should be true for different values: {left:?} != {right:?}"
311 );
312
313 let bitwise_result = apply_operator(&Operator::BitwiseAnd, &left, &right);
315 match (&left, &right) {
316 (Value::Uint(a), Value::Uint(b)) => {
317 let expected = (a & b) != 0;
318 assert_eq!(
319 bitwise_result, expected,
320 "BitwiseAnd for Uint({a}) & Uint({b}) should be {expected}"
321 );
322 }
323 (Value::Int(a), Value::Int(b)) => {
324 #[allow(clippy::cast_sign_loss)]
325 let expected = ((*a as u64) & (*b as u64)) != 0;
326 assert_eq!(
327 bitwise_result, expected,
328 "BitwiseAnd for Int({a}) & Int({b}) should be {expected}"
329 );
330 }
331 (Value::Uint(a), Value::Int(b)) | (Value::Int(b), Value::Uint(a)) => {
332 #[allow(clippy::cast_sign_loss)]
333 let expected = (a & (*b as u64)) != 0;
334 assert_eq!(
335 bitwise_result, expected,
336 "BitwiseAnd for mixed Uint/Int should be {expected}"
337 );
338 }
339 _ => {
340 assert!(
342 !bitwise_result,
343 "BitwiseAnd should be false for non-integer types: {left:?} & {right:?}"
344 );
345 }
346 }
347 }
348 }
349
350 #[test]
351 fn test_apply_operator_consistency_with_individual_functions() {
352 let test_cases = vec![
353 (Value::Uint(42), Value::Uint(42)),
354 (Value::Uint(42), Value::Uint(24)),
355 (Value::Int(-100), Value::Int(-100)),
356 (Value::Int(100), Value::Int(-100)),
357 (
358 Value::String("test".to_string()),
359 Value::String("test".to_string()),
360 ),
361 (
362 Value::String("hello".to_string()),
363 Value::String("world".to_string()),
364 ),
365 (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![1, 2, 3])),
366 (Value::Bytes(vec![1, 2, 3]), Value::Bytes(vec![4, 5, 6])),
367 (Value::Uint(42), Value::Int(42)),
369 (Value::Uint(42), Value::String("42".to_string())),
370 (Value::Int(42), Value::Bytes(vec![42])),
371 ];
372
373 for (left, right) in test_cases {
374 assert_eq!(
376 apply_operator(&Operator::Equal, &left, &right),
377 apply_equal(&left, &right),
378 "apply_operator(Equal) should match apply_equal for {left:?}, {right:?}"
379 );
380
381 assert_eq!(
382 apply_operator(&Operator::NotEqual, &left, &right),
383 apply_not_equal(&left, &right),
384 "apply_operator(NotEqual) should match apply_not_equal for {left:?}, {right:?}"
385 );
386
387 assert_eq!(
388 apply_operator(&Operator::BitwiseAnd, &left, &right),
389 apply_bitwise_and(&left, &right),
390 "apply_operator(BitwiseAnd) should match apply_bitwise_and for {left:?}, {right:?}"
391 );
392 }
393 }
394
395 #[test]
396 fn test_apply_operator_magic_rule_scenarios() {
397 let elf_magic = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
401 let elf_expected = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
402 assert!(apply_operator(&Operator::Equal, &elf_magic, &elf_expected));
403 assert!(!apply_operator(
404 &Operator::NotEqual,
405 &elf_magic,
406 &elf_expected
407 ));
408
409 let zip_magic = Value::Uint(0x504B_0304);
411 let zip_expected = Value::Uint(0x504B_0304);
412 assert!(apply_operator(&Operator::Equal, &zip_magic, &zip_expected));
413
414 let flags = Value::Uint(0b1101_0110);
416 let flag_mask = Value::Uint(0b0000_0010); assert!(apply_operator(&Operator::BitwiseAnd, &flags, &flag_mask));
418
419 let no_flag_mask = Value::Uint(0b0000_0001); assert!(!apply_operator(
421 &Operator::BitwiseAnd,
422 &flags,
423 &no_flag_mask
424 ));
425
426 let content = Value::String("#!/bin/bash".to_string());
428 let shebang = Value::String("#!/bin/bash".to_string());
429 assert!(apply_operator(&Operator::Equal, &content, &shebang));
430
431 let not_shebang = Value::String("#!/usr/bin/python".to_string());
432 assert!(apply_operator(&Operator::NotEqual, &content, ¬_shebang));
433
434 let version = Value::Uint(2);
436 let expected_version = Value::Uint(2);
437 let old_version = Value::Uint(1);
438 assert!(apply_operator(
439 &Operator::Equal,
440 &version,
441 &expected_version
442 ));
443 assert!(apply_operator(&Operator::NotEqual, &version, &old_version));
444 }
445
446 #[test]
447 fn test_apply_operator_edge_cases() {
448 let max_uint = Value::Uint(u64::MAX);
450 let min_signed = Value::Int(i64::MIN);
451 let max_signed = Value::Int(i64::MAX);
452
453 assert!(apply_operator(&Operator::Equal, &max_uint, &max_uint));
455 assert!(apply_operator(&Operator::Equal, &min_signed, &min_signed));
456 assert!(apply_operator(&Operator::Equal, &max_signed, &max_signed));
457
458 assert!(apply_operator(&Operator::NotEqual, &max_uint, &min_signed));
460 assert!(apply_operator(
461 &Operator::NotEqual,
462 &max_signed,
463 &min_signed
464 ));
465
466 assert!(apply_operator(
468 &Operator::BitwiseAnd,
469 &max_uint,
470 &Value::Uint(1)
471 ));
472 assert!(apply_operator(
473 &Operator::BitwiseAnd,
474 &min_signed,
475 &min_signed
476 ));
477
478 let empty_bytes = Value::Bytes(vec![]);
480 let empty_string = Value::String(String::new());
481 assert!(apply_operator(&Operator::Equal, &empty_bytes, &empty_bytes));
482 assert!(apply_operator(
483 &Operator::Equal,
484 &empty_string,
485 &empty_string
486 ));
487 assert!(apply_operator(
488 &Operator::NotEqual,
489 &empty_bytes,
490 &empty_string
491 ));
492
493 let zero_uint = Value::Uint(0);
495 let zero_signed = Value::Int(0);
496 assert!(!apply_operator(
497 &Operator::BitwiseAnd,
498 &zero_uint,
499 &Value::Uint(0xFF)
500 ));
501 assert!(!apply_operator(
502 &Operator::BitwiseAnd,
503 &zero_signed,
504 &Value::Int(0xFF)
505 ));
506 assert!(!apply_operator(
507 &Operator::NotEqual,
508 &zero_uint,
509 &zero_signed
510 )); }
512
513 #[test]
514 fn test_apply_operator_all_combinations() {
515 let operators = [
516 Operator::Equal,
517 Operator::NotEqual,
518 Operator::LessThan,
519 Operator::GreaterThan,
520 Operator::LessEqual,
521 Operator::GreaterEqual,
522 Operator::BitwiseAnd,
523 Operator::BitwiseAndMask(0xFF),
524 ];
525 let values = [
526 Value::Uint(42),
527 Value::Int(-42),
528 Value::Bytes(vec![42]),
529 Value::String("42".to_string()),
530 ];
531
532 for operator in &operators {
534 for left in &values {
535 for right in &values {
536 let result = apply_operator(operator, left, right);
538
539 let expected = match operator {
541 Operator::Equal => apply_equal(left, right),
542 Operator::NotEqual => apply_not_equal(left, right),
543 Operator::LessThan => apply_less_than(left, right),
544 Operator::GreaterThan => apply_greater_than(left, right),
545 Operator::LessEqual => apply_less_equal(left, right),
546 Operator::GreaterEqual => apply_greater_equal(left, right),
547 Operator::BitwiseAnd => apply_bitwise_and(left, right),
548 Operator::BitwiseAndMask(mask) => {
549 apply_bitwise_and_mask(*mask, left, right)
550 }
551 };
552
553 assert_eq!(
554 result, expected,
555 "apply_operator({operator:?}, {left:?}, {right:?}) should match individual function"
556 );
557 }
558 }
559 }
560 }
561}