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 Short {
87 endian: Endianness,
89 signed: bool,
91 },
92 Long {
94 endian: Endianness,
96 signed: bool,
98 },
99 String {
101 max_length: Option<usize>,
103 },
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
108pub enum Operator {
109 Equal,
111 NotEqual,
113 BitwiseAnd,
115 BitwiseAndMask(u64),
117}
118
119#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
121pub enum Value {
122 Uint(u64),
124 Int(i64),
126 Bytes(Vec<u8>),
128 String(String),
130}
131
132#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
134pub enum Endianness {
135 Little,
137 Big,
139 Native,
141}
142
143#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
160pub enum StrengthModifier {
161 Add(i32),
163 Subtract(i32),
165 Multiply(i32),
167 Divide(i32),
169 Set(i32),
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct MagicRule {
176 pub offset: OffsetSpec,
178 pub typ: TypeKind,
180 pub op: Operator,
182 pub value: Value,
184 pub message: String,
186 pub children: Vec<MagicRule>,
188 pub level: u32,
190 pub strength_modifier: Option<StrengthModifier>,
192}
193
194#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_offset_spec_absolute() {
208 let offset = OffsetSpec::Absolute(42);
209 assert_eq!(offset, OffsetSpec::Absolute(42));
210
211 let negative = OffsetSpec::Absolute(-10);
213 assert_eq!(negative, OffsetSpec::Absolute(-10));
214 }
215
216 #[test]
217 fn test_offset_spec_indirect() {
218 let indirect = OffsetSpec::Indirect {
219 base_offset: 0x20,
220 pointer_type: TypeKind::Long {
221 endian: Endianness::Little,
222 signed: false,
223 },
224 adjustment: 4,
225 endian: Endianness::Little,
226 };
227
228 match indirect {
229 OffsetSpec::Indirect {
230 base_offset,
231 adjustment,
232 ..
233 } => {
234 assert_eq!(base_offset, 0x20);
235 assert_eq!(adjustment, 4);
236 }
237 _ => panic!("Expected Indirect variant"),
238 }
239 }
240
241 #[test]
242 fn test_offset_spec_relative() {
243 let relative = OffsetSpec::Relative(8);
244 assert_eq!(relative, OffsetSpec::Relative(8));
245
246 let negative_relative = OffsetSpec::Relative(-4);
248 assert_eq!(negative_relative, OffsetSpec::Relative(-4));
249 }
250
251 #[test]
252 fn test_offset_spec_from_end() {
253 let from_end = OffsetSpec::FromEnd(-16);
254 assert_eq!(from_end, OffsetSpec::FromEnd(-16));
255
256 let positive_from_end = OffsetSpec::FromEnd(8);
258 assert_eq!(positive_from_end, OffsetSpec::FromEnd(8));
259 }
260
261 #[test]
262 fn test_offset_spec_debug() {
263 let offset = OffsetSpec::Absolute(100);
264 let debug_str = format!("{offset:?}");
265 assert!(debug_str.contains("Absolute"));
266 assert!(debug_str.contains("100"));
267 }
268
269 #[test]
270 fn test_offset_spec_clone() {
271 let original = OffsetSpec::Indirect {
272 base_offset: 0x10,
273 pointer_type: TypeKind::Short {
274 endian: Endianness::Big,
275 signed: true,
276 },
277 adjustment: -2,
278 endian: Endianness::Big,
279 };
280
281 let cloned = original.clone();
282 assert_eq!(original, cloned);
283 }
284
285 #[test]
286 fn test_offset_spec_serialization() {
287 let offset = OffsetSpec::Absolute(42);
288
289 let json = serde_json::to_string(&offset).expect("Failed to serialize");
291 let deserialized: OffsetSpec = serde_json::from_str(&json).expect("Failed to deserialize");
292
293 assert_eq!(offset, deserialized);
294 }
295
296 #[test]
297 fn test_offset_spec_indirect_serialization() {
298 let indirect = OffsetSpec::Indirect {
299 base_offset: 0x100,
300 pointer_type: TypeKind::Long {
301 endian: Endianness::Native,
302 signed: false,
303 },
304 adjustment: 12,
305 endian: Endianness::Native,
306 };
307
308 let json = serde_json::to_string(&indirect).expect("Failed to serialize");
310 let deserialized: OffsetSpec = serde_json::from_str(&json).expect("Failed to deserialize");
311
312 assert_eq!(indirect, deserialized);
313 }
314
315 #[test]
316 fn test_all_offset_spec_variants() {
317 let variants = [
318 OffsetSpec::Absolute(0),
319 OffsetSpec::Absolute(-100),
320 OffsetSpec::Indirect {
321 base_offset: 0x20,
322 pointer_type: TypeKind::Byte,
323 adjustment: 0,
324 endian: Endianness::Little,
325 },
326 OffsetSpec::Relative(50),
327 OffsetSpec::Relative(-25),
328 OffsetSpec::FromEnd(-8),
329 OffsetSpec::FromEnd(4),
330 ];
331
332 for (i, variant) in variants.iter().enumerate() {
334 for (j, other) in variants.iter().enumerate() {
335 if i != j {
336 assert_ne!(
337 variant, other,
338 "Variants at indices {i} and {j} should be different"
339 );
340 }
341 }
342 }
343 }
344
345 #[test]
346 fn test_endianness_variants() {
347 let endianness_values = vec![Endianness::Little, Endianness::Big, Endianness::Native];
348
349 for endian in endianness_values {
350 let indirect = OffsetSpec::Indirect {
351 base_offset: 0,
352 pointer_type: TypeKind::Long {
353 endian,
354 signed: false,
355 },
356 adjustment: 0,
357 endian,
358 };
359
360 match indirect {
362 OffsetSpec::Indirect {
363 endian: actual_endian,
364 ..
365 } => {
366 assert_eq!(endian, actual_endian);
367 }
368 _ => panic!("Expected Indirect variant"),
369 }
370 }
371 }
372
373 #[test]
375 fn test_value_uint() {
376 let value = Value::Uint(42);
377 assert_eq!(value, Value::Uint(42));
378
379 let large_value = Value::Uint(u64::MAX);
381 assert_eq!(large_value, Value::Uint(u64::MAX));
382 }
383
384 #[test]
385 fn test_value_int() {
386 let positive = Value::Int(100);
387 assert_eq!(positive, Value::Int(100));
388
389 let negative = Value::Int(-50);
390 assert_eq!(negative, Value::Int(-50));
391
392 let max_int = Value::Int(i64::MAX);
394 let min_int = Value::Int(i64::MIN);
395 assert_eq!(max_int, Value::Int(i64::MAX));
396 assert_eq!(min_int, Value::Int(i64::MIN));
397 }
398
399 #[test]
400 fn test_value_bytes() {
401 let empty_bytes = Value::Bytes(vec![]);
402 assert_eq!(empty_bytes, Value::Bytes(vec![]));
403
404 let some_bytes = Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]);
405 assert_eq!(some_bytes, Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]));
406
407 let other_bytes = Value::Bytes(vec![0x50, 0x4b, 0x03, 0x04]);
409 assert_ne!(some_bytes, other_bytes);
410 }
411
412 #[test]
413 fn test_value_string() {
414 let empty_string = Value::String(String::new());
415 assert_eq!(empty_string, Value::String(String::new()));
416
417 let hello = Value::String("Hello, World!".to_string());
418 assert_eq!(hello, Value::String("Hello, World!".to_string()));
419
420 let unicode = Value::String("🦀 Rust".to_string());
422 assert_eq!(unicode, Value::String("🦀 Rust".to_string()));
423 }
424
425 #[test]
426 fn test_value_comparison() {
427 let uint_val = Value::Uint(42);
429 let int_val = Value::Int(42);
430 let bytes_val = Value::Bytes(vec![42]);
431 let string_val = Value::String("42".to_string());
432
433 assert_ne!(uint_val, int_val);
434 assert_ne!(uint_val, bytes_val);
435 assert_ne!(uint_val, string_val);
436 assert_ne!(int_val, bytes_val);
437 assert_ne!(int_val, string_val);
438 assert_ne!(bytes_val, string_val);
439 }
440
441 #[test]
442 fn test_value_debug() {
443 let uint_val = Value::Uint(123);
444 let debug_str = format!("{uint_val:?}");
445 assert!(debug_str.contains("Uint"));
446 assert!(debug_str.contains("123"));
447
448 let string_val = Value::String("test".to_string());
449 let debug_str = format!("{string_val:?}");
450 assert!(debug_str.contains("String"));
451 assert!(debug_str.contains("test"));
452 }
453
454 #[test]
455 fn test_value_clone() {
456 let original = Value::Bytes(vec![1, 2, 3, 4]);
457 let cloned = original.clone();
458 assert_eq!(original, cloned);
459
460 match (original, cloned) {
462 (Value::Bytes(orig_bytes), Value::Bytes(cloned_bytes)) => {
463 assert_eq!(orig_bytes, cloned_bytes);
464 }
466 _ => panic!("Expected Bytes variants"),
467 }
468 }
469
470 #[test]
471 fn test_value_serialization() {
472 let values = vec![
473 Value::Uint(42),
474 Value::Int(-100),
475 Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
476 Value::String("ELF executable".to_string()),
477 ];
478
479 for value in values {
480 let json = serde_json::to_string(&value).expect("Failed to serialize Value");
482 let deserialized: Value =
483 serde_json::from_str(&json).expect("Failed to deserialize Value");
484 assert_eq!(value, deserialized);
485 }
486 }
487
488 #[test]
489 fn test_value_serialization_edge_cases() {
490 let empty_bytes = Value::Bytes(vec![]);
492 let json = serde_json::to_string(&empty_bytes).expect("Failed to serialize empty bytes");
493 let deserialized: Value =
494 serde_json::from_str(&json).expect("Failed to deserialize empty bytes");
495 assert_eq!(empty_bytes, deserialized);
496
497 let empty_string = Value::String(String::new());
498 let json = serde_json::to_string(&empty_string).expect("Failed to serialize empty string");
499 let deserialized: Value =
500 serde_json::from_str(&json).expect("Failed to deserialize empty string");
501 assert_eq!(empty_string, deserialized);
502
503 let max_uint = Value::Uint(u64::MAX);
505 let json = serde_json::to_string(&max_uint).expect("Failed to serialize max uint");
506 let deserialized: Value =
507 serde_json::from_str(&json).expect("Failed to deserialize max uint");
508 assert_eq!(max_uint, deserialized);
509
510 let min_int = Value::Int(i64::MIN);
511 let json = serde_json::to_string(&min_int).expect("Failed to serialize min int");
512 let deserialized: Value =
513 serde_json::from_str(&json).expect("Failed to deserialize min int");
514 assert_eq!(min_int, deserialized);
515 }
516
517 #[test]
519 fn test_type_kind_byte() {
520 let byte_type = TypeKind::Byte;
521 assert_eq!(byte_type, TypeKind::Byte);
522 }
523
524 #[test]
525 fn test_type_kind_short() {
526 let short_little_endian = TypeKind::Short {
527 endian: Endianness::Little,
528 signed: false,
529 };
530 let short_big_endian = TypeKind::Short {
531 endian: Endianness::Big,
532 signed: true,
533 };
534
535 assert_ne!(short_little_endian, short_big_endian);
536 assert_eq!(short_little_endian, short_little_endian.clone());
537 }
538
539 #[test]
540 fn test_type_kind_long() {
541 let long_native = TypeKind::Long {
542 endian: Endianness::Native,
543 signed: true,
544 };
545
546 match long_native {
547 TypeKind::Long { endian, signed } => {
548 assert_eq!(endian, Endianness::Native);
549 assert!(signed);
550 }
551 _ => panic!("Expected Long variant"),
552 }
553 }
554
555 #[test]
556 fn test_type_kind_string() {
557 let unlimited_string = TypeKind::String { max_length: None };
558 let limited_string = TypeKind::String {
559 max_length: Some(256),
560 };
561
562 assert_ne!(unlimited_string, limited_string);
563 assert_eq!(unlimited_string, unlimited_string.clone());
564 }
565
566 #[test]
567 fn test_type_kind_serialization() {
568 let types = vec![
569 TypeKind::Byte,
570 TypeKind::Short {
571 endian: Endianness::Little,
572 signed: false,
573 },
574 TypeKind::Long {
575 endian: Endianness::Big,
576 signed: true,
577 },
578 TypeKind::String { max_length: None },
579 TypeKind::String {
580 max_length: Some(128),
581 },
582 ];
583
584 for typ in types {
585 let json = serde_json::to_string(&typ).expect("Failed to serialize TypeKind");
586 let deserialized: TypeKind =
587 serde_json::from_str(&json).expect("Failed to deserialize TypeKind");
588 assert_eq!(typ, deserialized);
589 }
590 }
591
592 #[test]
594 fn test_operator_variants() {
595 let operators = [Operator::Equal, Operator::NotEqual, Operator::BitwiseAnd];
596
597 for (i, op) in operators.iter().enumerate() {
598 for (j, other) in operators.iter().enumerate() {
599 if i == j {
600 assert_eq!(op, other);
601 } else {
602 assert_ne!(op, other);
603 }
604 }
605 }
606 }
607
608 #[test]
609 fn test_operator_serialization() {
610 let operators = vec![Operator::Equal, Operator::NotEqual, Operator::BitwiseAnd];
611
612 for op in operators {
613 let json = serde_json::to_string(&op).expect("Failed to serialize Operator");
614 let deserialized: Operator =
615 serde_json::from_str(&json).expect("Failed to deserialize Operator");
616 assert_eq!(op, deserialized);
617 }
618 }
619
620 #[test]
622 fn test_magic_rule_creation() {
623 let rule = MagicRule {
624 offset: OffsetSpec::Absolute(0),
625 typ: TypeKind::Byte,
626 op: Operator::Equal,
627 value: Value::Uint(0x7f),
628 message: "ELF magic".to_string(),
629 children: vec![],
630 level: 0,
631 strength_modifier: None,
632 };
633
634 assert_eq!(rule.message, "ELF magic");
635 assert_eq!(rule.level, 0);
636 assert!(rule.children.is_empty());
637 }
638
639 #[test]
640 fn test_magic_rule_with_children() {
641 let child_rule = MagicRule {
642 offset: OffsetSpec::Absolute(4),
643 typ: TypeKind::Byte,
644 op: Operator::Equal,
645 value: Value::Uint(1),
646 message: "32-bit".to_string(),
647 children: vec![],
648 level: 1,
649 strength_modifier: None,
650 };
651
652 let parent_rule = MagicRule {
653 offset: OffsetSpec::Absolute(0),
654 typ: TypeKind::Long {
655 endian: Endianness::Little,
656 signed: false,
657 },
658 op: Operator::Equal,
659 value: Value::Bytes(vec![0x7f, 0x45, 0x4c, 0x46]),
660 message: "ELF executable".to_string(),
661 children: vec![child_rule],
662 level: 0,
663 strength_modifier: None,
664 };
665
666 assert_eq!(parent_rule.children.len(), 1);
667 assert_eq!(parent_rule.children[0].level, 1);
668 assert_eq!(parent_rule.children[0].message, "32-bit");
669 }
670
671 #[test]
672 fn test_magic_rule_serialization() {
673 let rule = MagicRule {
674 offset: OffsetSpec::Absolute(16),
675 typ: TypeKind::Short {
676 endian: Endianness::Little,
677 signed: false,
678 },
679 op: Operator::NotEqual,
680 value: Value::Uint(0),
681 message: "Non-zero short value".to_string(),
682 children: vec![],
683 level: 2,
684 strength_modifier: None,
685 };
686
687 let json = serde_json::to_string(&rule).expect("Failed to serialize MagicRule");
688 let deserialized: MagicRule =
689 serde_json::from_str(&json).expect("Failed to deserialize MagicRule");
690
691 assert_eq!(rule.message, deserialized.message);
692 assert_eq!(rule.level, deserialized.level);
693 assert_eq!(rule.children.len(), deserialized.children.len());
694 }
695
696 #[test]
698 fn test_strength_modifier_variants() {
699 let add = StrengthModifier::Add(10);
700 let sub = StrengthModifier::Subtract(5);
701 let mul = StrengthModifier::Multiply(2);
702 let div = StrengthModifier::Divide(2);
703 let set = StrengthModifier::Set(50);
704
705 assert_eq!(add, StrengthModifier::Add(10));
707 assert_eq!(sub, StrengthModifier::Subtract(5));
708 assert_eq!(mul, StrengthModifier::Multiply(2));
709 assert_eq!(div, StrengthModifier::Divide(2));
710 assert_eq!(set, StrengthModifier::Set(50));
711
712 assert_ne!(add, sub);
714 assert_ne!(mul, div);
715 assert_ne!(set, add);
716 }
717
718 #[test]
719 fn test_strength_modifier_negative_values() {
720 let add_negative = StrengthModifier::Add(-10);
721 let sub_negative = StrengthModifier::Subtract(-5);
722 let set_negative = StrengthModifier::Set(-50);
723
724 assert_eq!(add_negative, StrengthModifier::Add(-10));
725 assert_eq!(sub_negative, StrengthModifier::Subtract(-5));
726 assert_eq!(set_negative, StrengthModifier::Set(-50));
727 }
728
729 #[test]
730 fn test_strength_modifier_serialization() {
731 let modifiers = vec![
732 StrengthModifier::Add(10),
733 StrengthModifier::Subtract(5),
734 StrengthModifier::Multiply(2),
735 StrengthModifier::Divide(3),
736 StrengthModifier::Set(100),
737 ];
738
739 for modifier in modifiers {
740 let json =
741 serde_json::to_string(&modifier).expect("Failed to serialize StrengthModifier");
742 let deserialized: StrengthModifier =
743 serde_json::from_str(&json).expect("Failed to deserialize StrengthModifier");
744 assert_eq!(modifier, deserialized);
745 }
746 }
747
748 #[test]
749 fn test_strength_modifier_debug() {
750 let modifier = StrengthModifier::Add(25);
751 let debug_str = format!("{modifier:?}");
752 assert!(debug_str.contains("Add"));
753 assert!(debug_str.contains("25"));
754 }
755
756 #[test]
757 fn test_strength_modifier_clone() {
758 let original = StrengthModifier::Multiply(4);
759 let cloned = original;
760 assert_eq!(original, cloned);
761 }
762
763 #[test]
764 fn test_magic_rule_with_strength_modifier() {
765 let rule = MagicRule {
766 offset: OffsetSpec::Absolute(0),
767 typ: TypeKind::Byte,
768 op: Operator::Equal,
769 value: Value::Uint(0x7f),
770 message: "ELF magic".to_string(),
771 children: vec![],
772 level: 0,
773 strength_modifier: Some(StrengthModifier::Add(20)),
774 };
775
776 assert_eq!(rule.strength_modifier, Some(StrengthModifier::Add(20)));
777
778 let json = serde_json::to_string(&rule).expect("Failed to serialize MagicRule");
780 let deserialized: MagicRule =
781 serde_json::from_str(&json).expect("Failed to deserialize MagicRule");
782 assert_eq!(rule.strength_modifier, deserialized.strength_modifier);
783 }
784
785 #[test]
786 fn test_magic_rule_without_strength_modifier() {
787 let rule = MagicRule {
788 offset: OffsetSpec::Absolute(0),
789 typ: TypeKind::Byte,
790 op: Operator::Equal,
791 value: Value::Uint(0x7f),
792 message: "ELF magic".to_string(),
793 children: vec![],
794 level: 0,
795 strength_modifier: None,
796 };
797
798 assert_eq!(rule.strength_modifier, None);
799 }
800}