1use crate::parser::ast::{Endianness, TypeKind, Value};
10use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
11use thiserror::Error;
12
13#[derive(Debug, Error, PartialEq, Eq)]
15pub enum TypeReadError {
16 #[error(
18 "Buffer overrun: attempted to read at offset {offset} but buffer length is {buffer_len}"
19 )]
20 BufferOverrun {
21 offset: usize,
23 buffer_len: usize,
25 },
26 #[error("Unsupported type: {type_name}")]
28 UnsupportedType {
29 type_name: String,
31 },
32}
33
34pub fn read_byte(buffer: &[u8], offset: usize, signed: bool) -> Result<Value, TypeReadError> {
80 buffer
81 .get(offset)
82 .map(|&byte| {
83 if signed {
84 #[allow(clippy::cast_possible_wrap)]
86 Value::Int(i64::from(byte as i8))
87 } else {
88 Value::Uint(u64::from(byte))
89 }
90 })
91 .ok_or(TypeReadError::BufferOverrun {
92 offset,
93 buffer_len: buffer.len(),
94 })
95}
96
97pub fn read_short(
133 buffer: &[u8],
134 offset: usize,
135 endian: Endianness,
136 signed: bool,
137) -> Result<Value, TypeReadError> {
138 let bytes = buffer
139 .get(offset..offset + 2)
140 .ok_or(TypeReadError::BufferOverrun {
141 offset,
142 buffer_len: buffer.len(),
143 })?;
144
145 let value = match endian {
146 Endianness::Little => LittleEndian::read_u16(bytes),
147 Endianness::Big => BigEndian::read_u16(bytes),
148 Endianness::Native => NativeEndian::read_u16(bytes),
149 };
150
151 if signed {
152 #[allow(clippy::cast_possible_wrap)]
153 Ok(Value::Int(i64::from(value as i16)))
154 } else {
155 Ok(Value::Uint(u64::from(value)))
156 }
157}
158
159pub fn read_long(
195 buffer: &[u8],
196 offset: usize,
197 endian: Endianness,
198 signed: bool,
199) -> Result<Value, TypeReadError> {
200 let bytes = buffer
201 .get(offset..offset + 4)
202 .ok_or(TypeReadError::BufferOverrun {
203 offset,
204 buffer_len: buffer.len(),
205 })?;
206
207 let value = match endian {
208 Endianness::Little => LittleEndian::read_u32(bytes),
209 Endianness::Big => BigEndian::read_u32(bytes),
210 Endianness::Native => NativeEndian::read_u32(bytes),
211 };
212
213 if signed {
214 #[allow(clippy::cast_possible_wrap)]
215 Ok(Value::Int(i64::from(value as i32)))
216 } else {
217 Ok(Value::Uint(u64::from(value)))
218 }
219}
220
221pub fn read_string(
285 buffer: &[u8],
286 offset: usize,
287 max_length: Option<usize>,
288) -> Result<Value, TypeReadError> {
289 if offset >= buffer.len() {
291 return Err(TypeReadError::BufferOverrun {
292 offset,
293 buffer_len: buffer.len(),
294 });
295 }
296
297 let remaining_buffer = &buffer[offset..];
299
300 let read_length = if let Some(max_len) = max_length {
302 let search_len = std::cmp::min(max_len, remaining_buffer.len());
304 memchr::memchr(0, &remaining_buffer[..search_len]).unwrap_or(search_len)
305 } else {
306 memchr::memchr(0, remaining_buffer).unwrap_or(remaining_buffer.len())
308 };
309
310 let string_bytes = &remaining_buffer[..read_length];
312
313 let string_value = String::from_utf8_lossy(string_bytes).into_owned();
315
316 Ok(Value::String(string_value))
317}
318
319pub fn read_typed_value(
360 buffer: &[u8],
361 offset: usize,
362 type_kind: &TypeKind,
363) -> Result<Value, TypeReadError> {
364 match type_kind {
365 TypeKind::Byte { signed } => read_byte(buffer, offset, *signed),
366 TypeKind::Short { endian, signed } => read_short(buffer, offset, *endian, *signed),
367 TypeKind::Long { endian, signed } => read_long(buffer, offset, *endian, *signed),
368 TypeKind::String { max_length } => read_string(buffer, offset, *max_length),
369 }
370}
371
372#[must_use]
401pub fn coerce_value_to_type(value: &Value, type_kind: &TypeKind) -> Value {
402 match (value, type_kind) {
403 (Value::Uint(v), TypeKind::Byte { signed: true }) if *v > i8::MAX as u64 =>
404 {
405 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
406 Value::Int(i64::from(*v as u8 as i8))
407 }
408 (Value::Uint(v), TypeKind::Short { signed: true, .. }) if *v > i16::MAX as u64 =>
409 {
410 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
411 Value::Int(i64::from(*v as u16 as i16))
412 }
413 (Value::Uint(v), TypeKind::Long { signed: true, .. }) if *v > i32::MAX as u64 =>
414 {
415 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
416 Value::Int(i64::from(*v as u32 as i32))
417 }
418 _ => value.clone(),
419 }
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425
426 #[test]
427 fn test_read_byte_values() {
428 let buffer: Vec<u8> = (0..=255).collect();
430 for (i, &byte) in buffer.iter().enumerate() {
431 assert_eq!(
432 read_byte(&buffer, i, false).unwrap(),
433 Value::Uint(u64::from(byte))
434 );
435 }
436 }
437
438 #[test]
439 fn test_read_byte_out_of_bounds() {
440 assert_eq!(
442 read_byte(&[], 0, false).unwrap_err(),
443 TypeReadError::BufferOverrun {
444 offset: 0,
445 buffer_len: 0
446 }
447 );
448 assert_eq!(
450 read_byte(&[0x42], 1, false).unwrap_err(),
451 TypeReadError::BufferOverrun {
452 offset: 1,
453 buffer_len: 1
454 }
455 );
456 assert_eq!(
458 read_byte(&[1, 2, 3], 100, false).unwrap_err(),
459 TypeReadError::BufferOverrun {
460 offset: 100,
461 buffer_len: 3
462 }
463 );
464 }
465
466 #[test]
467 fn test_read_byte_signedness() {
468 let cases: Vec<(u8, bool, Value)> = vec![
469 (0x00, false, Value::Uint(0)),
470 (0x7f, false, Value::Uint(127)),
471 (0x80, false, Value::Uint(128)),
472 (0xff, false, Value::Uint(255)),
473 (0x00, true, Value::Int(0)),
474 (0x7f, true, Value::Int(127)),
475 (0x80, true, Value::Int(-128)),
476 (0xff, true, Value::Int(-1)),
477 ];
478 for (byte, signed, expected) in cases {
479 let result = read_byte(&[byte], 0, signed).unwrap();
480 assert_eq!(result, expected, "byte=0x{byte:02x}, signed={signed}");
481 }
482 }
483
484 #[test]
485 fn test_type_read_error_display() {
486 let error = TypeReadError::BufferOverrun {
487 offset: 10,
488 buffer_len: 5,
489 };
490 let msg = format!("{error}");
491 assert!(msg.contains("offset 10"));
492 assert!(msg.contains("buffer length is 5"));
493 }
494
495 #[test]
497 fn test_read_short_little_endian_unsigned() {
498 let buffer = &[0x34, 0x12, 0x78, 0x56]; let result = read_short(buffer, 0, Endianness::Little, false).unwrap();
502 assert_eq!(result, Value::Uint(0x1234));
503
504 let result = read_short(buffer, 2, Endianness::Little, false).unwrap();
506 assert_eq!(result, Value::Uint(0x5678));
507 }
508
509 #[test]
510 fn test_read_short_big_endian_unsigned() {
511 let buffer = &[0x12, 0x34, 0x56, 0x78]; let result = read_short(buffer, 0, Endianness::Big, false).unwrap();
515 assert_eq!(result, Value::Uint(0x1234));
516
517 let result = read_short(buffer, 2, Endianness::Big, false).unwrap();
519 assert_eq!(result, Value::Uint(0x5678));
520 }
521
522 #[test]
523 fn test_read_short_native_endian_unsigned() {
524 let buffer = &[0x34, 0x12, 0x78, 0x56];
525
526 let result = read_short(buffer, 0, Endianness::Native, false).unwrap();
528
529 match result {
531 Value::Uint(val) => {
532 assert!(val == 0x1234 || val == 0x3412);
534 }
535 _ => panic!("Expected Value::Uint variant"),
536 }
537 }
538
539 #[test]
540 fn test_read_short_signed_positive() {
541 let buffer = &[0xff, 0x7f]; let result = read_short(buffer, 0, Endianness::Little, true).unwrap();
544 assert_eq!(result, Value::Int(32767));
545 }
546
547 #[test]
548 fn test_read_short_signed_negative() {
549 let buffer = &[0x00, 0x80]; let result = read_short(buffer, 0, Endianness::Little, true).unwrap();
552 assert_eq!(result, Value::Int(-32768));
553 }
554
555 #[test]
556 fn test_read_short_signed_vs_unsigned() {
557 let buffer = &[0xff, 0xff]; let unsigned_result = read_short(buffer, 0, Endianness::Little, false).unwrap();
561 assert_eq!(unsigned_result, Value::Uint(65535));
562
563 let signed_result = read_short(buffer, 0, Endianness::Little, true).unwrap();
565 assert_eq!(signed_result, Value::Int(-1));
566 }
567
568 #[test]
569 fn test_read_short_buffer_overrun() {
570 let buffer = &[0x12]; let result = read_short(buffer, 0, Endianness::Little, false);
574 assert!(result.is_err());
575 assert_eq!(
576 result.unwrap_err(),
577 TypeReadError::BufferOverrun {
578 offset: 0,
579 buffer_len: 1
580 }
581 );
582 }
583
584 #[test]
585 fn test_read_short_offset_out_of_bounds() {
586 let buffer = &[0x12, 0x34, 0x56];
587
588 let result = read_short(buffer, 2, Endianness::Little, false);
590 assert!(result.is_err());
591 assert_eq!(
592 result.unwrap_err(),
593 TypeReadError::BufferOverrun {
594 offset: 2,
595 buffer_len: 3
596 }
597 );
598 }
599
600 #[test]
601 fn test_read_short_empty_buffer() {
602 let buffer = &[];
603
604 let result = read_short(buffer, 0, Endianness::Little, false);
605 assert!(result.is_err());
606 assert_eq!(
607 result.unwrap_err(),
608 TypeReadError::BufferOverrun {
609 offset: 0,
610 buffer_len: 0
611 }
612 );
613 }
614
615 #[test]
616 fn test_read_short_all_endianness_variants() {
617 let buffer = &[0x12, 0x34];
618
619 let little = read_short(buffer, 0, Endianness::Little, false).unwrap();
621 let big = read_short(buffer, 0, Endianness::Big, false).unwrap();
622 let native = read_short(buffer, 0, Endianness::Native, false).unwrap();
623
624 assert_eq!(little, Value::Uint(0x3412));
626 assert_eq!(big, Value::Uint(0x1234));
627
628 match native {
630 Value::Uint(val) => assert!(val == 0x1234 || val == 0x3412),
631 _ => panic!("Expected Value::Uint variant"),
632 }
633 }
634
635 #[test]
637 fn test_read_long_little_endian_unsigned() {
638 let buffer = &[0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a, 0x78, 0x56]; let result = read_long(buffer, 0, Endianness::Little, false).unwrap();
642 assert_eq!(result, Value::Uint(0x1234_5678));
643
644 let result = read_long(buffer, 4, Endianness::Little, false).unwrap();
646 assert_eq!(result, Value::Uint(0x5678_9abc));
647 }
648
649 #[test]
650 fn test_read_long_big_endian_unsigned() {
651 let buffer = &[0x12, 0x34, 0x56, 0x78, 0x56, 0x78, 0x9a, 0xbc]; let result = read_long(buffer, 0, Endianness::Big, false).unwrap();
655 assert_eq!(result, Value::Uint(0x1234_5678));
656
657 let result = read_long(buffer, 4, Endianness::Big, false).unwrap();
659 assert_eq!(result, Value::Uint(0x5678_9abc));
660 }
661
662 #[test]
663 fn test_read_long_native_endian_unsigned() {
664 let buffer = &[0x78, 0x56, 0x34, 0x12];
665
666 let result = read_long(buffer, 0, Endianness::Native, false).unwrap();
668
669 match result {
671 Value::Uint(val) => {
672 assert!(val == 0x1234_5678 || val == 0x7856_3412);
674 }
675 _ => panic!("Expected Value::Uint variant"),
676 }
677 }
678
679 #[test]
680 fn test_read_long_signed_positive() {
681 let buffer = &[0xff, 0xff, 0xff, 0x7f]; let result = read_long(buffer, 0, Endianness::Little, true).unwrap();
684 assert_eq!(result, Value::Int(2_147_483_647));
685 }
686
687 #[test]
688 fn test_read_long_signed_negative() {
689 let buffer = &[0x00, 0x00, 0x00, 0x80]; let result = read_long(buffer, 0, Endianness::Little, true).unwrap();
692 assert_eq!(result, Value::Int(-2_147_483_648));
693 }
694
695 #[test]
696 fn test_read_long_signed_vs_unsigned() {
697 let buffer = &[0xff, 0xff, 0xff, 0xff]; let unsigned_result = read_long(buffer, 0, Endianness::Little, false).unwrap();
701 assert_eq!(unsigned_result, Value::Uint(4_294_967_295));
702
703 let signed_result = read_long(buffer, 0, Endianness::Little, true).unwrap();
705 assert_eq!(signed_result, Value::Int(-1));
706 }
707
708 #[test]
709 fn test_read_long_buffer_overrun() {
710 let buffer = &[0x12, 0x34, 0x56]; let result = read_long(buffer, 0, Endianness::Little, false);
714 assert!(result.is_err());
715 assert_eq!(
716 result.unwrap_err(),
717 TypeReadError::BufferOverrun {
718 offset: 0,
719 buffer_len: 3
720 }
721 );
722 }
723
724 #[test]
725 fn test_read_long_offset_out_of_bounds() {
726 let buffer = &[0x12, 0x34, 0x56, 0x78, 0x9a];
727
728 let result = read_long(buffer, 2, Endianness::Little, false);
730 assert!(result.is_err());
731 assert_eq!(
732 result.unwrap_err(),
733 TypeReadError::BufferOverrun {
734 offset: 2,
735 buffer_len: 5
736 }
737 );
738 }
739
740 #[test]
741 fn test_read_long_empty_buffer() {
742 let buffer = &[];
743
744 let result = read_long(buffer, 0, Endianness::Little, false);
745 assert!(result.is_err());
746 assert_eq!(
747 result.unwrap_err(),
748 TypeReadError::BufferOverrun {
749 offset: 0,
750 buffer_len: 0
751 }
752 );
753 }
754
755 #[test]
756 fn test_read_long_all_endianness_variants() {
757 let buffer = &[0x12, 0x34, 0x56, 0x78];
758
759 let little = read_long(buffer, 0, Endianness::Little, false).unwrap();
761 let big = read_long(buffer, 0, Endianness::Big, false).unwrap();
762 let native = read_long(buffer, 0, Endianness::Native, false).unwrap();
763
764 assert_eq!(little, Value::Uint(0x7856_3412));
766 assert_eq!(big, Value::Uint(0x1234_5678));
767
768 match native {
770 Value::Uint(val) => assert!(val == 0x1234_5678 || val == 0x7856_3412),
771 _ => panic!("Expected Value::Uint variant"),
772 }
773 }
774
775 #[test]
776 fn test_read_long_extreme_values() {
777 let max_buffer = &[0xff, 0xff, 0xff, 0xff];
779 let max_result = read_long(max_buffer, 0, Endianness::Little, false).unwrap();
780 assert_eq!(max_result, Value::Uint(u64::from(u32::MAX)));
781
782 let zero_buffer = &[0x00, 0x00, 0x00, 0x00];
784 let zero_result = read_long(zero_buffer, 0, Endianness::Little, false).unwrap();
785 assert_eq!(zero_result, Value::Uint(0));
786 }
787
788 #[test]
789 fn test_read_short_extreme_values() {
790 let max_buffer = &[0xff, 0xff];
792 let max_result = read_short(max_buffer, 0, Endianness::Little, false).unwrap();
793 assert_eq!(max_result, Value::Uint(u64::from(u16::MAX)));
794
795 let zero_buffer = &[0x00, 0x00];
797 let zero_result = read_short(zero_buffer, 0, Endianness::Little, false).unwrap();
798 assert_eq!(zero_result, Value::Uint(0));
799 }
800
801 #[test]
802 fn test_multi_byte_reading_consistency() {
803 let buffer = &[0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xde, 0xf0];
805
806 let byte0 = read_byte(buffer, 0, false).unwrap();
808 let byte1 = read_byte(buffer, 1, false).unwrap();
809
810 let short = read_short(buffer, 0, Endianness::Little, false).unwrap();
812
813 match (byte0, byte1, short) {
815 (Value::Uint(b0), Value::Uint(b1), Value::Uint(s)) => {
816 assert_eq!(s, b0 + (b1 << 8)); }
818 _ => panic!("Expected all Uint values"),
819 }
820 }
821
822 #[test]
824 fn test_unsupported_type_error() {
825 let error = TypeReadError::UnsupportedType {
826 type_name: "CustomType".to_string(),
827 };
828
829 let error_string = format!("{error}");
830 assert!(error_string.contains("Unsupported type"));
831 assert!(error_string.contains("CustomType"));
832 }
833
834 #[test]
835 fn test_unsupported_type_error_debug() {
836 let error = TypeReadError::UnsupportedType {
837 type_name: "TestType".to_string(),
838 };
839
840 let debug_string = format!("{error:?}");
841 assert!(debug_string.contains("UnsupportedType"));
842 assert!(debug_string.contains("TestType"));
843 }
844
845 #[test]
846 fn test_unsupported_type_error_equality() {
847 let error1 = TypeReadError::UnsupportedType {
848 type_name: "Type1".to_string(),
849 };
850 let error2 = TypeReadError::UnsupportedType {
851 type_name: "Type1".to_string(),
852 };
853 let error3 = TypeReadError::UnsupportedType {
854 type_name: "Type2".to_string(),
855 };
856
857 assert_eq!(error1, error2);
858 assert_ne!(error1, error3);
859 }
860
861 #[test]
863 fn test_read_typed_value_byte() {
864 let buffer = &[0x7f, 0x45, 0x4c, 0x46];
865 let type_kind = TypeKind::Byte { signed: false };
866
867 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
868 assert_eq!(result, Value::Uint(0x7f));
869
870 let result = read_typed_value(buffer, 3, &type_kind).unwrap();
871 assert_eq!(result, Value::Uint(0x46));
872 }
873
874 #[test]
875 fn test_read_typed_value_short_unsigned_little_endian() {
876 let buffer = &[0x34, 0x12, 0x78, 0x56];
877 let type_kind = TypeKind::Short {
878 endian: Endianness::Little,
879 signed: false,
880 };
881
882 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
883 assert_eq!(result, Value::Uint(0x1234));
884
885 let result = read_typed_value(buffer, 2, &type_kind).unwrap();
886 assert_eq!(result, Value::Uint(0x5678));
887 }
888
889 #[test]
890 fn test_read_typed_value_short_signed_big_endian() {
891 let buffer = &[0x80, 0x00, 0x7f, 0xff];
892 let type_kind = TypeKind::Short {
893 endian: Endianness::Big,
894 signed: true,
895 };
896
897 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
899 assert_eq!(result, Value::Int(-32768));
900
901 let result = read_typed_value(buffer, 2, &type_kind).unwrap();
903 assert_eq!(result, Value::Int(32767));
904 }
905
906 #[test]
907 fn test_read_typed_value_long_unsigned_little_endian() {
908 let buffer = &[0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a, 0x78, 0x56];
909 let type_kind = TypeKind::Long {
910 endian: Endianness::Little,
911 signed: false,
912 };
913
914 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
915 assert_eq!(result, Value::Uint(0x1234_5678));
916
917 let result = read_typed_value(buffer, 4, &type_kind).unwrap();
918 assert_eq!(result, Value::Uint(0x5678_9abc));
919 }
920
921 #[test]
922 fn test_read_typed_value_long_signed_big_endian() {
923 let buffer = &[0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff];
924 let type_kind = TypeKind::Long {
925 endian: Endianness::Big,
926 signed: true,
927 };
928
929 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
931 assert_eq!(result, Value::Int(-2_147_483_648));
932
933 let result = read_typed_value(buffer, 4, &type_kind).unwrap();
935 assert_eq!(result, Value::Int(2_147_483_647));
936 }
937
938 #[test]
939 fn test_read_typed_value_native_endian() {
940 let buffer = &[0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xde, 0xf0];
941
942 let short_type = TypeKind::Short {
944 endian: Endianness::Native,
945 signed: false,
946 };
947
948 let result = read_typed_value(buffer, 0, &short_type).unwrap();
949 match result {
950 Value::Uint(val) => {
951 assert!(val == 0x1234 || val == 0x3412);
953 }
954 _ => panic!("Expected Value::Uint variant"),
955 }
956 }
957
958 #[test]
959 fn test_read_typed_value_string() {
960 let buffer = b"Hello\x00World\x00";
961 let type_kind = TypeKind::String { max_length: None };
962
963 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
964 assert_eq!(result, Value::String("Hello".to_string()));
965
966 let result = read_typed_value(buffer, 6, &type_kind).unwrap();
967 assert_eq!(result, Value::String("World".to_string()));
968 }
969
970 #[test]
971 fn test_read_typed_value_string_with_max_length() {
972 let buffer = b"VeryLongString\x00";
973 let type_kind = TypeKind::String {
974 max_length: Some(4),
975 };
976
977 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
978 assert_eq!(result, Value::String("Very".to_string()));
979 }
980
981 #[test]
982 fn test_read_typed_value_buffer_overrun() {
983 let buffer = &[0x12];
984 let type_kind = TypeKind::Short {
985 endian: Endianness::Little,
986 signed: false,
987 };
988
989 let result = read_typed_value(buffer, 0, &type_kind);
990 assert!(result.is_err());
991 assert_eq!(
992 result.unwrap_err(),
993 TypeReadError::BufferOverrun {
994 offset: 0,
995 buffer_len: 1
996 }
997 );
998 }
999
1000 #[test]
1002 fn test_read_string_null_terminated() {
1003 let buffer = b"Hello\x00World";
1004
1005 let result = read_string(buffer, 0, None).unwrap();
1006 assert_eq!(result, Value::String("Hello".to_string()));
1007 }
1008
1009 #[test]
1010 fn test_read_string_null_terminated_at_offset() {
1011 let buffer = b"Prefix\x00Hello\x00Suffix";
1012
1013 let result = read_string(buffer, 7, None).unwrap();
1014 assert_eq!(result, Value::String("Hello".to_string()));
1015 }
1016
1017 #[test]
1018 fn test_read_string_with_max_length_shorter_than_null() {
1019 let buffer = b"VeryLongString\x00";
1020
1021 let result = read_string(buffer, 0, Some(4)).unwrap();
1023 assert_eq!(result, Value::String("Very".to_string()));
1024 }
1025
1026 #[test]
1027 fn test_read_string_with_max_length_longer_than_null() {
1028 let buffer = b"Short\x00LongerSuffix";
1029
1030 let result = read_string(buffer, 0, Some(10)).unwrap();
1032 assert_eq!(result, Value::String("Short".to_string()));
1033 }
1034
1035 #[test]
1036 fn test_read_string_no_null_terminator_with_max_length() {
1037 let buffer = b"NoNullTerminator";
1038
1039 let result = read_string(buffer, 0, Some(6)).unwrap();
1041 assert_eq!(result, Value::String("NoNull".to_string()));
1042 }
1043
1044 #[test]
1045 fn test_read_string_no_null_terminator_no_max_length() {
1046 let buffer = b"NoNullTerminator";
1047
1048 let result = read_string(buffer, 0, None).unwrap();
1050 assert_eq!(result, Value::String("NoNullTerminator".to_string()));
1051 }
1052
1053 #[test]
1054 fn test_read_string_empty_string() {
1055 let buffer = b"\x00Hello";
1056
1057 let result = read_string(buffer, 0, None).unwrap();
1059 assert_eq!(result, Value::String(String::new()));
1060 }
1061
1062 #[test]
1063 fn test_read_string_empty_buffer() {
1064 let buffer = b"";
1065
1066 let result = read_string(buffer, 0, None);
1068 assert!(result.is_err());
1069 assert_eq!(
1070 result.unwrap_err(),
1071 TypeReadError::BufferOverrun {
1072 offset: 0,
1073 buffer_len: 0
1074 }
1075 );
1076 }
1077
1078 #[test]
1079 fn test_read_string_offset_out_of_bounds() {
1080 let buffer = b"Hello";
1081
1082 let result = read_string(buffer, 10, None);
1084 assert!(result.is_err());
1085 assert_eq!(
1086 result.unwrap_err(),
1087 TypeReadError::BufferOverrun {
1088 offset: 10,
1089 buffer_len: 5
1090 }
1091 );
1092 }
1093
1094 #[test]
1095 fn test_read_string_offset_at_buffer_end() {
1096 let buffer = b"Hello";
1097
1098 let result = read_string(buffer, 5, None);
1100 assert!(result.is_err());
1101 assert_eq!(
1102 result.unwrap_err(),
1103 TypeReadError::BufferOverrun {
1104 offset: 5,
1105 buffer_len: 5
1106 }
1107 );
1108 }
1109
1110 #[test]
1111 fn test_read_string_max_length_zero() {
1112 let buffer = b"Hello\x00World";
1113
1114 let result = read_string(buffer, 0, Some(0)).unwrap();
1116 assert_eq!(result, Value::String(String::new()));
1117 }
1118
1119 #[test]
1120 fn test_read_string_max_length_larger_than_buffer() {
1121 let buffer = b"Short";
1122
1123 let result = read_string(buffer, 0, Some(100)).unwrap();
1125 assert_eq!(result, Value::String("Short".to_string()));
1126 }
1127
1128 #[test]
1129 fn test_read_string_utf8_valid() {
1130 let buffer = b"Caf\xc3\xa9\x00"; let result = read_string(buffer, 0, None).unwrap();
1133 assert_eq!(result, Value::String("Café".to_string()));
1134 }
1135
1136 #[test]
1137 fn test_read_string_utf8_invalid() {
1138 let buffer = b"Invalid\xff\xfe\x00"; let result = read_string(buffer, 0, None).unwrap();
1141 assert!(matches!(result, Value::String(_)));
1143 if let Value::String(s) = result {
1144 assert!(s.starts_with("Invalid"));
1145 assert!(s.contains('\u{FFFD}')); }
1147 }
1148
1149 #[test]
1150 fn test_read_string_binary_data() {
1151 let buffer = &[0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x80, 0x90]; let result = read_string(buffer, 0, None).unwrap();
1154 assert_eq!(result, Value::String("Hello".to_string()));
1155 }
1156
1157 #[test]
1158 fn test_read_string_multiple_nulls() {
1159 let buffer = b"First\x00\x00Second\x00";
1160
1161 let result = read_string(buffer, 0, None).unwrap();
1163 assert_eq!(result, Value::String("First".to_string()));
1164
1165 let result = read_string(buffer, 6, None).unwrap();
1167 assert_eq!(result, Value::String(String::new()));
1168 }
1169
1170 #[test]
1171 fn test_read_string_ascii_control_characters() {
1172 let buffer = b"Hello\x09World\x00"; let result = read_string(buffer, 0, None).unwrap();
1175 assert_eq!(result, Value::String("Hello\tWorld".to_string()));
1176 }
1177
1178 #[test]
1179 fn test_read_string_single_character() {
1180 let buffer = b"A\x00";
1181
1182 let result = read_string(buffer, 0, None).unwrap();
1183 assert_eq!(result, Value::String("A".to_string()));
1184 }
1185
1186 #[test]
1187 fn test_read_string_max_length_exact_match() {
1188 let buffer = b"Exact\x00";
1189
1190 let result = read_string(buffer, 0, Some(5)).unwrap();
1192 assert_eq!(result, Value::String("Exact".to_string()));
1193 }
1194
1195 #[test]
1196 fn test_read_string_at_buffer_boundary() {
1197 let buffer = b"Hello";
1198
1199 let result = read_string(buffer, 4, Some(1)).unwrap();
1201 assert_eq!(result, Value::String("o".to_string()));
1202 }
1203
1204 #[test]
1205 fn test_read_string_whitespace_handling() {
1206 let buffer = b" Spaces \x00";
1207
1208 let result = read_string(buffer, 0, None).unwrap();
1210 assert_eq!(result, Value::String(" Spaces ".to_string()));
1211 }
1212
1213 #[test]
1214 fn test_read_string_newline_characters() {
1215 let buffer = b"Line1\nLine2\r\n\x00";
1216
1217 let result = read_string(buffer, 0, None).unwrap();
1218 assert_eq!(result, Value::String("Line1\nLine2\r\n".to_string()));
1219 }
1220
1221 #[test]
1222 fn test_read_string_consistency_with_typed_value() {
1223 let buffer = b"Test\x00String";
1224
1225 let direct_result = read_string(buffer, 0, None).unwrap();
1227
1228 let type_kind = TypeKind::String { max_length: None };
1229 let typed_result = read_typed_value(buffer, 0, &type_kind).unwrap();
1230
1231 assert_eq!(direct_result, typed_result);
1232 assert_eq!(typed_result, Value::String("Test".to_string()));
1233 }
1234
1235 #[test]
1236 fn test_read_string_consistency_with_max_length() {
1237 let buffer = b"LongString\x00";
1238
1239 let direct_result = read_string(buffer, 0, Some(4)).unwrap();
1241
1242 let type_kind = TypeKind::String {
1243 max_length: Some(4),
1244 };
1245 let typed_result = read_typed_value(buffer, 0, &type_kind).unwrap();
1246
1247 assert_eq!(direct_result, typed_result);
1248 assert_eq!(typed_result, Value::String("Long".to_string()));
1249 }
1250
1251 #[test]
1252 fn test_read_string_edge_case_combinations() {
1253 let test_cases = [
1255 (b"" as &[u8], 0, None, true), (b"\x00", 0, None, false), (b"A", 0, Some(0), false), (b"AB", 1, Some(1), false), ];
1260
1261 for (buffer, offset, max_length, should_fail) in test_cases {
1262 let result = read_string(buffer, offset, max_length);
1263
1264 if should_fail {
1265 assert!(
1266 result.is_err(),
1267 "Expected failure for buffer {buffer:?}, offset {offset}, max_length {max_length:?}"
1268 );
1269 } else {
1270 assert!(
1271 result.is_ok(),
1272 "Expected success for buffer {buffer:?}, offset {offset}, max_length {max_length:?}"
1273 );
1274 }
1275 }
1276 }
1277}
1278
1279#[test]
1280fn test_read_typed_value_buffer_overrun() {
1281 let buffer = &[0x12, 0x34];
1282
1283 let long_type = TypeKind::Long {
1285 endian: Endianness::Little,
1286 signed: false,
1287 };
1288 let result = read_typed_value(buffer, 0, &long_type);
1289 assert!(result.is_err());
1290 assert_eq!(
1291 result.unwrap_err(),
1292 TypeReadError::BufferOverrun {
1293 offset: 0,
1294 buffer_len: 2
1295 }
1296 );
1297
1298 let short_type = TypeKind::Short {
1300 endian: Endianness::Little,
1301 signed: false,
1302 };
1303 let result = read_typed_value(buffer, 1, &short_type);
1304 assert!(result.is_err());
1305 assert_eq!(
1306 result.unwrap_err(),
1307 TypeReadError::BufferOverrun {
1308 offset: 1,
1309 buffer_len: 2
1310 }
1311 );
1312}
1313
1314#[test]
1315fn test_read_typed_value_all_supported_types() {
1316 let buffer = &[0x7f, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a];
1317
1318 let test_cases = vec![
1320 (TypeKind::Byte { signed: false }, 0, Value::Uint(0x7f)),
1321 (
1322 TypeKind::Short {
1323 endian: Endianness::Little,
1324 signed: false,
1325 },
1326 1,
1327 Value::Uint(0x1234), ),
1329 (
1330 TypeKind::Short {
1331 endian: Endianness::Big,
1332 signed: false,
1333 },
1334 1,
1335 Value::Uint(0x3412), ),
1337 (
1338 TypeKind::Long {
1339 endian: Endianness::Little,
1340 signed: false,
1341 },
1342 1,
1343 Value::Uint(0x5678_1234), ),
1345 (
1346 TypeKind::Long {
1347 endian: Endianness::Big,
1348 signed: false,
1349 },
1350 1,
1351 Value::Uint(0x3412_7856), ),
1353 ];
1354
1355 for (type_kind, offset, expected) in test_cases {
1356 let result = read_typed_value(buffer, offset, &type_kind).unwrap();
1357 assert_eq!(result, expected, "Failed for type: {type_kind:?}");
1358 }
1359}
1360
1361#[test]
1362fn test_read_typed_value_signed_vs_unsigned() {
1363 let buffer = &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
1364
1365 let unsigned_short = TypeKind::Short {
1367 endian: Endianness::Little,
1368 signed: false,
1369 };
1370 let signed_short = TypeKind::Short {
1371 endian: Endianness::Little,
1372 signed: true,
1373 };
1374
1375 let unsigned_result = read_typed_value(buffer, 0, &unsigned_short).unwrap();
1376 let signed_result = read_typed_value(buffer, 0, &signed_short).unwrap();
1377
1378 assert_eq!(unsigned_result, Value::Uint(65535));
1379 assert_eq!(signed_result, Value::Int(-1));
1380
1381 let unsigned_long = TypeKind::Long {
1383 endian: Endianness::Little,
1384 signed: false,
1385 };
1386 let signed_long = TypeKind::Long {
1387 endian: Endianness::Little,
1388 signed: true,
1389 };
1390
1391 let unsigned_result = read_typed_value(buffer, 0, &unsigned_long).unwrap();
1392 let signed_result = read_typed_value(buffer, 0, &signed_long).unwrap();
1393
1394 assert_eq!(unsigned_result, Value::Uint(4_294_967_295));
1395 assert_eq!(signed_result, Value::Int(-1));
1396}
1397
1398#[test]
1399fn test_read_typed_value_consistency_with_direct_calls() {
1400 let buffer = &[0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xde, 0xf0];
1401
1402 let byte_type = TypeKind::Byte { signed: false };
1404 let direct_byte = read_byte(buffer, 0, false).unwrap();
1405 let typed_byte = read_typed_value(buffer, 0, &byte_type).unwrap();
1406 assert_eq!(direct_byte, typed_byte);
1407
1408 let short_type = TypeKind::Short {
1409 endian: Endianness::Little,
1410 signed: false,
1411 };
1412 let direct_short = read_short(buffer, 0, Endianness::Little, false).unwrap();
1413 let typed_short = read_typed_value(buffer, 0, &short_type).unwrap();
1414 assert_eq!(direct_short, typed_short);
1415
1416 let long_type = TypeKind::Long {
1417 endian: Endianness::Big,
1418 signed: true,
1419 };
1420 let direct_long = read_long(buffer, 0, Endianness::Big, true).unwrap();
1421 let typed_long = read_typed_value(buffer, 0, &long_type).unwrap();
1422 assert_eq!(direct_long, typed_long);
1423}
1424
1425#[test]
1426fn test_read_typed_value_empty_buffer() {
1427 let buffer = &[];
1428
1429 let types = vec![
1431 TypeKind::Byte { signed: false },
1432 TypeKind::Short {
1433 endian: Endianness::Little,
1434 signed: false,
1435 },
1436 TypeKind::Long {
1437 endian: Endianness::Little,
1438 signed: false,
1439 },
1440 ];
1441
1442 for type_kind in types {
1443 let result = read_typed_value(buffer, 0, &type_kind);
1444 assert!(result.is_err());
1445 match result.unwrap_err() {
1446 TypeReadError::BufferOverrun { offset, buffer_len } => {
1447 assert_eq!(offset, 0);
1448 assert_eq!(buffer_len, 0);
1449 }
1450 TypeReadError::UnsupportedType { .. } => panic!("Expected BufferOverrun error"),
1451 }
1452 }
1453}
1454
1455#[test]
1456#[allow(clippy::too_many_lines)]
1457fn test_coerce_value_to_type() {
1458 let cases = [
1459 (
1461 Value::Uint(0xff),
1462 TypeKind::Byte { signed: true },
1463 Value::Int(-1),
1464 ),
1465 (
1466 Value::Uint(0x80),
1467 TypeKind::Byte { signed: true },
1468 Value::Int(-128),
1469 ),
1470 (
1471 Value::Uint(0xfe),
1472 TypeKind::Byte { signed: true },
1473 Value::Int(-2),
1474 ),
1475 (
1477 Value::Uint(0x7f),
1478 TypeKind::Byte { signed: true },
1479 Value::Uint(0x7f),
1480 ),
1481 (
1482 Value::Uint(0),
1483 TypeKind::Byte { signed: true },
1484 Value::Uint(0),
1485 ),
1486 (
1487 Value::Uint(1),
1488 TypeKind::Byte { signed: true },
1489 Value::Uint(1),
1490 ),
1491 (
1493 Value::Uint(0xff),
1494 TypeKind::Byte { signed: false },
1495 Value::Uint(0xff),
1496 ),
1497 (
1498 Value::Uint(0x80),
1499 TypeKind::Byte { signed: false },
1500 Value::Uint(0x80),
1501 ),
1502 (
1504 Value::Uint(0xffff),
1505 TypeKind::Short {
1506 endian: Endianness::Native,
1507 signed: true,
1508 },
1509 Value::Int(-1),
1510 ),
1511 (
1512 Value::Uint(0x8000),
1513 TypeKind::Short {
1514 endian: Endianness::Native,
1515 signed: true,
1516 },
1517 Value::Int(-32768),
1518 ),
1519 (
1520 Value::Uint(0xffd8),
1521 TypeKind::Short {
1522 endian: Endianness::Big,
1523 signed: true,
1524 },
1525 Value::Int(-40),
1526 ),
1527 (
1529 Value::Uint(0x7fff),
1530 TypeKind::Short {
1531 endian: Endianness::Native,
1532 signed: true,
1533 },
1534 Value::Uint(0x7fff),
1535 ),
1536 (
1538 Value::Uint(0xffff),
1539 TypeKind::Short {
1540 endian: Endianness::Native,
1541 signed: false,
1542 },
1543 Value::Uint(0xffff),
1544 ),
1545 (
1547 Value::Uint(0xffff_ffff),
1548 TypeKind::Long {
1549 endian: Endianness::Native,
1550 signed: true,
1551 },
1552 Value::Int(-1),
1553 ),
1554 (
1555 Value::Uint(0x8000_0000),
1556 TypeKind::Long {
1557 endian: Endianness::Native,
1558 signed: true,
1559 },
1560 Value::Int(-2_147_483_648),
1561 ),
1562 (
1563 Value::Uint(0x8950_4e47),
1564 TypeKind::Long {
1565 endian: Endianness::Big,
1566 signed: true,
1567 },
1568 Value::Int(-1_991_225_785),
1569 ),
1570 (
1572 Value::Uint(0x7fff_ffff),
1573 TypeKind::Long {
1574 endian: Endianness::Native,
1575 signed: true,
1576 },
1577 Value::Uint(0x7fff_ffff),
1578 ),
1579 (
1581 Value::Uint(0xffff_ffff),
1582 TypeKind::Long {
1583 endian: Endianness::Native,
1584 signed: false,
1585 },
1586 Value::Uint(0xffff_ffff),
1587 ),
1588 (
1590 Value::Int(-1),
1591 TypeKind::Byte { signed: true },
1592 Value::Int(-1),
1593 ),
1594 (
1595 Value::Int(42),
1596 TypeKind::Long {
1597 endian: Endianness::Native,
1598 signed: true,
1599 },
1600 Value::Int(42),
1601 ),
1602 (
1604 Value::Uint(0xff),
1605 TypeKind::String { max_length: None },
1606 Value::Uint(0xff),
1607 ),
1608 ];
1609
1610 for (i, (input, type_kind, expected)) in cases.iter().enumerate() {
1611 let result = coerce_value_to_type(input, type_kind);
1612 assert_eq!(
1613 result, *expected,
1614 "Case {i}: coerce({input:?}, {type_kind:?})"
1615 );
1616 }
1617}