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 Float {
129 endian: Endianness,
131 },
132 Double {
143 endian: Endianness,
145 },
146 String {
148 max_length: Option<usize>,
150 },
151}
152
153impl TypeKind {
154 #[must_use]
170 pub const fn bit_width(&self) -> Option<u32> {
171 match self {
172 Self::Byte { .. } => Some(8),
173 Self::Short { .. } => Some(16),
174 Self::Long { .. } | Self::Float { .. } => Some(32),
175 Self::Quad { .. } | Self::Double { .. } => Some(64),
176 Self::String { .. } => None,
177 }
178 }
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
183pub enum Operator {
184 Equal,
195 NotEqual,
206 LessThan,
217 GreaterThan,
228 LessEqual,
239 GreaterEqual,
250 BitwiseAnd,
261 BitwiseAndMask(u64),
272 BitwiseXor,
283 BitwiseNot,
294 AnyValue,
305}
306
307#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
309pub enum Value {
310 Uint(u64),
312 Int(i64),
314 Float(f64),
325 Bytes(Vec<u8>),
327 String(String),
329}
330
331#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
333pub enum Endianness {
334 Little,
336 Big,
338 Native,
340}
341
342#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
359pub enum StrengthModifier {
360 Add(i32),
362 Subtract(i32),
364 Multiply(i32),
366 Divide(i32),
368 Set(i32),
370}
371
372#[derive(Debug, Clone, Serialize, Deserialize)]
374pub struct MagicRule {
375 pub offset: OffsetSpec,
377 pub typ: TypeKind,
379 pub op: Operator,
381 pub value: Value,
383 pub message: String,
385 pub children: Vec<MagicRule>,
387 pub level: u32,
389 pub strength_modifier: Option<StrengthModifier>,
391}
392
393#[cfg(test)]
402mod tests {
403 use super::*;
404
405 #[test]
406 fn test_offset_spec_absolute() {
407 let offset = OffsetSpec::Absolute(42);
408 assert_eq!(offset, OffsetSpec::Absolute(42));
409
410 let negative = OffsetSpec::Absolute(-10);
412 assert_eq!(negative, OffsetSpec::Absolute(-10));
413 }
414
415 #[test]
416 fn test_offset_spec_indirect() {
417 let indirect = OffsetSpec::Indirect {
418 base_offset: 0x20,
419 pointer_type: TypeKind::Long {
420 endian: Endianness::Little,
421 signed: false,
422 },
423 adjustment: 4,
424 endian: Endianness::Little,
425 };
426
427 match indirect {
428 OffsetSpec::Indirect {
429 base_offset,
430 adjustment,
431 ..
432 } => {
433 assert_eq!(base_offset, 0x20);
434 assert_eq!(adjustment, 4);
435 }
436 _ => panic!("Expected Indirect variant"),
437 }
438 }
439
440 #[test]
441 fn test_offset_spec_relative() {
442 let relative = OffsetSpec::Relative(8);
443 assert_eq!(relative, OffsetSpec::Relative(8));
444
445 let negative_relative = OffsetSpec::Relative(-4);
447 assert_eq!(negative_relative, OffsetSpec::Relative(-4));
448 }
449
450 #[test]
451 fn test_offset_spec_from_end() {
452 let from_end = OffsetSpec::FromEnd(-16);
453 assert_eq!(from_end, OffsetSpec::FromEnd(-16));
454
455 let positive_from_end = OffsetSpec::FromEnd(8);
457 assert_eq!(positive_from_end, OffsetSpec::FromEnd(8));
458 }
459
460 #[test]
461 fn test_offset_spec_debug() {
462 let offset = OffsetSpec::Absolute(100);
463 let debug_str = format!("{offset:?}");
464 assert!(debug_str.contains("Absolute"));
465 assert!(debug_str.contains("100"));
466 }
467
468 #[test]
469 fn test_offset_spec_clone() {
470 let original = OffsetSpec::Indirect {
471 base_offset: 0x10,
472 pointer_type: TypeKind::Short {
473 endian: Endianness::Big,
474 signed: true,
475 },
476 adjustment: -2,
477 endian: Endianness::Big,
478 };
479
480 let cloned = original.clone();
481 assert_eq!(original, cloned);
482 }
483
484 #[test]
485 fn test_offset_spec_serialization() {
486 let offset = OffsetSpec::Absolute(42);
487
488 let json = serde_json::to_string(&offset).expect("Failed to serialize");
490 let deserialized: OffsetSpec = serde_json::from_str(&json).expect("Failed to deserialize");
491
492 assert_eq!(offset, deserialized);
493 }
494
495 #[test]
496 fn test_offset_spec_indirect_serialization() {
497 let indirect = OffsetSpec::Indirect {
498 base_offset: 0x100,
499 pointer_type: TypeKind::Long {
500 endian: Endianness::Native,
501 signed: false,
502 },
503 adjustment: 12,
504 endian: Endianness::Native,
505 };
506
507 let json = serde_json::to_string(&indirect).expect("Failed to serialize");
509 let deserialized: OffsetSpec = serde_json::from_str(&json).expect("Failed to deserialize");
510
511 assert_eq!(indirect, deserialized);
512 }
513
514 #[test]
515 fn test_all_offset_spec_variants() {
516 let variants = [
517 OffsetSpec::Absolute(0),
518 OffsetSpec::Absolute(-100),
519 OffsetSpec::Indirect {
520 base_offset: 0x20,
521 pointer_type: TypeKind::Byte { signed: true },
522 adjustment: 0,
523 endian: Endianness::Little,
524 },
525 OffsetSpec::Relative(50),
526 OffsetSpec::Relative(-25),
527 OffsetSpec::FromEnd(-8),
528 OffsetSpec::FromEnd(4),
529 ];
530
531 for (i, variant) in variants.iter().enumerate() {
533 for (j, other) in variants.iter().enumerate() {
534 if i != j {
535 assert_ne!(
536 variant, other,
537 "Variants at indices {i} and {j} should be different"
538 );
539 }
540 }
541 }
542 }
543
544 #[test]
545 fn test_endianness_variants() {
546 let endianness_values = vec![Endianness::Little, Endianness::Big, Endianness::Native];
547
548 for endian in endianness_values {
549 let indirect = OffsetSpec::Indirect {
550 base_offset: 0,
551 pointer_type: TypeKind::Long {
552 endian,
553 signed: false,
554 },
555 adjustment: 0,
556 endian,
557 };
558
559 match indirect {
561 OffsetSpec::Indirect {
562 endian: actual_endian,
563 ..
564 } => {
565 assert_eq!(endian, actual_endian);
566 }
567 _ => panic!("Expected Indirect variant"),
568 }
569 }
570 }
571
572 #[test]
574 fn test_value_uint() {
575 let value = Value::Uint(42);
576 assert_eq!(value, Value::Uint(42));
577
578 let large_value = Value::Uint(u64::MAX);
580 assert_eq!(large_value, Value::Uint(u64::MAX));
581 }
582
583 #[test]
584 fn test_value_int() {
585 let positive = Value::Int(100);
586 assert_eq!(positive, Value::Int(100));
587
588 let negative = Value::Int(-50);
589 assert_eq!(negative, Value::Int(-50));
590
591 let max_int = Value::Int(i64::MAX);
593 let min_int = Value::Int(i64::MIN);
594 assert_eq!(max_int, Value::Int(i64::MAX));
595 assert_eq!(min_int, Value::Int(i64::MIN));
596 }
597
598 #[test]
599 fn test_value_bytes() {
600 let empty_bytes = Value::Bytes(vec![]);
601 assert_eq!(empty_bytes, Value::Bytes(vec![]));
602
603 let some_bytes = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
604 assert_eq!(some_bytes, Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]));
605
606 let other_bytes = Value::Bytes(vec![0x50, 0x4b, 0x03, 0x04]);
608 assert_ne!(some_bytes, other_bytes);
609 }
610
611 #[test]
612 fn test_value_string() {
613 let empty_string = Value::String(String::new());
614 assert_eq!(empty_string, Value::String(String::new()));
615
616 let hello = Value::String("Hello, World!".to_string());
617 assert_eq!(hello, Value::String("Hello, World!".to_string()));
618
619 let unicode = Value::String("🦀 Rust".to_string());
621 assert_eq!(unicode, Value::String("🦀 Rust".to_string()));
622 }
623
624 #[test]
625 fn test_value_comparison() {
626 let uint_val = Value::Uint(42);
628 let int_val = Value::Int(42);
629 let float_val = Value::Float(42.0);
630 let bytes_val = Value::Bytes(vec![42]);
631 let string_val = Value::String("42".to_string());
632
633 assert_ne!(uint_val, int_val);
634 assert_ne!(uint_val, float_val);
635 assert_ne!(uint_val, bytes_val);
636 assert_ne!(uint_val, string_val);
637 assert_ne!(int_val, float_val);
638 assert_ne!(int_val, bytes_val);
639 assert_ne!(int_val, string_val);
640 assert_ne!(float_val, bytes_val);
641 assert_ne!(float_val, string_val);
642 assert_ne!(bytes_val, string_val);
643 }
644
645 #[test]
646 fn test_value_debug() {
647 let uint_val = Value::Uint(123);
648 let debug_str = format!("{uint_val:?}");
649 assert!(debug_str.contains("Uint"));
650 assert!(debug_str.contains("123"));
651
652 let string_val = Value::String("test".to_string());
653 let debug_str = format!("{string_val:?}");
654 assert!(debug_str.contains("String"));
655 assert!(debug_str.contains("test"));
656 }
657
658 #[test]
659 fn test_value_clone() {
660 let original = Value::Bytes(vec![1, 2, 3, 4]);
661 let cloned = original.clone();
662 assert_eq!(original, cloned);
663
664 match (original, cloned) {
666 (Value::Bytes(orig_bytes), Value::Bytes(cloned_bytes)) => {
667 assert_eq!(orig_bytes, cloned_bytes);
668 }
670 _ => panic!("Expected Bytes variants"),
671 }
672 }
673
674 #[test]
675 fn test_value_float() {
676 let value = Value::Float(3.125);
677 assert_eq!(value, Value::Float(3.125));
678
679 let negative = Value::Float(-1.5);
680 assert_eq!(negative, Value::Float(-1.5));
681
682 let zero = Value::Float(0.0);
683 assert_eq!(zero, Value::Float(0.0));
684 }
685
686 #[test]
687 fn test_value_serialization() {
688 let values = vec![
689 Value::Uint(42),
690 Value::Int(-100),
691 Value::Float(3.125),
692 Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
693 Value::String("ELF executable".to_string()),
694 ];
695
696 for value in values {
697 let json = serde_json::to_string(&value).expect("Failed to serialize Value");
699 let deserialized: Value =
700 serde_json::from_str(&json).expect("Failed to deserialize Value");
701 assert_eq!(value, deserialized);
702 }
703 }
704
705 #[test]
706 fn test_value_serialization_edge_cases() {
707 let empty_bytes = Value::Bytes(vec![]);
709 let json = serde_json::to_string(&empty_bytes).expect("Failed to serialize empty bytes");
710 let deserialized: Value =
711 serde_json::from_str(&json).expect("Failed to deserialize empty bytes");
712 assert_eq!(empty_bytes, deserialized);
713
714 let empty_string = Value::String(String::new());
715 let json = serde_json::to_string(&empty_string).expect("Failed to serialize empty string");
716 let deserialized: Value =
717 serde_json::from_str(&json).expect("Failed to deserialize empty string");
718 assert_eq!(empty_string, deserialized);
719
720 let max_uint = Value::Uint(u64::MAX);
722 let json = serde_json::to_string(&max_uint).expect("Failed to serialize max uint");
723 let deserialized: Value =
724 serde_json::from_str(&json).expect("Failed to deserialize max uint");
725 assert_eq!(max_uint, deserialized);
726
727 let min_int = Value::Int(i64::MIN);
728 let json = serde_json::to_string(&min_int).expect("Failed to serialize min int");
729 let deserialized: Value =
730 serde_json::from_str(&json).expect("Failed to deserialize min int");
731 assert_eq!(min_int, deserialized);
732 }
733
734 #[test]
736 fn test_type_kind_byte() {
737 let byte_type = TypeKind::Byte { signed: true };
738 assert_eq!(byte_type, TypeKind::Byte { signed: true });
739 }
740
741 #[test]
742 fn test_type_kind_short() {
743 let short_little_endian = TypeKind::Short {
744 endian: Endianness::Little,
745 signed: false,
746 };
747 let short_big_endian = TypeKind::Short {
748 endian: Endianness::Big,
749 signed: true,
750 };
751
752 assert_ne!(short_little_endian, short_big_endian);
753 assert_eq!(short_little_endian, short_little_endian.clone());
754 }
755
756 #[test]
757 fn test_type_kind_long() {
758 let long_native = TypeKind::Long {
759 endian: Endianness::Native,
760 signed: true,
761 };
762
763 match long_native {
764 TypeKind::Long { endian, signed } => {
765 assert_eq!(endian, Endianness::Native);
766 assert!(signed);
767 }
768 _ => panic!("Expected Long variant"),
769 }
770 }
771
772 #[test]
773 fn test_type_kind_string() {
774 let unlimited_string = TypeKind::String { max_length: None };
775 let limited_string = TypeKind::String {
776 max_length: Some(256),
777 };
778
779 assert_ne!(unlimited_string, limited_string);
780 assert_eq!(unlimited_string, unlimited_string.clone());
781 }
782
783 #[test]
784 fn test_type_kind_serialization() {
785 let types = vec![
786 TypeKind::Byte { signed: true },
787 TypeKind::Short {
788 endian: Endianness::Little,
789 signed: false,
790 },
791 TypeKind::Long {
792 endian: Endianness::Big,
793 signed: true,
794 },
795 TypeKind::Quad {
796 endian: Endianness::Little,
797 signed: false,
798 },
799 TypeKind::Quad {
800 endian: Endianness::Big,
801 signed: true,
802 },
803 TypeKind::Float {
804 endian: Endianness::Native,
805 },
806 TypeKind::Float {
807 endian: Endianness::Big,
808 },
809 TypeKind::Double {
810 endian: Endianness::Little,
811 },
812 TypeKind::Double {
813 endian: Endianness::Native,
814 },
815 TypeKind::String { max_length: None },
816 TypeKind::String {
817 max_length: Some(128),
818 },
819 ];
820
821 for typ in types {
822 let json = serde_json::to_string(&typ).expect("Failed to serialize TypeKind");
823 let deserialized: TypeKind =
824 serde_json::from_str(&json).expect("Failed to deserialize TypeKind");
825 assert_eq!(typ, deserialized);
826 }
827 }
828
829 #[test]
831 fn test_operator_variants() {
832 let operators = [
833 Operator::Equal,
834 Operator::NotEqual,
835 Operator::BitwiseAnd,
836 Operator::BitwiseXor,
837 Operator::BitwiseNot,
838 Operator::AnyValue,
839 ];
840
841 for (i, op) in operators.iter().enumerate() {
842 for (j, other) in operators.iter().enumerate() {
843 if i == j {
844 assert_eq!(op, other);
845 } else {
846 assert_ne!(op, other);
847 }
848 }
849 }
850 }
851
852 #[test]
853 fn test_operator_serialization() {
854 let operators = vec![
855 Operator::Equal,
856 Operator::NotEqual,
857 Operator::BitwiseAnd,
858 Operator::BitwiseXor,
859 Operator::BitwiseNot,
860 Operator::AnyValue,
861 ];
862
863 for op in operators {
864 let json = serde_json::to_string(&op).expect("Failed to serialize Operator");
865 let deserialized: Operator =
866 serde_json::from_str(&json).expect("Failed to deserialize Operator");
867 assert_eq!(op, deserialized);
868 }
869 }
870
871 #[test]
873 fn test_magic_rule_creation() {
874 let rule = MagicRule {
875 offset: OffsetSpec::Absolute(0),
876 typ: TypeKind::Byte { signed: true },
877 op: Operator::Equal,
878 value: Value::Uint(0x7f),
879 message: "ELF magic".to_string(),
880 children: vec![],
881 level: 0,
882 strength_modifier: None,
883 };
884
885 assert_eq!(rule.message, "ELF magic");
886 assert_eq!(rule.level, 0);
887 assert!(rule.children.is_empty());
888 }
889
890 #[test]
891 fn test_magic_rule_with_children() {
892 let child_rule = MagicRule {
893 offset: OffsetSpec::Absolute(4),
894 typ: TypeKind::Byte { signed: true },
895 op: Operator::Equal,
896 value: Value::Uint(1),
897 message: "32-bit".to_string(),
898 children: vec![],
899 level: 1,
900 strength_modifier: None,
901 };
902
903 let parent_rule = MagicRule {
904 offset: OffsetSpec::Absolute(0),
905 typ: TypeKind::Long {
906 endian: Endianness::Little,
907 signed: false,
908 },
909 op: Operator::Equal,
910 value: Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
911 message: "ELF executable".to_string(),
912 children: vec![child_rule],
913 level: 0,
914 strength_modifier: None,
915 };
916
917 assert_eq!(parent_rule.children.len(), 1);
918 assert_eq!(parent_rule.children[0].level, 1);
919 assert_eq!(parent_rule.children[0].message, "32-bit");
920 }
921
922 #[test]
923 fn test_magic_rule_serialization() {
924 let rule = MagicRule {
925 offset: OffsetSpec::Absolute(16),
926 typ: TypeKind::Short {
927 endian: Endianness::Little,
928 signed: false,
929 },
930 op: Operator::NotEqual,
931 value: Value::Uint(0),
932 message: "Non-zero short value".to_string(),
933 children: vec![],
934 level: 2,
935 strength_modifier: None,
936 };
937
938 let json = serde_json::to_string(&rule).expect("Failed to serialize MagicRule");
939 let deserialized: MagicRule =
940 serde_json::from_str(&json).expect("Failed to deserialize MagicRule");
941
942 assert_eq!(rule.message, deserialized.message);
943 assert_eq!(rule.level, deserialized.level);
944 assert_eq!(rule.children.len(), deserialized.children.len());
945 }
946
947 #[test]
949 fn test_strength_modifier_variants() {
950 let add = StrengthModifier::Add(10);
951 let sub = StrengthModifier::Subtract(5);
952 let mul = StrengthModifier::Multiply(2);
953 let div = StrengthModifier::Divide(2);
954 let set = StrengthModifier::Set(50);
955
956 assert_eq!(add, StrengthModifier::Add(10));
958 assert_eq!(sub, StrengthModifier::Subtract(5));
959 assert_eq!(mul, StrengthModifier::Multiply(2));
960 assert_eq!(div, StrengthModifier::Divide(2));
961 assert_eq!(set, StrengthModifier::Set(50));
962
963 assert_ne!(add, sub);
965 assert_ne!(mul, div);
966 assert_ne!(set, add);
967 }
968
969 #[test]
970 fn test_strength_modifier_negative_values() {
971 let add_negative = StrengthModifier::Add(-10);
972 let sub_negative = StrengthModifier::Subtract(-5);
973 let set_negative = StrengthModifier::Set(-50);
974
975 assert_eq!(add_negative, StrengthModifier::Add(-10));
976 assert_eq!(sub_negative, StrengthModifier::Subtract(-5));
977 assert_eq!(set_negative, StrengthModifier::Set(-50));
978 }
979
980 #[test]
981 fn test_strength_modifier_serialization() {
982 let modifiers = vec![
983 StrengthModifier::Add(10),
984 StrengthModifier::Subtract(5),
985 StrengthModifier::Multiply(2),
986 StrengthModifier::Divide(3),
987 StrengthModifier::Set(100),
988 ];
989
990 for modifier in modifiers {
991 let json =
992 serde_json::to_string(&modifier).expect("Failed to serialize StrengthModifier");
993 let deserialized: StrengthModifier =
994 serde_json::from_str(&json).expect("Failed to deserialize StrengthModifier");
995 assert_eq!(modifier, deserialized);
996 }
997 }
998
999 #[test]
1000 fn test_strength_modifier_debug() {
1001 let modifier = StrengthModifier::Add(25);
1002 let debug_str = format!("{modifier:?}");
1003 assert!(debug_str.contains("Add"));
1004 assert!(debug_str.contains("25"));
1005 }
1006
1007 #[test]
1008 fn test_strength_modifier_clone() {
1009 let original = StrengthModifier::Multiply(4);
1010 let cloned = original;
1011 assert_eq!(original, cloned);
1012 }
1013
1014 #[test]
1015 fn test_magic_rule_with_strength_modifier() {
1016 let rule = MagicRule {
1017 offset: OffsetSpec::Absolute(0),
1018 typ: TypeKind::Byte { signed: true },
1019 op: Operator::Equal,
1020 value: Value::Uint(0x7f),
1021 message: "ELF magic".to_string(),
1022 children: vec![],
1023 level: 0,
1024 strength_modifier: Some(StrengthModifier::Add(20)),
1025 };
1026
1027 assert_eq!(rule.strength_modifier, Some(StrengthModifier::Add(20)));
1028
1029 let json = serde_json::to_string(&rule).expect("Failed to serialize MagicRule");
1031 let deserialized: MagicRule =
1032 serde_json::from_str(&json).expect("Failed to deserialize MagicRule");
1033 assert_eq!(rule.strength_modifier, deserialized.strength_modifier);
1034 }
1035
1036 #[test]
1037 fn test_magic_rule_without_strength_modifier() {
1038 let rule = MagicRule {
1039 offset: OffsetSpec::Absolute(0),
1040 typ: TypeKind::Byte { signed: true },
1041 op: Operator::Equal,
1042 value: Value::Uint(0x7f),
1043 message: "ELF magic".to_string(),
1044 children: vec![],
1045 level: 0,
1046 strength_modifier: None,
1047 };
1048
1049 assert_eq!(rule.strength_modifier, None);
1050 }
1051}