1use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
13pub enum OffsetSpec {
14 Absolute(i64),
28
29 Indirect {
47 base_offset: i64,
49 pointer_type: TypeKind,
51 adjustment: i64,
53 endian: Endianness,
55 },
56
57 Relative(i64),
67
68 FromEnd(i64),
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
82pub enum TypeKind {
83 Byte {
85 signed: bool,
87 },
88 Short {
90 endian: Endianness,
92 signed: bool,
94 },
95 Long {
97 endian: Endianness,
99 signed: bool,
101 },
102 Quad {
113 endian: Endianness,
115 signed: bool,
117 },
118 String {
120 max_length: Option<usize>,
122 },
123}
124
125impl TypeKind {
126 #[must_use]
140 pub const fn bit_width(&self) -> Option<u32> {
141 match self {
142 Self::Byte { .. } => Some(8),
143 Self::Short { .. } => Some(16),
144 Self::Long { .. } => Some(32),
145 Self::Quad { .. } => Some(64),
146 Self::String { .. } => None,
147 }
148 }
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
153pub enum Operator {
154 Equal,
165 NotEqual,
176 LessThan,
187 GreaterThan,
198 LessEqual,
209 GreaterEqual,
220 BitwiseAnd,
231 BitwiseAndMask(u64),
242 BitwiseXor,
253 BitwiseNot,
264 AnyValue,
275}
276
277#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
279pub enum Value {
280 Uint(u64),
282 Int(i64),
284 Bytes(Vec<u8>),
286 String(String),
288}
289
290#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
292pub enum Endianness {
293 Little,
295 Big,
297 Native,
299}
300
301#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
318pub enum StrengthModifier {
319 Add(i32),
321 Subtract(i32),
323 Multiply(i32),
325 Divide(i32),
327 Set(i32),
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
333pub struct MagicRule {
334 pub offset: OffsetSpec,
336 pub typ: TypeKind,
338 pub op: Operator,
340 pub value: Value,
342 pub message: String,
344 pub children: Vec<MagicRule>,
346 pub level: u32,
348 pub strength_modifier: Option<StrengthModifier>,
350}
351
352#[cfg(test)]
361mod tests {
362 use super::*;
363
364 #[test]
365 fn test_offset_spec_absolute() {
366 let offset = OffsetSpec::Absolute(42);
367 assert_eq!(offset, OffsetSpec::Absolute(42));
368
369 let negative = OffsetSpec::Absolute(-10);
371 assert_eq!(negative, OffsetSpec::Absolute(-10));
372 }
373
374 #[test]
375 fn test_offset_spec_indirect() {
376 let indirect = OffsetSpec::Indirect {
377 base_offset: 0x20,
378 pointer_type: TypeKind::Long {
379 endian: Endianness::Little,
380 signed: false,
381 },
382 adjustment: 4,
383 endian: Endianness::Little,
384 };
385
386 match indirect {
387 OffsetSpec::Indirect {
388 base_offset,
389 adjustment,
390 ..
391 } => {
392 assert_eq!(base_offset, 0x20);
393 assert_eq!(adjustment, 4);
394 }
395 _ => panic!("Expected Indirect variant"),
396 }
397 }
398
399 #[test]
400 fn test_offset_spec_relative() {
401 let relative = OffsetSpec::Relative(8);
402 assert_eq!(relative, OffsetSpec::Relative(8));
403
404 let negative_relative = OffsetSpec::Relative(-4);
406 assert_eq!(negative_relative, OffsetSpec::Relative(-4));
407 }
408
409 #[test]
410 fn test_offset_spec_from_end() {
411 let from_end = OffsetSpec::FromEnd(-16);
412 assert_eq!(from_end, OffsetSpec::FromEnd(-16));
413
414 let positive_from_end = OffsetSpec::FromEnd(8);
416 assert_eq!(positive_from_end, OffsetSpec::FromEnd(8));
417 }
418
419 #[test]
420 fn test_offset_spec_debug() {
421 let offset = OffsetSpec::Absolute(100);
422 let debug_str = format!("{offset:?}");
423 assert!(debug_str.contains("Absolute"));
424 assert!(debug_str.contains("100"));
425 }
426
427 #[test]
428 fn test_offset_spec_clone() {
429 let original = OffsetSpec::Indirect {
430 base_offset: 0x10,
431 pointer_type: TypeKind::Short {
432 endian: Endianness::Big,
433 signed: true,
434 },
435 adjustment: -2,
436 endian: Endianness::Big,
437 };
438
439 let cloned = original.clone();
440 assert_eq!(original, cloned);
441 }
442
443 #[test]
444 fn test_offset_spec_serialization() {
445 let offset = OffsetSpec::Absolute(42);
446
447 let json = serde_json::to_string(&offset).expect("Failed to serialize");
449 let deserialized: OffsetSpec = serde_json::from_str(&json).expect("Failed to deserialize");
450
451 assert_eq!(offset, deserialized);
452 }
453
454 #[test]
455 fn test_offset_spec_indirect_serialization() {
456 let indirect = OffsetSpec::Indirect {
457 base_offset: 0x100,
458 pointer_type: TypeKind::Long {
459 endian: Endianness::Native,
460 signed: false,
461 },
462 adjustment: 12,
463 endian: Endianness::Native,
464 };
465
466 let json = serde_json::to_string(&indirect).expect("Failed to serialize");
468 let deserialized: OffsetSpec = serde_json::from_str(&json).expect("Failed to deserialize");
469
470 assert_eq!(indirect, deserialized);
471 }
472
473 #[test]
474 fn test_all_offset_spec_variants() {
475 let variants = [
476 OffsetSpec::Absolute(0),
477 OffsetSpec::Absolute(-100),
478 OffsetSpec::Indirect {
479 base_offset: 0x20,
480 pointer_type: TypeKind::Byte { signed: true },
481 adjustment: 0,
482 endian: Endianness::Little,
483 },
484 OffsetSpec::Relative(50),
485 OffsetSpec::Relative(-25),
486 OffsetSpec::FromEnd(-8),
487 OffsetSpec::FromEnd(4),
488 ];
489
490 for (i, variant) in variants.iter().enumerate() {
492 for (j, other) in variants.iter().enumerate() {
493 if i != j {
494 assert_ne!(
495 variant, other,
496 "Variants at indices {i} and {j} should be different"
497 );
498 }
499 }
500 }
501 }
502
503 #[test]
504 fn test_endianness_variants() {
505 let endianness_values = vec![Endianness::Little, Endianness::Big, Endianness::Native];
506
507 for endian in endianness_values {
508 let indirect = OffsetSpec::Indirect {
509 base_offset: 0,
510 pointer_type: TypeKind::Long {
511 endian,
512 signed: false,
513 },
514 adjustment: 0,
515 endian,
516 };
517
518 match indirect {
520 OffsetSpec::Indirect {
521 endian: actual_endian,
522 ..
523 } => {
524 assert_eq!(endian, actual_endian);
525 }
526 _ => panic!("Expected Indirect variant"),
527 }
528 }
529 }
530
531 #[test]
533 fn test_value_uint() {
534 let value = Value::Uint(42);
535 assert_eq!(value, Value::Uint(42));
536
537 let large_value = Value::Uint(u64::MAX);
539 assert_eq!(large_value, Value::Uint(u64::MAX));
540 }
541
542 #[test]
543 fn test_value_int() {
544 let positive = Value::Int(100);
545 assert_eq!(positive, Value::Int(100));
546
547 let negative = Value::Int(-50);
548 assert_eq!(negative, Value::Int(-50));
549
550 let max_int = Value::Int(i64::MAX);
552 let min_int = Value::Int(i64::MIN);
553 assert_eq!(max_int, Value::Int(i64::MAX));
554 assert_eq!(min_int, Value::Int(i64::MIN));
555 }
556
557 #[test]
558 fn test_value_bytes() {
559 let empty_bytes = Value::Bytes(vec![]);
560 assert_eq!(empty_bytes, Value::Bytes(vec![]));
561
562 let some_bytes = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
563 assert_eq!(some_bytes, Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]));
564
565 let other_bytes = Value::Bytes(vec![0x50, 0x4b, 0x03, 0x04]);
567 assert_ne!(some_bytes, other_bytes);
568 }
569
570 #[test]
571 fn test_value_string() {
572 let empty_string = Value::String(String::new());
573 assert_eq!(empty_string, Value::String(String::new()));
574
575 let hello = Value::String("Hello, World!".to_string());
576 assert_eq!(hello, Value::String("Hello, World!".to_string()));
577
578 let unicode = Value::String("🦀 Rust".to_string());
580 assert_eq!(unicode, Value::String("🦀 Rust".to_string()));
581 }
582
583 #[test]
584 fn test_value_comparison() {
585 let uint_val = Value::Uint(42);
587 let int_val = Value::Int(42);
588 let bytes_val = Value::Bytes(vec![42]);
589 let string_val = Value::String("42".to_string());
590
591 assert_ne!(uint_val, int_val);
592 assert_ne!(uint_val, bytes_val);
593 assert_ne!(uint_val, string_val);
594 assert_ne!(int_val, bytes_val);
595 assert_ne!(int_val, string_val);
596 assert_ne!(bytes_val, string_val);
597 }
598
599 #[test]
600 fn test_value_debug() {
601 let uint_val = Value::Uint(123);
602 let debug_str = format!("{uint_val:?}");
603 assert!(debug_str.contains("Uint"));
604 assert!(debug_str.contains("123"));
605
606 let string_val = Value::String("test".to_string());
607 let debug_str = format!("{string_val:?}");
608 assert!(debug_str.contains("String"));
609 assert!(debug_str.contains("test"));
610 }
611
612 #[test]
613 fn test_value_clone() {
614 let original = Value::Bytes(vec![1, 2, 3, 4]);
615 let cloned = original.clone();
616 assert_eq!(original, cloned);
617
618 match (original, cloned) {
620 (Value::Bytes(orig_bytes), Value::Bytes(cloned_bytes)) => {
621 assert_eq!(orig_bytes, cloned_bytes);
622 }
624 _ => panic!("Expected Bytes variants"),
625 }
626 }
627
628 #[test]
629 fn test_value_serialization() {
630 let values = vec![
631 Value::Uint(42),
632 Value::Int(-100),
633 Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
634 Value::String("ELF executable".to_string()),
635 ];
636
637 for value in values {
638 let json = serde_json::to_string(&value).expect("Failed to serialize Value");
640 let deserialized: Value =
641 serde_json::from_str(&json).expect("Failed to deserialize Value");
642 assert_eq!(value, deserialized);
643 }
644 }
645
646 #[test]
647 fn test_value_serialization_edge_cases() {
648 let empty_bytes = Value::Bytes(vec![]);
650 let json = serde_json::to_string(&empty_bytes).expect("Failed to serialize empty bytes");
651 let deserialized: Value =
652 serde_json::from_str(&json).expect("Failed to deserialize empty bytes");
653 assert_eq!(empty_bytes, deserialized);
654
655 let empty_string = Value::String(String::new());
656 let json = serde_json::to_string(&empty_string).expect("Failed to serialize empty string");
657 let deserialized: Value =
658 serde_json::from_str(&json).expect("Failed to deserialize empty string");
659 assert_eq!(empty_string, deserialized);
660
661 let max_uint = Value::Uint(u64::MAX);
663 let json = serde_json::to_string(&max_uint).expect("Failed to serialize max uint");
664 let deserialized: Value =
665 serde_json::from_str(&json).expect("Failed to deserialize max uint");
666 assert_eq!(max_uint, deserialized);
667
668 let min_int = Value::Int(i64::MIN);
669 let json = serde_json::to_string(&min_int).expect("Failed to serialize min int");
670 let deserialized: Value =
671 serde_json::from_str(&json).expect("Failed to deserialize min int");
672 assert_eq!(min_int, deserialized);
673 }
674
675 #[test]
677 fn test_type_kind_byte() {
678 let byte_type = TypeKind::Byte { signed: true };
679 assert_eq!(byte_type, TypeKind::Byte { signed: true });
680 }
681
682 #[test]
683 fn test_type_kind_short() {
684 let short_little_endian = TypeKind::Short {
685 endian: Endianness::Little,
686 signed: false,
687 };
688 let short_big_endian = TypeKind::Short {
689 endian: Endianness::Big,
690 signed: true,
691 };
692
693 assert_ne!(short_little_endian, short_big_endian);
694 assert_eq!(short_little_endian, short_little_endian.clone());
695 }
696
697 #[test]
698 fn test_type_kind_long() {
699 let long_native = TypeKind::Long {
700 endian: Endianness::Native,
701 signed: true,
702 };
703
704 match long_native {
705 TypeKind::Long { endian, signed } => {
706 assert_eq!(endian, Endianness::Native);
707 assert!(signed);
708 }
709 _ => panic!("Expected Long variant"),
710 }
711 }
712
713 #[test]
714 fn test_type_kind_string() {
715 let unlimited_string = TypeKind::String { max_length: None };
716 let limited_string = TypeKind::String {
717 max_length: Some(256),
718 };
719
720 assert_ne!(unlimited_string, limited_string);
721 assert_eq!(unlimited_string, unlimited_string.clone());
722 }
723
724 #[test]
725 fn test_type_kind_serialization() {
726 let types = vec![
727 TypeKind::Byte { signed: true },
728 TypeKind::Short {
729 endian: Endianness::Little,
730 signed: false,
731 },
732 TypeKind::Long {
733 endian: Endianness::Big,
734 signed: true,
735 },
736 TypeKind::Quad {
737 endian: Endianness::Little,
738 signed: false,
739 },
740 TypeKind::Quad {
741 endian: Endianness::Big,
742 signed: true,
743 },
744 TypeKind::String { max_length: None },
745 TypeKind::String {
746 max_length: Some(128),
747 },
748 ];
749
750 for typ in types {
751 let json = serde_json::to_string(&typ).expect("Failed to serialize TypeKind");
752 let deserialized: TypeKind =
753 serde_json::from_str(&json).expect("Failed to deserialize TypeKind");
754 assert_eq!(typ, deserialized);
755 }
756 }
757
758 #[test]
760 fn test_operator_variants() {
761 let operators = [
762 Operator::Equal,
763 Operator::NotEqual,
764 Operator::BitwiseAnd,
765 Operator::BitwiseXor,
766 Operator::BitwiseNot,
767 Operator::AnyValue,
768 ];
769
770 for (i, op) in operators.iter().enumerate() {
771 for (j, other) in operators.iter().enumerate() {
772 if i == j {
773 assert_eq!(op, other);
774 } else {
775 assert_ne!(op, other);
776 }
777 }
778 }
779 }
780
781 #[test]
782 fn test_operator_serialization() {
783 let operators = vec![
784 Operator::Equal,
785 Operator::NotEqual,
786 Operator::BitwiseAnd,
787 Operator::BitwiseXor,
788 Operator::BitwiseNot,
789 Operator::AnyValue,
790 ];
791
792 for op in operators {
793 let json = serde_json::to_string(&op).expect("Failed to serialize Operator");
794 let deserialized: Operator =
795 serde_json::from_str(&json).expect("Failed to deserialize Operator");
796 assert_eq!(op, deserialized);
797 }
798 }
799
800 #[test]
802 fn test_magic_rule_creation() {
803 let rule = MagicRule {
804 offset: OffsetSpec::Absolute(0),
805 typ: TypeKind::Byte { signed: true },
806 op: Operator::Equal,
807 value: Value::Uint(0x7f),
808 message: "ELF magic".to_string(),
809 children: vec![],
810 level: 0,
811 strength_modifier: None,
812 };
813
814 assert_eq!(rule.message, "ELF magic");
815 assert_eq!(rule.level, 0);
816 assert!(rule.children.is_empty());
817 }
818
819 #[test]
820 fn test_magic_rule_with_children() {
821 let child_rule = MagicRule {
822 offset: OffsetSpec::Absolute(4),
823 typ: TypeKind::Byte { signed: true },
824 op: Operator::Equal,
825 value: Value::Uint(1),
826 message: "32-bit".to_string(),
827 children: vec![],
828 level: 1,
829 strength_modifier: None,
830 };
831
832 let parent_rule = MagicRule {
833 offset: OffsetSpec::Absolute(0),
834 typ: TypeKind::Long {
835 endian: Endianness::Little,
836 signed: false,
837 },
838 op: Operator::Equal,
839 value: Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
840 message: "ELF executable".to_string(),
841 children: vec![child_rule],
842 level: 0,
843 strength_modifier: None,
844 };
845
846 assert_eq!(parent_rule.children.len(), 1);
847 assert_eq!(parent_rule.children[0].level, 1);
848 assert_eq!(parent_rule.children[0].message, "32-bit");
849 }
850
851 #[test]
852 fn test_magic_rule_serialization() {
853 let rule = MagicRule {
854 offset: OffsetSpec::Absolute(16),
855 typ: TypeKind::Short {
856 endian: Endianness::Little,
857 signed: false,
858 },
859 op: Operator::NotEqual,
860 value: Value::Uint(0),
861 message: "Non-zero short value".to_string(),
862 children: vec![],
863 level: 2,
864 strength_modifier: None,
865 };
866
867 let json = serde_json::to_string(&rule).expect("Failed to serialize MagicRule");
868 let deserialized: MagicRule =
869 serde_json::from_str(&json).expect("Failed to deserialize MagicRule");
870
871 assert_eq!(rule.message, deserialized.message);
872 assert_eq!(rule.level, deserialized.level);
873 assert_eq!(rule.children.len(), deserialized.children.len());
874 }
875
876 #[test]
878 fn test_strength_modifier_variants() {
879 let add = StrengthModifier::Add(10);
880 let sub = StrengthModifier::Subtract(5);
881 let mul = StrengthModifier::Multiply(2);
882 let div = StrengthModifier::Divide(2);
883 let set = StrengthModifier::Set(50);
884
885 assert_eq!(add, StrengthModifier::Add(10));
887 assert_eq!(sub, StrengthModifier::Subtract(5));
888 assert_eq!(mul, StrengthModifier::Multiply(2));
889 assert_eq!(div, StrengthModifier::Divide(2));
890 assert_eq!(set, StrengthModifier::Set(50));
891
892 assert_ne!(add, sub);
894 assert_ne!(mul, div);
895 assert_ne!(set, add);
896 }
897
898 #[test]
899 fn test_strength_modifier_negative_values() {
900 let add_negative = StrengthModifier::Add(-10);
901 let sub_negative = StrengthModifier::Subtract(-5);
902 let set_negative = StrengthModifier::Set(-50);
903
904 assert_eq!(add_negative, StrengthModifier::Add(-10));
905 assert_eq!(sub_negative, StrengthModifier::Subtract(-5));
906 assert_eq!(set_negative, StrengthModifier::Set(-50));
907 }
908
909 #[test]
910 fn test_strength_modifier_serialization() {
911 let modifiers = vec![
912 StrengthModifier::Add(10),
913 StrengthModifier::Subtract(5),
914 StrengthModifier::Multiply(2),
915 StrengthModifier::Divide(3),
916 StrengthModifier::Set(100),
917 ];
918
919 for modifier in modifiers {
920 let json =
921 serde_json::to_string(&modifier).expect("Failed to serialize StrengthModifier");
922 let deserialized: StrengthModifier =
923 serde_json::from_str(&json).expect("Failed to deserialize StrengthModifier");
924 assert_eq!(modifier, deserialized);
925 }
926 }
927
928 #[test]
929 fn test_strength_modifier_debug() {
930 let modifier = StrengthModifier::Add(25);
931 let debug_str = format!("{modifier:?}");
932 assert!(debug_str.contains("Add"));
933 assert!(debug_str.contains("25"));
934 }
935
936 #[test]
937 fn test_strength_modifier_clone() {
938 let original = StrengthModifier::Multiply(4);
939 let cloned = original;
940 assert_eq!(original, cloned);
941 }
942
943 #[test]
944 fn test_magic_rule_with_strength_modifier() {
945 let rule = MagicRule {
946 offset: OffsetSpec::Absolute(0),
947 typ: TypeKind::Byte { signed: true },
948 op: Operator::Equal,
949 value: Value::Uint(0x7f),
950 message: "ELF magic".to_string(),
951 children: vec![],
952 level: 0,
953 strength_modifier: Some(StrengthModifier::Add(20)),
954 };
955
956 assert_eq!(rule.strength_modifier, Some(StrengthModifier::Add(20)));
957
958 let json = serde_json::to_string(&rule).expect("Failed to serialize MagicRule");
960 let deserialized: MagicRule =
961 serde_json::from_str(&json).expect("Failed to deserialize MagicRule");
962 assert_eq!(rule.strength_modifier, deserialized.strength_modifier);
963 }
964
965 #[test]
966 fn test_magic_rule_without_strength_modifier() {
967 let rule = MagicRule {
968 offset: OffsetSpec::Absolute(0),
969 typ: TypeKind::Byte { signed: true },
970 op: Operator::Equal,
971 value: Value::Uint(0x7f),
972 message: "ELF magic".to_string(),
973 children: vec![],
974 level: 0,
975 strength_modifier: None,
976 };
977
978 assert_eq!(rule.strength_modifier, None);
979 }
980}