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 end = offset.checked_add(2).ok_or(TypeReadError::BufferOverrun {
139 offset,
140 buffer_len: buffer.len(),
141 })?;
142 let bytes = buffer
143 .get(offset..end)
144 .ok_or(TypeReadError::BufferOverrun {
145 offset,
146 buffer_len: buffer.len(),
147 })?;
148
149 let value = match endian {
150 Endianness::Little => LittleEndian::read_u16(bytes),
151 Endianness::Big => BigEndian::read_u16(bytes),
152 Endianness::Native => NativeEndian::read_u16(bytes),
153 };
154
155 if signed {
156 #[allow(clippy::cast_possible_wrap)]
157 Ok(Value::Int(i64::from(value as i16)))
158 } else {
159 Ok(Value::Uint(u64::from(value)))
160 }
161}
162
163pub fn read_long(
199 buffer: &[u8],
200 offset: usize,
201 endian: Endianness,
202 signed: bool,
203) -> Result<Value, TypeReadError> {
204 let end = offset.checked_add(4).ok_or(TypeReadError::BufferOverrun {
205 offset,
206 buffer_len: buffer.len(),
207 })?;
208 let bytes = buffer
209 .get(offset..end)
210 .ok_or(TypeReadError::BufferOverrun {
211 offset,
212 buffer_len: buffer.len(),
213 })?;
214
215 let value = match endian {
216 Endianness::Little => LittleEndian::read_u32(bytes),
217 Endianness::Big => BigEndian::read_u32(bytes),
218 Endianness::Native => NativeEndian::read_u32(bytes),
219 };
220
221 if signed {
222 #[allow(clippy::cast_possible_wrap)]
223 Ok(Value::Int(i64::from(value as i32)))
224 } else {
225 Ok(Value::Uint(u64::from(value)))
226 }
227}
228
229pub fn read_quad(
270 buffer: &[u8],
271 offset: usize,
272 endian: Endianness,
273 signed: bool,
274) -> Result<Value, TypeReadError> {
275 let end = offset.checked_add(8).ok_or(TypeReadError::BufferOverrun {
276 offset,
277 buffer_len: buffer.len(),
278 })?;
279 let bytes = buffer
280 .get(offset..end)
281 .ok_or(TypeReadError::BufferOverrun {
282 offset,
283 buffer_len: buffer.len(),
284 })?;
285
286 let value = match endian {
287 Endianness::Little => LittleEndian::read_u64(bytes),
288 Endianness::Big => BigEndian::read_u64(bytes),
289 Endianness::Native => NativeEndian::read_u64(bytes),
290 };
291
292 if signed {
293 #[allow(clippy::cast_possible_wrap)]
294 Ok(Value::Int(value as i64))
295 } else {
296 Ok(Value::Uint(value))
297 }
298}
299
300pub fn read_string(
364 buffer: &[u8],
365 offset: usize,
366 max_length: Option<usize>,
367) -> Result<Value, TypeReadError> {
368 if offset >= buffer.len() {
370 return Err(TypeReadError::BufferOverrun {
371 offset,
372 buffer_len: buffer.len(),
373 });
374 }
375
376 let remaining_buffer = &buffer[offset..];
378
379 let read_length = if let Some(max_len) = max_length {
381 let search_len = std::cmp::min(max_len, remaining_buffer.len());
383 memchr::memchr(0, &remaining_buffer[..search_len]).unwrap_or(search_len)
384 } else {
385 memchr::memchr(0, remaining_buffer).unwrap_or(remaining_buffer.len())
387 };
388
389 let string_bytes = &remaining_buffer[..read_length];
391
392 let string_value = String::from_utf8_lossy(string_bytes).into_owned();
394
395 Ok(Value::String(string_value))
396}
397
398pub fn read_typed_value(
439 buffer: &[u8],
440 offset: usize,
441 type_kind: &TypeKind,
442) -> Result<Value, TypeReadError> {
443 match type_kind {
444 TypeKind::Byte { signed } => read_byte(buffer, offset, *signed),
445 TypeKind::Short { endian, signed } => read_short(buffer, offset, *endian, *signed),
446 TypeKind::Long { endian, signed } => read_long(buffer, offset, *endian, *signed),
447 TypeKind::Quad { endian, signed } => read_quad(buffer, offset, *endian, *signed),
448 TypeKind::String { max_length } => read_string(buffer, offset, *max_length),
449 }
450}
451
452#[must_use]
481pub fn coerce_value_to_type(value: &Value, type_kind: &TypeKind) -> Value {
482 match (value, type_kind) {
483 (Value::Uint(v), TypeKind::Byte { signed: true }) if *v > i8::MAX as u64 =>
484 {
485 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
486 Value::Int(i64::from(*v as u8 as i8))
487 }
488 (Value::Uint(v), TypeKind::Short { signed: true, .. }) if *v > i16::MAX as u64 =>
489 {
490 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
491 Value::Int(i64::from(*v as u16 as i16))
492 }
493 (Value::Uint(v), TypeKind::Long { signed: true, .. }) if *v > i32::MAX as u64 =>
494 {
495 #[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)]
496 Value::Int(i64::from(*v as u32 as i32))
497 }
498 (Value::Uint(v), TypeKind::Quad { signed: true, .. }) if *v > i64::MAX as u64 =>
499 {
500 #[allow(clippy::cast_possible_wrap)]
501 Value::Int(*v as i64)
502 }
503 _ => value.clone(),
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use super::*;
510
511 #[test]
512 fn test_read_byte_values() {
513 let buffer: Vec<u8> = (0..=255).collect();
515 for (i, &byte) in buffer.iter().enumerate() {
516 assert_eq!(
517 read_byte(&buffer, i, false).unwrap(),
518 Value::Uint(u64::from(byte))
519 );
520 }
521 }
522
523 #[test]
524 fn test_read_byte_out_of_bounds() {
525 assert_eq!(
527 read_byte(&[], 0, false).unwrap_err(),
528 TypeReadError::BufferOverrun {
529 offset: 0,
530 buffer_len: 0
531 }
532 );
533 assert_eq!(
535 read_byte(&[0x42], 1, false).unwrap_err(),
536 TypeReadError::BufferOverrun {
537 offset: 1,
538 buffer_len: 1
539 }
540 );
541 assert_eq!(
543 read_byte(&[1, 2, 3], 100, false).unwrap_err(),
544 TypeReadError::BufferOverrun {
545 offset: 100,
546 buffer_len: 3
547 }
548 );
549 }
550
551 #[test]
552 fn test_read_byte_signedness() {
553 let cases: Vec<(u8, bool, Value)> = vec![
554 (0x00, false, Value::Uint(0)),
555 (0x7f, false, Value::Uint(127)),
556 (0x80, false, Value::Uint(128)),
557 (0xff, false, Value::Uint(255)),
558 (0x00, true, Value::Int(0)),
559 (0x7f, true, Value::Int(127)),
560 (0x80, true, Value::Int(-128)),
561 (0xff, true, Value::Int(-1)),
562 ];
563 for (byte, signed, expected) in cases {
564 let result = read_byte(&[byte], 0, signed).unwrap();
565 assert_eq!(result, expected, "byte=0x{byte:02x}, signed={signed}");
566 }
567 }
568
569 #[test]
570 fn test_type_read_error_display() {
571 let error = TypeReadError::BufferOverrun {
572 offset: 10,
573 buffer_len: 5,
574 };
575 let msg = format!("{error}");
576 assert!(msg.contains("offset 10"));
577 assert!(msg.contains("buffer length is 5"));
578 }
579
580 #[test]
582 fn test_read_short_little_endian_unsigned() {
583 let buffer = &[0x34, 0x12, 0x78, 0x56]; let result = read_short(buffer, 0, Endianness::Little, false).unwrap();
587 assert_eq!(result, Value::Uint(0x1234));
588
589 let result = read_short(buffer, 2, Endianness::Little, false).unwrap();
591 assert_eq!(result, Value::Uint(0x5678));
592 }
593
594 #[test]
595 fn test_read_short_big_endian_unsigned() {
596 let buffer = &[0x12, 0x34, 0x56, 0x78]; let result = read_short(buffer, 0, Endianness::Big, false).unwrap();
600 assert_eq!(result, Value::Uint(0x1234));
601
602 let result = read_short(buffer, 2, Endianness::Big, false).unwrap();
604 assert_eq!(result, Value::Uint(0x5678));
605 }
606
607 #[test]
608 fn test_read_short_native_endian_unsigned() {
609 let buffer = &[0x34, 0x12, 0x78, 0x56];
610
611 let result = read_short(buffer, 0, Endianness::Native, false).unwrap();
613
614 match result {
616 Value::Uint(val) => {
617 assert!(val == 0x1234 || val == 0x3412);
619 }
620 _ => panic!("Expected Value::Uint variant"),
621 }
622 }
623
624 #[test]
625 fn test_read_short_signed_positive() {
626 let buffer = &[0xff, 0x7f]; let result = read_short(buffer, 0, Endianness::Little, true).unwrap();
629 assert_eq!(result, Value::Int(32767));
630 }
631
632 #[test]
633 fn test_read_short_signed_negative() {
634 let buffer = &[0x00, 0x80]; let result = read_short(buffer, 0, Endianness::Little, true).unwrap();
637 assert_eq!(result, Value::Int(-32768));
638 }
639
640 #[test]
641 fn test_read_short_signed_vs_unsigned() {
642 let buffer = &[0xff, 0xff]; let unsigned_result = read_short(buffer, 0, Endianness::Little, false).unwrap();
646 assert_eq!(unsigned_result, Value::Uint(65535));
647
648 let signed_result = read_short(buffer, 0, Endianness::Little, true).unwrap();
650 assert_eq!(signed_result, Value::Int(-1));
651 }
652
653 #[test]
654 fn test_read_short_buffer_overrun() {
655 let buffer = &[0x12]; let result = read_short(buffer, 0, Endianness::Little, false);
659 assert!(result.is_err());
660 assert_eq!(
661 result.unwrap_err(),
662 TypeReadError::BufferOverrun {
663 offset: 0,
664 buffer_len: 1
665 }
666 );
667 }
668
669 #[test]
670 fn test_read_short_offset_out_of_bounds() {
671 let buffer = &[0x12, 0x34, 0x56];
672
673 let result = read_short(buffer, 2, Endianness::Little, false);
675 assert!(result.is_err());
676 assert_eq!(
677 result.unwrap_err(),
678 TypeReadError::BufferOverrun {
679 offset: 2,
680 buffer_len: 3
681 }
682 );
683 }
684
685 #[test]
686 fn test_read_short_empty_buffer() {
687 let buffer = &[];
688
689 let result = read_short(buffer, 0, Endianness::Little, false);
690 assert!(result.is_err());
691 assert_eq!(
692 result.unwrap_err(),
693 TypeReadError::BufferOverrun {
694 offset: 0,
695 buffer_len: 0
696 }
697 );
698 }
699
700 #[test]
701 fn test_read_short_all_endianness_variants() {
702 let buffer = &[0x12, 0x34];
703
704 let little = read_short(buffer, 0, Endianness::Little, false).unwrap();
706 let big = read_short(buffer, 0, Endianness::Big, false).unwrap();
707 let native = read_short(buffer, 0, Endianness::Native, false).unwrap();
708
709 assert_eq!(little, Value::Uint(0x3412));
711 assert_eq!(big, Value::Uint(0x1234));
712
713 match native {
715 Value::Uint(val) => assert!(val == 0x1234 || val == 0x3412),
716 _ => panic!("Expected Value::Uint variant"),
717 }
718 }
719
720 #[test]
722 fn test_read_long_little_endian_unsigned() {
723 let buffer = &[0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a, 0x78, 0x56]; let result = read_long(buffer, 0, Endianness::Little, false).unwrap();
727 assert_eq!(result, Value::Uint(0x1234_5678));
728
729 let result = read_long(buffer, 4, Endianness::Little, false).unwrap();
731 assert_eq!(result, Value::Uint(0x5678_9abc));
732 }
733
734 #[test]
735 fn test_read_long_big_endian_unsigned() {
736 let buffer = &[0x12, 0x34, 0x56, 0x78, 0x56, 0x78, 0x9a, 0xbc]; let result = read_long(buffer, 0, Endianness::Big, false).unwrap();
740 assert_eq!(result, Value::Uint(0x1234_5678));
741
742 let result = read_long(buffer, 4, Endianness::Big, false).unwrap();
744 assert_eq!(result, Value::Uint(0x5678_9abc));
745 }
746
747 #[test]
748 fn test_read_long_native_endian_unsigned() {
749 let buffer = &[0x78, 0x56, 0x34, 0x12];
750
751 let result = read_long(buffer, 0, Endianness::Native, false).unwrap();
753
754 match result {
756 Value::Uint(val) => {
757 assert!(val == 0x1234_5678 || val == 0x7856_3412);
759 }
760 _ => panic!("Expected Value::Uint variant"),
761 }
762 }
763
764 #[test]
765 fn test_read_long_signed_positive() {
766 let buffer = &[0xff, 0xff, 0xff, 0x7f]; let result = read_long(buffer, 0, Endianness::Little, true).unwrap();
769 assert_eq!(result, Value::Int(2_147_483_647));
770 }
771
772 #[test]
773 fn test_read_long_signed_negative() {
774 let buffer = &[0x00, 0x00, 0x00, 0x80]; let result = read_long(buffer, 0, Endianness::Little, true).unwrap();
777 assert_eq!(result, Value::Int(-2_147_483_648));
778 }
779
780 #[test]
781 fn test_read_long_signed_vs_unsigned() {
782 let buffer = &[0xff, 0xff, 0xff, 0xff]; let unsigned_result = read_long(buffer, 0, Endianness::Little, false).unwrap();
786 assert_eq!(unsigned_result, Value::Uint(4_294_967_295));
787
788 let signed_result = read_long(buffer, 0, Endianness::Little, true).unwrap();
790 assert_eq!(signed_result, Value::Int(-1));
791 }
792
793 #[test]
794 fn test_read_long_buffer_overrun() {
795 let buffer = &[0x12, 0x34, 0x56]; let result = read_long(buffer, 0, Endianness::Little, false);
799 assert!(result.is_err());
800 assert_eq!(
801 result.unwrap_err(),
802 TypeReadError::BufferOverrun {
803 offset: 0,
804 buffer_len: 3
805 }
806 );
807 }
808
809 #[test]
810 fn test_read_long_offset_out_of_bounds() {
811 let buffer = &[0x12, 0x34, 0x56, 0x78, 0x9a];
812
813 let result = read_long(buffer, 2, Endianness::Little, false);
815 assert!(result.is_err());
816 assert_eq!(
817 result.unwrap_err(),
818 TypeReadError::BufferOverrun {
819 offset: 2,
820 buffer_len: 5
821 }
822 );
823 }
824
825 #[test]
826 fn test_read_long_empty_buffer() {
827 let buffer = &[];
828
829 let result = read_long(buffer, 0, Endianness::Little, false);
830 assert!(result.is_err());
831 assert_eq!(
832 result.unwrap_err(),
833 TypeReadError::BufferOverrun {
834 offset: 0,
835 buffer_len: 0
836 }
837 );
838 }
839
840 #[test]
841 fn test_read_long_all_endianness_variants() {
842 let buffer = &[0x12, 0x34, 0x56, 0x78];
843
844 let little = read_long(buffer, 0, Endianness::Little, false).unwrap();
846 let big = read_long(buffer, 0, Endianness::Big, false).unwrap();
847 let native = read_long(buffer, 0, Endianness::Native, false).unwrap();
848
849 assert_eq!(little, Value::Uint(0x7856_3412));
851 assert_eq!(big, Value::Uint(0x1234_5678));
852
853 match native {
855 Value::Uint(val) => assert!(val == 0x1234_5678 || val == 0x7856_3412),
856 _ => panic!("Expected Value::Uint variant"),
857 }
858 }
859
860 #[test]
861 fn test_read_long_extreme_values() {
862 let max_buffer = &[0xff, 0xff, 0xff, 0xff];
864 let max_result = read_long(max_buffer, 0, Endianness::Little, false).unwrap();
865 assert_eq!(max_result, Value::Uint(u64::from(u32::MAX)));
866
867 let zero_buffer = &[0x00, 0x00, 0x00, 0x00];
869 let zero_result = read_long(zero_buffer, 0, Endianness::Little, false).unwrap();
870 assert_eq!(zero_result, Value::Uint(0));
871 }
872
873 #[test]
875 fn test_read_quad_endianness_and_signedness() {
876 let cases: Vec<(&[u8], Endianness, bool, Value)> = vec![
877 (
879 &[0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12],
880 Endianness::Little,
881 false,
882 Value::Uint(0x1234_5678_90ab_cdef),
883 ),
884 (
886 &[0x12, 0x34, 0x56, 0x78, 0x90, 0xab, 0xcd, 0xef],
887 Endianness::Big,
888 false,
889 Value::Uint(0x1234_5678_90ab_cdef),
890 ),
891 (
893 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f],
894 Endianness::Little,
895 true,
896 Value::Int(i64::MAX),
897 ),
898 (
900 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80],
901 Endianness::Little,
902 true,
903 Value::Int(i64::MIN),
904 ),
905 (
907 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
908 Endianness::Big,
909 true,
910 Value::Int(-1),
911 ),
912 (
914 &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
915 Endianness::Little,
916 false,
917 Value::Uint(u64::MAX),
918 ),
919 (
921 &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
922 Endianness::Little,
923 false,
924 Value::Uint(0),
925 ),
926 ];
927 for (buffer, endian, signed, expected) in cases {
928 let result = read_quad(buffer, 0, endian, signed).unwrap();
929 assert_eq!(result, expected, "endian={endian:?}, signed={signed}");
930 }
931 }
932
933 #[test]
934 fn test_read_quad_buffer_overrun() {
935 let buffer = &[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07];
937 assert_eq!(
938 read_quad(buffer, 0, Endianness::Little, false).unwrap_err(),
939 TypeReadError::BufferOverrun {
940 offset: 0,
941 buffer_len: 7
942 }
943 );
944
945 assert_eq!(
947 read_quad(&[], 0, Endianness::Big, false).unwrap_err(),
948 TypeReadError::BufferOverrun {
949 offset: 0,
950 buffer_len: 0
951 }
952 );
953
954 let buffer = &[0x00; 16];
956 assert_eq!(
957 read_quad(buffer, 10, Endianness::Little, false).unwrap_err(),
958 TypeReadError::BufferOverrun {
959 offset: 10,
960 buffer_len: 16
961 }
962 );
963 }
964
965 #[test]
966 fn test_read_quad_at_offset() {
967 let buffer = &[0x00, 0x00, 0xef, 0xcd, 0xab, 0x90, 0x78, 0x56, 0x34, 0x12];
968 let result = read_quad(buffer, 2, Endianness::Little, false).unwrap();
969 assert_eq!(result, Value::Uint(0x1234_5678_90ab_cdef));
970 }
971
972 #[test]
973 fn test_read_short_extreme_values() {
974 let max_buffer = &[0xff, 0xff];
976 let max_result = read_short(max_buffer, 0, Endianness::Little, false).unwrap();
977 assert_eq!(max_result, Value::Uint(u64::from(u16::MAX)));
978
979 let zero_buffer = &[0x00, 0x00];
981 let zero_result = read_short(zero_buffer, 0, Endianness::Little, false).unwrap();
982 assert_eq!(zero_result, Value::Uint(0));
983 }
984
985 #[test]
986 fn test_multi_byte_reading_consistency() {
987 let buffer = &[0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xde, 0xf0];
989
990 let byte0 = read_byte(buffer, 0, false).unwrap();
992 let byte1 = read_byte(buffer, 1, false).unwrap();
993
994 let short = read_short(buffer, 0, Endianness::Little, false).unwrap();
996
997 match (byte0, byte1, short) {
999 (Value::Uint(b0), Value::Uint(b1), Value::Uint(s)) => {
1000 assert_eq!(s, b0 + (b1 << 8)); }
1002 _ => panic!("Expected all Uint values"),
1003 }
1004 }
1005
1006 #[test]
1008 fn test_unsupported_type_error() {
1009 let error = TypeReadError::UnsupportedType {
1010 type_name: "CustomType".to_string(),
1011 };
1012
1013 let error_string = format!("{error}");
1014 assert!(error_string.contains("Unsupported type"));
1015 assert!(error_string.contains("CustomType"));
1016 }
1017
1018 #[test]
1019 fn test_unsupported_type_error_debug() {
1020 let error = TypeReadError::UnsupportedType {
1021 type_name: "TestType".to_string(),
1022 };
1023
1024 let debug_string = format!("{error:?}");
1025 assert!(debug_string.contains("UnsupportedType"));
1026 assert!(debug_string.contains("TestType"));
1027 }
1028
1029 #[test]
1030 fn test_unsupported_type_error_equality() {
1031 let error1 = TypeReadError::UnsupportedType {
1032 type_name: "Type1".to_string(),
1033 };
1034 let error2 = TypeReadError::UnsupportedType {
1035 type_name: "Type1".to_string(),
1036 };
1037 let error3 = TypeReadError::UnsupportedType {
1038 type_name: "Type2".to_string(),
1039 };
1040
1041 assert_eq!(error1, error2);
1042 assert_ne!(error1, error3);
1043 }
1044
1045 #[test]
1047 fn test_read_typed_value_byte() {
1048 let buffer = &[0x7f, 0x45, 0x4c, 0x46];
1049 let type_kind = TypeKind::Byte { signed: false };
1050
1051 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1052 assert_eq!(result, Value::Uint(0x7f));
1053
1054 let result = read_typed_value(buffer, 3, &type_kind).unwrap();
1055 assert_eq!(result, Value::Uint(0x46));
1056 }
1057
1058 #[test]
1059 fn test_read_typed_value_short_unsigned_little_endian() {
1060 let buffer = &[0x34, 0x12, 0x78, 0x56];
1061 let type_kind = TypeKind::Short {
1062 endian: Endianness::Little,
1063 signed: false,
1064 };
1065
1066 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1067 assert_eq!(result, Value::Uint(0x1234));
1068
1069 let result = read_typed_value(buffer, 2, &type_kind).unwrap();
1070 assert_eq!(result, Value::Uint(0x5678));
1071 }
1072
1073 #[test]
1074 fn test_read_typed_value_short_signed_big_endian() {
1075 let buffer = &[0x80, 0x00, 0x7f, 0xff];
1076 let type_kind = TypeKind::Short {
1077 endian: Endianness::Big,
1078 signed: true,
1079 };
1080
1081 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1083 assert_eq!(result, Value::Int(-32768));
1084
1085 let result = read_typed_value(buffer, 2, &type_kind).unwrap();
1087 assert_eq!(result, Value::Int(32767));
1088 }
1089
1090 #[test]
1091 fn test_read_typed_value_long_unsigned_little_endian() {
1092 let buffer = &[0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a, 0x78, 0x56];
1093 let type_kind = TypeKind::Long {
1094 endian: Endianness::Little,
1095 signed: false,
1096 };
1097
1098 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1099 assert_eq!(result, Value::Uint(0x1234_5678));
1100
1101 let result = read_typed_value(buffer, 4, &type_kind).unwrap();
1102 assert_eq!(result, Value::Uint(0x5678_9abc));
1103 }
1104
1105 #[test]
1106 fn test_read_typed_value_long_signed_big_endian() {
1107 let buffer = &[0x80, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff];
1108 let type_kind = TypeKind::Long {
1109 endian: Endianness::Big,
1110 signed: true,
1111 };
1112
1113 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1115 assert_eq!(result, Value::Int(-2_147_483_648));
1116
1117 let result = read_typed_value(buffer, 4, &type_kind).unwrap();
1119 assert_eq!(result, Value::Int(2_147_483_647));
1120 }
1121
1122 #[test]
1123 fn test_read_typed_value_native_endian() {
1124 let buffer = &[0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xde, 0xf0];
1125
1126 let short_type = TypeKind::Short {
1128 endian: Endianness::Native,
1129 signed: false,
1130 };
1131
1132 let result = read_typed_value(buffer, 0, &short_type).unwrap();
1133 match result {
1134 Value::Uint(val) => {
1135 assert!(val == 0x1234 || val == 0x3412);
1137 }
1138 _ => panic!("Expected Value::Uint variant"),
1139 }
1140 }
1141
1142 #[test]
1143 fn test_read_typed_value_string() {
1144 let buffer = b"Hello\x00World\x00";
1145 let type_kind = TypeKind::String { max_length: None };
1146
1147 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1148 assert_eq!(result, Value::String("Hello".to_string()));
1149
1150 let result = read_typed_value(buffer, 6, &type_kind).unwrap();
1151 assert_eq!(result, Value::String("World".to_string()));
1152 }
1153
1154 #[test]
1155 fn test_read_typed_value_string_with_max_length() {
1156 let buffer = b"VeryLongString\x00";
1157 let type_kind = TypeKind::String {
1158 max_length: Some(4),
1159 };
1160
1161 let result = read_typed_value(buffer, 0, &type_kind).unwrap();
1162 assert_eq!(result, Value::String("Very".to_string()));
1163 }
1164
1165 #[test]
1166 fn test_read_typed_value_buffer_overrun() {
1167 let buffer = &[0x12];
1168 let type_kind = TypeKind::Short {
1169 endian: Endianness::Little,
1170 signed: false,
1171 };
1172
1173 let result = read_typed_value(buffer, 0, &type_kind);
1174 assert!(result.is_err());
1175 assert_eq!(
1176 result.unwrap_err(),
1177 TypeReadError::BufferOverrun {
1178 offset: 0,
1179 buffer_len: 1
1180 }
1181 );
1182 }
1183
1184 #[test]
1186 fn test_read_string_null_terminated() {
1187 let buffer = b"Hello\x00World";
1188
1189 let result = read_string(buffer, 0, None).unwrap();
1190 assert_eq!(result, Value::String("Hello".to_string()));
1191 }
1192
1193 #[test]
1194 fn test_read_string_null_terminated_at_offset() {
1195 let buffer = b"Prefix\x00Hello\x00Suffix";
1196
1197 let result = read_string(buffer, 7, None).unwrap();
1198 assert_eq!(result, Value::String("Hello".to_string()));
1199 }
1200
1201 #[test]
1202 fn test_read_string_with_max_length_shorter_than_null() {
1203 let buffer = b"VeryLongString\x00";
1204
1205 let result = read_string(buffer, 0, Some(4)).unwrap();
1207 assert_eq!(result, Value::String("Very".to_string()));
1208 }
1209
1210 #[test]
1211 fn test_read_string_with_max_length_longer_than_null() {
1212 let buffer = b"Short\x00LongerSuffix";
1213
1214 let result = read_string(buffer, 0, Some(10)).unwrap();
1216 assert_eq!(result, Value::String("Short".to_string()));
1217 }
1218
1219 #[test]
1220 fn test_read_string_no_null_terminator_with_max_length() {
1221 let buffer = b"NoNullTerminator";
1222
1223 let result = read_string(buffer, 0, Some(6)).unwrap();
1225 assert_eq!(result, Value::String("NoNull".to_string()));
1226 }
1227
1228 #[test]
1229 fn test_read_string_no_null_terminator_no_max_length() {
1230 let buffer = b"NoNullTerminator";
1231
1232 let result = read_string(buffer, 0, None).unwrap();
1234 assert_eq!(result, Value::String("NoNullTerminator".to_string()));
1235 }
1236
1237 #[test]
1238 fn test_read_string_empty_string() {
1239 let buffer = b"\x00Hello";
1240
1241 let result = read_string(buffer, 0, None).unwrap();
1243 assert_eq!(result, Value::String(String::new()));
1244 }
1245
1246 #[test]
1247 fn test_read_string_empty_buffer() {
1248 let buffer = b"";
1249
1250 let result = read_string(buffer, 0, None);
1252 assert!(result.is_err());
1253 assert_eq!(
1254 result.unwrap_err(),
1255 TypeReadError::BufferOverrun {
1256 offset: 0,
1257 buffer_len: 0
1258 }
1259 );
1260 }
1261
1262 #[test]
1263 fn test_read_string_offset_out_of_bounds() {
1264 let buffer = b"Hello";
1265
1266 let result = read_string(buffer, 10, None);
1268 assert!(result.is_err());
1269 assert_eq!(
1270 result.unwrap_err(),
1271 TypeReadError::BufferOverrun {
1272 offset: 10,
1273 buffer_len: 5
1274 }
1275 );
1276 }
1277
1278 #[test]
1279 fn test_read_string_offset_at_buffer_end() {
1280 let buffer = b"Hello";
1281
1282 let result = read_string(buffer, 5, None);
1284 assert!(result.is_err());
1285 assert_eq!(
1286 result.unwrap_err(),
1287 TypeReadError::BufferOverrun {
1288 offset: 5,
1289 buffer_len: 5
1290 }
1291 );
1292 }
1293
1294 #[test]
1295 fn test_read_string_max_length_zero() {
1296 let buffer = b"Hello\x00World";
1297
1298 let result = read_string(buffer, 0, Some(0)).unwrap();
1300 assert_eq!(result, Value::String(String::new()));
1301 }
1302
1303 #[test]
1304 fn test_read_string_max_length_larger_than_buffer() {
1305 let buffer = b"Short";
1306
1307 let result = read_string(buffer, 0, Some(100)).unwrap();
1309 assert_eq!(result, Value::String("Short".to_string()));
1310 }
1311
1312 #[test]
1313 fn test_read_string_utf8_valid() {
1314 let buffer = b"Caf\xc3\xa9\x00"; let result = read_string(buffer, 0, None).unwrap();
1317 assert_eq!(result, Value::String("Café".to_string()));
1318 }
1319
1320 #[test]
1321 fn test_read_string_utf8_invalid() {
1322 let buffer = b"Invalid\xff\xfe\x00"; let result = read_string(buffer, 0, None).unwrap();
1325 assert!(matches!(result, Value::String(_)));
1327 if let Value::String(s) = result {
1328 assert!(s.starts_with("Invalid"));
1329 assert!(s.contains('\u{FFFD}')); }
1331 }
1332
1333 #[test]
1334 fn test_read_string_binary_data() {
1335 let buffer = &[0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x80, 0x90]; let result = read_string(buffer, 0, None).unwrap();
1338 assert_eq!(result, Value::String("Hello".to_string()));
1339 }
1340
1341 #[test]
1342 fn test_read_string_multiple_nulls() {
1343 let buffer = b"First\x00\x00Second\x00";
1344
1345 let result = read_string(buffer, 0, None).unwrap();
1347 assert_eq!(result, Value::String("First".to_string()));
1348
1349 let result = read_string(buffer, 6, None).unwrap();
1351 assert_eq!(result, Value::String(String::new()));
1352 }
1353
1354 #[test]
1355 fn test_read_string_ascii_control_characters() {
1356 let buffer = b"Hello\x09World\x00"; let result = read_string(buffer, 0, None).unwrap();
1359 assert_eq!(result, Value::String("Hello\tWorld".to_string()));
1360 }
1361
1362 #[test]
1363 fn test_read_string_single_character() {
1364 let buffer = b"A\x00";
1365
1366 let result = read_string(buffer, 0, None).unwrap();
1367 assert_eq!(result, Value::String("A".to_string()));
1368 }
1369
1370 #[test]
1371 fn test_read_string_max_length_exact_match() {
1372 let buffer = b"Exact\x00";
1373
1374 let result = read_string(buffer, 0, Some(5)).unwrap();
1376 assert_eq!(result, Value::String("Exact".to_string()));
1377 }
1378
1379 #[test]
1380 fn test_read_string_at_buffer_boundary() {
1381 let buffer = b"Hello";
1382
1383 let result = read_string(buffer, 4, Some(1)).unwrap();
1385 assert_eq!(result, Value::String("o".to_string()));
1386 }
1387
1388 #[test]
1389 fn test_read_string_whitespace_handling() {
1390 let buffer = b" Spaces \x00";
1391
1392 let result = read_string(buffer, 0, None).unwrap();
1394 assert_eq!(result, Value::String(" Spaces ".to_string()));
1395 }
1396
1397 #[test]
1398 fn test_read_string_newline_characters() {
1399 let buffer = b"Line1\nLine2\r\n\x00";
1400
1401 let result = read_string(buffer, 0, None).unwrap();
1402 assert_eq!(result, Value::String("Line1\nLine2\r\n".to_string()));
1403 }
1404
1405 #[test]
1406 fn test_read_string_consistency_with_typed_value() {
1407 let buffer = b"Test\x00String";
1408
1409 let direct_result = read_string(buffer, 0, None).unwrap();
1411
1412 let type_kind = TypeKind::String { max_length: None };
1413 let typed_result = read_typed_value(buffer, 0, &type_kind).unwrap();
1414
1415 assert_eq!(direct_result, typed_result);
1416 assert_eq!(typed_result, Value::String("Test".to_string()));
1417 }
1418
1419 #[test]
1420 fn test_read_string_consistency_with_max_length() {
1421 let buffer = b"LongString\x00";
1422
1423 let direct_result = read_string(buffer, 0, Some(4)).unwrap();
1425
1426 let type_kind = TypeKind::String {
1427 max_length: Some(4),
1428 };
1429 let typed_result = read_typed_value(buffer, 0, &type_kind).unwrap();
1430
1431 assert_eq!(direct_result, typed_result);
1432 assert_eq!(typed_result, Value::String("Long".to_string()));
1433 }
1434
1435 #[test]
1436 fn test_read_string_edge_case_combinations() {
1437 let test_cases = [
1439 (b"" as &[u8], 0, None, true), (b"\x00", 0, None, false), (b"A", 0, Some(0), false), (b"AB", 1, Some(1), false), ];
1444
1445 for (buffer, offset, max_length, should_fail) in test_cases {
1446 let result = read_string(buffer, offset, max_length);
1447
1448 if should_fail {
1449 assert!(
1450 result.is_err(),
1451 "Expected failure for buffer {buffer:?}, offset {offset}, max_length {max_length:?}"
1452 );
1453 } else {
1454 assert!(
1455 result.is_ok(),
1456 "Expected success for buffer {buffer:?}, offset {offset}, max_length {max_length:?}"
1457 );
1458 }
1459 }
1460 }
1461}
1462
1463#[test]
1464fn test_read_typed_value_buffer_overrun() {
1465 let buffer = &[0x12, 0x34];
1466
1467 let long_type = TypeKind::Long {
1469 endian: Endianness::Little,
1470 signed: false,
1471 };
1472 let result = read_typed_value(buffer, 0, &long_type);
1473 assert!(result.is_err());
1474 assert_eq!(
1475 result.unwrap_err(),
1476 TypeReadError::BufferOverrun {
1477 offset: 0,
1478 buffer_len: 2
1479 }
1480 );
1481
1482 let short_type = TypeKind::Short {
1484 endian: Endianness::Little,
1485 signed: false,
1486 };
1487 let result = read_typed_value(buffer, 1, &short_type);
1488 assert!(result.is_err());
1489 assert_eq!(
1490 result.unwrap_err(),
1491 TypeReadError::BufferOverrun {
1492 offset: 1,
1493 buffer_len: 2
1494 }
1495 );
1496}
1497
1498#[test]
1499fn test_read_typed_value_all_supported_types() {
1500 let buffer = &[0x7f, 0x34, 0x12, 0x78, 0x56, 0x34, 0x12, 0xbc, 0x9a];
1501
1502 let test_cases = vec![
1504 (TypeKind::Byte { signed: false }, 0, Value::Uint(0x7f)),
1505 (
1506 TypeKind::Short {
1507 endian: Endianness::Little,
1508 signed: false,
1509 },
1510 1,
1511 Value::Uint(0x1234), ),
1513 (
1514 TypeKind::Short {
1515 endian: Endianness::Big,
1516 signed: false,
1517 },
1518 1,
1519 Value::Uint(0x3412), ),
1521 (
1522 TypeKind::Long {
1523 endian: Endianness::Little,
1524 signed: false,
1525 },
1526 1,
1527 Value::Uint(0x5678_1234), ),
1529 (
1530 TypeKind::Long {
1531 endian: Endianness::Big,
1532 signed: false,
1533 },
1534 1,
1535 Value::Uint(0x3412_7856), ),
1537 ];
1538
1539 for (type_kind, offset, expected) in test_cases {
1540 let result = read_typed_value(buffer, offset, &type_kind).unwrap();
1541 assert_eq!(result, expected, "Failed for type: {type_kind:?}");
1542 }
1543}
1544
1545#[test]
1546fn test_read_typed_value_signed_vs_unsigned() {
1547 let buffer = &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff];
1548
1549 let unsigned_short = TypeKind::Short {
1551 endian: Endianness::Little,
1552 signed: false,
1553 };
1554 let signed_short = TypeKind::Short {
1555 endian: Endianness::Little,
1556 signed: true,
1557 };
1558
1559 let unsigned_result = read_typed_value(buffer, 0, &unsigned_short).unwrap();
1560 let signed_result = read_typed_value(buffer, 0, &signed_short).unwrap();
1561
1562 assert_eq!(unsigned_result, Value::Uint(65535));
1563 assert_eq!(signed_result, Value::Int(-1));
1564
1565 let unsigned_long = TypeKind::Long {
1567 endian: Endianness::Little,
1568 signed: false,
1569 };
1570 let signed_long = TypeKind::Long {
1571 endian: Endianness::Little,
1572 signed: true,
1573 };
1574
1575 let unsigned_result = read_typed_value(buffer, 0, &unsigned_long).unwrap();
1576 let signed_result = read_typed_value(buffer, 0, &signed_long).unwrap();
1577
1578 assert_eq!(unsigned_result, Value::Uint(4_294_967_295));
1579 assert_eq!(signed_result, Value::Int(-1));
1580}
1581
1582#[test]
1583fn test_read_typed_value_consistency_with_direct_calls() {
1584 let buffer = &[0x34, 0x12, 0x78, 0x56, 0xbc, 0x9a, 0xde, 0xf0];
1585
1586 let byte_type = TypeKind::Byte { signed: false };
1588 let direct_byte = read_byte(buffer, 0, false).unwrap();
1589 let typed_byte = read_typed_value(buffer, 0, &byte_type).unwrap();
1590 assert_eq!(direct_byte, typed_byte);
1591
1592 let short_type = TypeKind::Short {
1593 endian: Endianness::Little,
1594 signed: false,
1595 };
1596 let direct_short = read_short(buffer, 0, Endianness::Little, false).unwrap();
1597 let typed_short = read_typed_value(buffer, 0, &short_type).unwrap();
1598 assert_eq!(direct_short, typed_short);
1599
1600 let long_type = TypeKind::Long {
1601 endian: Endianness::Big,
1602 signed: true,
1603 };
1604 let direct_long = read_long(buffer, 0, Endianness::Big, true).unwrap();
1605 let typed_long = read_typed_value(buffer, 0, &long_type).unwrap();
1606 assert_eq!(direct_long, typed_long);
1607}
1608
1609#[test]
1610fn test_read_typed_value_empty_buffer() {
1611 let buffer = &[];
1612
1613 let types = vec![
1615 TypeKind::Byte { signed: false },
1616 TypeKind::Short {
1617 endian: Endianness::Little,
1618 signed: false,
1619 },
1620 TypeKind::Long {
1621 endian: Endianness::Little,
1622 signed: false,
1623 },
1624 ];
1625
1626 for type_kind in types {
1627 let result = read_typed_value(buffer, 0, &type_kind);
1628 assert!(result.is_err());
1629 match result.unwrap_err() {
1630 TypeReadError::BufferOverrun { offset, buffer_len } => {
1631 assert_eq!(offset, 0);
1632 assert_eq!(buffer_len, 0);
1633 }
1634 TypeReadError::UnsupportedType { .. } => panic!("Expected BufferOverrun error"),
1635 }
1636 }
1637}
1638
1639#[test]
1640#[allow(clippy::too_many_lines)]
1641fn test_coerce_value_to_type() {
1642 let cases = [
1643 (
1645 Value::Uint(0xff),
1646 TypeKind::Byte { signed: true },
1647 Value::Int(-1),
1648 ),
1649 (
1650 Value::Uint(0x80),
1651 TypeKind::Byte { signed: true },
1652 Value::Int(-128),
1653 ),
1654 (
1655 Value::Uint(0xfe),
1656 TypeKind::Byte { signed: true },
1657 Value::Int(-2),
1658 ),
1659 (
1661 Value::Uint(0x7f),
1662 TypeKind::Byte { signed: true },
1663 Value::Uint(0x7f),
1664 ),
1665 (
1666 Value::Uint(0),
1667 TypeKind::Byte { signed: true },
1668 Value::Uint(0),
1669 ),
1670 (
1671 Value::Uint(1),
1672 TypeKind::Byte { signed: true },
1673 Value::Uint(1),
1674 ),
1675 (
1677 Value::Uint(0xff),
1678 TypeKind::Byte { signed: false },
1679 Value::Uint(0xff),
1680 ),
1681 (
1682 Value::Uint(0x80),
1683 TypeKind::Byte { signed: false },
1684 Value::Uint(0x80),
1685 ),
1686 (
1688 Value::Uint(0xffff),
1689 TypeKind::Short {
1690 endian: Endianness::Native,
1691 signed: true,
1692 },
1693 Value::Int(-1),
1694 ),
1695 (
1696 Value::Uint(0x8000),
1697 TypeKind::Short {
1698 endian: Endianness::Native,
1699 signed: true,
1700 },
1701 Value::Int(-32768),
1702 ),
1703 (
1704 Value::Uint(0xffd8),
1705 TypeKind::Short {
1706 endian: Endianness::Big,
1707 signed: true,
1708 },
1709 Value::Int(-40),
1710 ),
1711 (
1713 Value::Uint(0x7fff),
1714 TypeKind::Short {
1715 endian: Endianness::Native,
1716 signed: true,
1717 },
1718 Value::Uint(0x7fff),
1719 ),
1720 (
1722 Value::Uint(0xffff),
1723 TypeKind::Short {
1724 endian: Endianness::Native,
1725 signed: false,
1726 },
1727 Value::Uint(0xffff),
1728 ),
1729 (
1731 Value::Uint(0xffff_ffff),
1732 TypeKind::Long {
1733 endian: Endianness::Native,
1734 signed: true,
1735 },
1736 Value::Int(-1),
1737 ),
1738 (
1739 Value::Uint(0x8000_0000),
1740 TypeKind::Long {
1741 endian: Endianness::Native,
1742 signed: true,
1743 },
1744 Value::Int(-2_147_483_648),
1745 ),
1746 (
1747 Value::Uint(0x8950_4e47),
1748 TypeKind::Long {
1749 endian: Endianness::Big,
1750 signed: true,
1751 },
1752 Value::Int(-1_991_225_785),
1753 ),
1754 (
1756 Value::Uint(0x7fff_ffff),
1757 TypeKind::Long {
1758 endian: Endianness::Native,
1759 signed: true,
1760 },
1761 Value::Uint(0x7fff_ffff),
1762 ),
1763 (
1765 Value::Uint(0xffff_ffff),
1766 TypeKind::Long {
1767 endian: Endianness::Native,
1768 signed: false,
1769 },
1770 Value::Uint(0xffff_ffff),
1771 ),
1772 (
1774 Value::Uint(0xffff_ffff_ffff_ffff),
1775 TypeKind::Quad {
1776 endian: Endianness::Native,
1777 signed: true,
1778 },
1779 Value::Int(-1),
1780 ),
1781 (
1782 Value::Uint(0x8000_0000_0000_0000),
1783 TypeKind::Quad {
1784 endian: Endianness::Native,
1785 signed: true,
1786 },
1787 Value::Int(i64::MIN),
1788 ),
1789 (
1791 Value::Uint(0x7fff_ffff_ffff_ffff),
1792 TypeKind::Quad {
1793 endian: Endianness::Native,
1794 signed: true,
1795 },
1796 Value::Uint(0x7fff_ffff_ffff_ffff),
1797 ),
1798 (
1800 Value::Uint(0xffff_ffff_ffff_ffff),
1801 TypeKind::Quad {
1802 endian: Endianness::Native,
1803 signed: false,
1804 },
1805 Value::Uint(0xffff_ffff_ffff_ffff),
1806 ),
1807 (
1809 Value::Int(-1),
1810 TypeKind::Byte { signed: true },
1811 Value::Int(-1),
1812 ),
1813 (
1814 Value::Int(42),
1815 TypeKind::Long {
1816 endian: Endianness::Native,
1817 signed: true,
1818 },
1819 Value::Int(42),
1820 ),
1821 (
1823 Value::Uint(0xff),
1824 TypeKind::String { max_length: None },
1825 Value::Uint(0xff),
1826 ),
1827 ];
1828
1829 for (i, (input, type_kind, expected)) in cases.iter().enumerate() {
1830 let result = coerce_value_to_type(input, type_kind);
1831 assert_eq!(
1832 result, *expected,
1833 "Case {i}: coerce({input:?}, {type_kind:?})"
1834 );
1835 }
1836}