1use crate::evaluator::operators::equality::apply_equal;
7use crate::parser::ast::Value;
8
9#[must_use]
41pub fn apply_bitwise_and_mask(mask: u64, left: &Value, right: &Value) -> bool {
42 let masked_left = match left {
43 Value::Uint(val) => Value::Uint(val & mask),
44 Value::Int(val) => {
45 let i64_mask =
47 i64::try_from(mask).unwrap_or_else(|_| i64::from_ne_bytes(mask.to_ne_bytes()));
48 Value::Int(val & i64_mask)
49 }
50 _ => return false, };
52 apply_equal(&masked_left, right)
53}
54
55#[must_use]
91pub fn apply_bitwise_and(left: &Value, right: &Value) -> bool {
92 match (left, right) {
93 (Value::Uint(a), Value::Uint(b)) => (a & b) != 0,
95
96 #[allow(clippy::cast_sign_loss)]
98 (Value::Int(a), Value::Int(b)) => ((*a as u64) & (*b as u64)) != 0,
99
100 #[allow(clippy::cast_sign_loss)]
102 (Value::Uint(a), Value::Int(b)) => (a & (*b as u64)) != 0,
103 #[allow(clippy::cast_sign_loss)]
104 (Value::Int(a), Value::Uint(b)) => ((*a as u64) & b) != 0,
105
106 _ => false,
108 }
109}
110
111#[must_use]
144pub fn apply_bitwise_xor(left: &Value, right: &Value) -> bool {
145 match (left, right) {
146 (Value::Uint(a), Value::Uint(b)) => (a ^ b) != 0,
147 #[allow(clippy::cast_sign_loss)]
148 (Value::Int(a), Value::Int(b)) => ((*a as u64) ^ (*b as u64)) != 0,
149 #[allow(clippy::cast_sign_loss)]
150 (Value::Uint(a), Value::Int(b)) => (a ^ (*b as u64)) != 0,
151 #[allow(clippy::cast_sign_loss)]
152 (Value::Int(a), Value::Uint(b)) => ((*a as u64) ^ b) != 0,
153 _ => false,
154 }
155}
156
157#[must_use]
189pub fn apply_bitwise_not(left: &Value, right: &Value) -> bool {
190 apply_bitwise_not_with_width(left, right, None)
191}
192
193#[must_use]
209pub fn apply_bitwise_not_with_width(left: &Value, right: &Value, bit_width: Option<u32>) -> bool {
210 let complemented = match (left, bit_width) {
211 (Value::Uint(val), Some(width)) if width < 64 => {
212 let mask = (1u64 << width) - 1;
213 Value::Uint(!val & mask)
214 }
215 (Value::Uint(val), _) => Value::Uint(!val),
216 (Value::Int(val), _) => Value::Int(!*val),
217 _ => return false,
218 };
219 apply_equal(&complemented, right)
220}
221
222#[cfg(test)]
223mod tests {
224 use super::*;
225
226 #[test]
227 fn test_apply_bitwise_and_uint_basic() {
228 assert!(apply_bitwise_and(&Value::Uint(0x01), &Value::Uint(0x01))); assert!(!apply_bitwise_and(&Value::Uint(0x02), &Value::Uint(0x01))); assert!(apply_bitwise_and(&Value::Uint(0x03), &Value::Uint(0x01))); }
233
234 #[test]
235 fn test_apply_bitwise_and_uint_multiple_bits() {
236 assert!(apply_bitwise_and(&Value::Uint(0xFF), &Value::Uint(0x0F))); assert!(!apply_bitwise_and(&Value::Uint(0xF0), &Value::Uint(0x0F))); assert!(!apply_bitwise_and(&Value::Uint(0xAA), &Value::Uint(0x55))); assert!(apply_bitwise_and(&Value::Uint(0xAA), &Value::Uint(0xAA))); }
242
243 #[test]
244 fn test_apply_bitwise_and_uint_edge_cases() {
245 assert!(!apply_bitwise_and(&Value::Uint(0), &Value::Uint(0xFF))); assert!(!apply_bitwise_and(&Value::Uint(0xFF), &Value::Uint(0))); assert!(!apply_bitwise_and(&Value::Uint(0), &Value::Uint(0))); assert!(apply_bitwise_and(&Value::Uint(u64::MAX), &Value::Uint(1))); assert!(apply_bitwise_and(
253 &Value::Uint(u64::MAX),
254 &Value::Uint(u64::MAX)
255 )); }
257
258 #[test]
259 fn test_apply_bitwise_and_uint_specific_patterns() {
260 assert!(apply_bitwise_and(
262 &Value::Uint(0x7F45_4C46),
263 &Value::Uint(0xFF00_0000)
264 )); assert!(apply_bitwise_and(
266 &Value::Uint(0x504B_0304),
267 &Value::Uint(0xFFFF_0000)
268 )); assert!(!apply_bitwise_and(
270 &Value::Uint(0x1234_5678),
271 &Value::Uint(0x0000_0001)
272 )); }
274
275 #[test]
276 fn test_apply_bitwise_and_int_basic() {
277 assert!(apply_bitwise_and(&Value::Int(1), &Value::Int(1))); assert!(!apply_bitwise_and(&Value::Int(2), &Value::Int(1))); assert!(apply_bitwise_and(&Value::Int(3), &Value::Int(1))); }
282
283 #[test]
284 fn test_apply_bitwise_and_int_negative() {
285 assert!(apply_bitwise_and(&Value::Int(-1), &Value::Int(1))); assert!(apply_bitwise_and(&Value::Int(-2), &Value::Int(2))); assert!(!apply_bitwise_and(&Value::Int(-2), &Value::Int(1))); }
290
291 #[test]
292 fn test_apply_bitwise_and_int_zero() {
293 assert!(!apply_bitwise_and(&Value::Int(0), &Value::Int(0xFF))); assert!(!apply_bitwise_and(&Value::Int(0xFF), &Value::Int(0))); assert!(!apply_bitwise_and(&Value::Int(0), &Value::Int(0))); }
298
299 #[test]
300 fn test_apply_bitwise_and_int_extreme_values() {
301 assert!(apply_bitwise_and(&Value::Int(i64::MAX), &Value::Int(1))); assert!(apply_bitwise_and(
304 &Value::Int(i64::MIN),
305 &Value::Int(i64::MIN)
306 )); assert!(apply_bitwise_and(&Value::Int(i64::MIN), &Value::Int(-1))); }
309
310 #[test]
311 fn test_apply_bitwise_and_mixed_int_uint() {
312 assert!(apply_bitwise_and(&Value::Uint(0xFF), &Value::Int(0x0F))); assert!(apply_bitwise_and(&Value::Int(0xFF), &Value::Uint(0x0F))); assert!(!apply_bitwise_and(&Value::Uint(0xF0), &Value::Int(0x0F))); assert!(!apply_bitwise_and(&Value::Int(0xF0), &Value::Uint(0x0F))); }
318
319 #[test]
320 fn test_apply_bitwise_and_mixed_negative_uint() {
321 assert!(apply_bitwise_and(&Value::Int(-1), &Value::Uint(1))); assert!(apply_bitwise_and(&Value::Uint(1), &Value::Int(-1))); assert!(!apply_bitwise_and(&Value::Int(-2), &Value::Uint(1))); assert!(!apply_bitwise_and(&Value::Uint(1), &Value::Int(-2))); }
327
328 #[test]
329 fn test_apply_bitwise_and_non_integer_types() {
330 assert!(!apply_bitwise_and(
332 &Value::String("test".to_string()),
333 &Value::Uint(0x01)
334 ));
335 assert!(!apply_bitwise_and(
336 &Value::Uint(0x01),
337 &Value::String("test".to_string())
338 ));
339 assert!(!apply_bitwise_and(
340 &Value::Bytes(vec![1]),
341 &Value::Uint(0x01)
342 ));
343 assert!(!apply_bitwise_and(
344 &Value::Uint(0x01),
345 &Value::Bytes(vec![1])
346 ));
347 assert!(!apply_bitwise_and(
348 &Value::String("a".to_string()),
349 &Value::String("b".to_string())
350 ));
351 assert!(!apply_bitwise_and(
352 &Value::Bytes(vec![1]),
353 &Value::Bytes(vec![1])
354 ));
355 }
356
357 #[test]
358 fn test_apply_bitwise_and_all_non_integer_combinations() {
359 let non_integer_values = [Value::String("test".to_string()), Value::Bytes(vec![42])];
360
361 let integer_values = [Value::Uint(42), Value::Int(42)];
362
363 for non_int in &non_integer_values {
365 for int_val in &integer_values {
366 assert!(
367 !apply_bitwise_and(non_int, int_val),
368 "Non-integer & integer should be false: {non_int:?} & {int_val:?}"
369 );
370 assert!(
371 !apply_bitwise_and(int_val, non_int),
372 "Integer & non-integer should be false: {int_val:?} & {non_int:?}"
373 );
374 }
375 }
376
377 for left in &non_integer_values {
379 for right in &non_integer_values {
380 assert!(
381 !apply_bitwise_and(left, right),
382 "Non-integer & non-integer should be false: {left:?} & {right:?}"
383 );
384 }
385 }
386 }
387
388 #[test]
389 fn test_apply_bitwise_and_bit_patterns() {
390 let test_cases = vec![
392 (0b0000_0001_u64, 0b0000_0001_u64, true), (0b0000_0010_u64, 0b0000_0001_u64, false), (0b0000_0011_u64, 0b0000_0001_u64, true), (0b1111_1111_u64, 0b0000_1111_u64, true), (0b1111_0000_u64, 0b0000_1111_u64, false), (0b1010_1010_u64, 0b0101_0101_u64, false), (0b1010_1010_u64, 0b1010_1010_u64, true), (0b1111_1111_u64, 0b0000_0000_u64, false), (0b0000_0000_u64, 0b1111_1111_u64, false), ];
403
404 for (value, mask, expected) in test_cases {
405 assert_eq!(
406 apply_bitwise_and(&Value::Uint(value), &Value::Uint(mask)),
407 expected,
408 "apply_bitwise_and(0b{value:08b}, 0b{mask:08b}) should be {expected}"
409 );
410 }
411 }
412
413 #[test]
414 fn test_apply_bitwise_and_magic_file_patterns() {
415 let elf_magic = Value::Uint(0x7F45_4C46);
419 let elf_mask = Value::Uint(0xFFFF_FFFF);
420 assert!(apply_bitwise_and(&elf_magic, &elf_mask));
421
422 assert!(apply_bitwise_and(&elf_magic, &Value::Uint(0x7F00_0000))); assert!(apply_bitwise_and(&elf_magic, &Value::Uint(0x0045_0000))); assert!(apply_bitwise_and(&elf_magic, &Value::Uint(0x0000_4C00))); assert!(apply_bitwise_and(&elf_magic, &Value::Uint(0x0000_0046))); let zip_magic = Value::Uint(0x504B_0304);
430 assert!(apply_bitwise_and(&zip_magic, &Value::Uint(0x504B_0000))); assert!(!apply_bitwise_and(&zip_magic, &Value::Uint(0x0000_0001))); let pdf_magic = Value::Uint(0x2550_4446); assert!(apply_bitwise_and(&pdf_magic, &Value::Uint(0xFF00_0000))); assert!(apply_bitwise_and(&pdf_magic, &Value::Uint(0x00FF_0000))); }
438
439 #[test]
440 fn test_apply_bitwise_and_symmetry() {
441 let test_cases = vec![
443 (Value::Uint(0xFF), Value::Uint(0x0F)),
444 (Value::Int(42), Value::Int(24)),
445 (Value::Uint(0xAAAA), Value::Int(0x5555)),
446 (Value::Int(-1), Value::Uint(1)),
447 ];
448
449 for (left, right) in test_cases {
450 let left_to_right = apply_bitwise_and(&left, &right);
451 let right_to_left = apply_bitwise_and(&right, &left);
452 assert_eq!(
453 left_to_right, right_to_left,
454 "Bitwise AND should be commutative: {left:?} & {right:?}"
455 );
456 }
457 }
458
459 #[test]
460 fn test_apply_bitwise_and_associativity_concept() {
461 let value = Value::Uint(0b1111_0000);
464 let mask1 = Value::Uint(0b1100_0000);
465 let mask2 = Value::Uint(0b0011_0000);
466 let combined_mask = Value::Uint(0b1111_0000);
467
468 assert!(apply_bitwise_and(&value, &mask1));
470 assert!(apply_bitwise_and(&value, &mask2));
471 assert!(apply_bitwise_and(&value, &combined_mask));
472 }
473
474 #[test]
475 fn test_apply_bitwise_xor_uint() {
476 assert!(apply_bitwise_xor(&Value::Uint(0xFF), &Value::Uint(0x0F)));
477 assert!(!apply_bitwise_xor(&Value::Uint(0xFF), &Value::Uint(0xFF)));
478 assert!(apply_bitwise_xor(&Value::Uint(1), &Value::Uint(2)));
479 assert!(!apply_bitwise_xor(&Value::Uint(0), &Value::Uint(0)));
480 }
481
482 #[test]
483 fn test_apply_bitwise_xor_int() {
484 assert!(apply_bitwise_xor(&Value::Int(0xFF), &Value::Int(0x0F)));
485 assert!(!apply_bitwise_xor(&Value::Int(42), &Value::Int(42)));
486 assert!(apply_bitwise_xor(&Value::Int(-1), &Value::Int(0)));
487 }
488
489 #[test]
490 fn test_apply_bitwise_xor_cross_type() {
491 assert!(apply_bitwise_xor(&Value::Uint(0xFF), &Value::Int(0x0F)));
492 assert!(apply_bitwise_xor(&Value::Int(0xFF), &Value::Uint(0x0F)));
493 assert!(!apply_bitwise_xor(&Value::Uint(42), &Value::Int(42)));
494 }
495
496 #[test]
497 fn test_apply_bitwise_xor_same_value() {
498 assert!(!apply_bitwise_xor(&Value::Uint(100), &Value::Uint(100)));
499 assert!(!apply_bitwise_xor(&Value::Int(-1), &Value::Int(-1)));
500 }
501
502 #[test]
503 fn test_apply_bitwise_xor_non_numeric() {
504 assert!(!apply_bitwise_xor(
505 &Value::Bytes(vec![1, 2]),
506 &Value::Uint(1)
507 ));
508 assert!(!apply_bitwise_xor(
509 &Value::String("x".to_string()),
510 &Value::Uint(0xFF)
511 ));
512 }
513
514 #[test]
515 fn test_apply_bitwise_not_uint() {
516 assert!(apply_bitwise_not(&Value::Uint(0), &Value::Uint(u64::MAX)));
517 assert!(apply_bitwise_not(&Value::Uint(u64::MAX), &Value::Uint(0)));
518 assert!(!apply_bitwise_not(&Value::Uint(0xFF), &Value::Uint(0)));
519 }
520
521 #[test]
522 fn test_apply_bitwise_not_int() {
523 assert!(apply_bitwise_not(&Value::Int(0), &Value::Int(-1)));
524 assert!(apply_bitwise_not(&Value::Int(-1), &Value::Int(0)));
525 }
526
527 #[test]
528 fn test_apply_bitwise_not_all_bits_set() {
529 assert!(apply_bitwise_not(
530 &Value::Uint(0xFFFF_FFFF_FFFF_FFFF),
531 &Value::Uint(0)
532 ));
533 }
534
535 #[test]
536 fn test_apply_bitwise_not_non_numeric() {
537 assert!(!apply_bitwise_not(
538 &Value::Bytes(vec![0xff]),
539 &Value::Uint(0)
540 ));
541 assert!(!apply_bitwise_not(
542 &Value::String("x".to_string()),
543 &Value::Uint(0)
544 ));
545 }
546
547 #[test]
548 fn test_apply_bitwise_not_with_byte_width() {
549 assert!(apply_bitwise_not_with_width(
551 &Value::Uint(0x00),
552 &Value::Uint(0xFF),
553 Some(8)
554 ));
555 assert!(apply_bitwise_not_with_width(
557 &Value::Uint(0xFF),
558 &Value::Uint(0x00),
559 Some(8)
560 ));
561 assert!(apply_bitwise_not_with_width(
563 &Value::Uint(0x42),
564 &Value::Uint(0xBD),
565 Some(8)
566 ));
567 }
568
569 #[test]
570 fn test_apply_bitwise_not_with_short_width() {
571 assert!(apply_bitwise_not_with_width(
573 &Value::Uint(0x0000),
574 &Value::Uint(0xFFFF),
575 Some(16)
576 ));
577 assert!(apply_bitwise_not_with_width(
579 &Value::Uint(0x1234),
580 &Value::Uint(0xEDCB),
581 Some(16)
582 ));
583 }
584
585 #[test]
586 fn test_apply_bitwise_not_with_long_width() {
587 assert!(apply_bitwise_not_with_width(
589 &Value::Uint(0x0000_0000),
590 &Value::Uint(0xFFFF_FFFF),
591 Some(32)
592 ));
593 }
594
595 #[test]
596 fn test_apply_bitwise_not_with_quad_width() {
597 assert!(apply_bitwise_not_with_width(
599 &Value::Uint(0),
600 &Value::Uint(u64::MAX),
601 Some(64)
602 ));
603 }
604
605 #[test]
606 fn test_apply_bitwise_not_with_no_width() {
607 assert!(apply_bitwise_not_with_width(
609 &Value::Uint(0),
610 &Value::Uint(u64::MAX),
611 None
612 ));
613 }
614}