@@ -855,3 +855,395 @@ test "large maps" {
855855 try expect (value19 != null );
856856 try expect (try value19 .? .getInt () == 19 );
857857}
858+
859+ // Test array32 format
860+ test "array32 write and read" {
861+ // Create an array larger than 65535 elements would be too memory intensive
862+ // Instead test the boundary where array32 format kicks in
863+ var arr : [0xfffff ]u8 = std .mem .zeroes ([0xfffff ]u8 );
864+ var write_buffer = std .io .fixedBufferStream (& arr );
865+ var read_buffer = std .io .fixedBufferStream (& arr );
866+ var p = pack .init (& write_buffer , & read_buffer );
867+
868+ // Test with 65536 elements (0x10000), which should use array32
869+ const test_size = 0x10000 ;
870+ var test_payload = try Payload .arrPayload (test_size , allocator );
871+ defer test_payload .free (allocator );
872+
873+ for (0.. test_size ) | i | {
874+ try test_payload .setArrElement (i , Payload .uintToPayload (i % 256 ));
875+ }
876+
877+ try p .write (test_payload );
878+ const val = try p .read (allocator );
879+ defer val .free (allocator );
880+
881+ try expect ((try val .getArrLen ()) == test_size );
882+ // Check first and last elements
883+ try expect ((try val .getArrElement (0 )).uint == 0 );
884+ try expect ((try val .getArrElement (test_size - 1 )).uint == (test_size - 1 ) % 256 );
885+ }
886+
887+ // Test bin16 and bin32
888+ test "bin16 and bin32 write and read" {
889+ var arr : [0xfffff ]u8 = std .mem .zeroes ([0xfffff ]u8 );
890+ var write_buffer = std .io .fixedBufferStream (& arr );
891+ var read_buffer = std .io .fixedBufferStream (& arr );
892+ var p = pack .init (& write_buffer , & read_buffer );
893+
894+ // Test bin16 (256 bytes)
895+ const test_bin16 = try allocator .alloc (u8 , 256 );
896+ defer allocator .free (test_bin16 );
897+ for (test_bin16 , 0.. ) | * byte , i | {
898+ byte .* = @intCast (i % 256 );
899+ }
900+
901+ try p .write (.{ .bin = msgpack .wrapBin (test_bin16 ) });
902+ {
903+ const val = try p .read (allocator );
904+ defer val .free (allocator );
905+ try expect (val .bin .value ().len == 256 );
906+ try expect (val .bin .value ()[0 ] == 0 );
907+ try expect (val .bin .value ()[255 ] == 255 );
908+ }
909+
910+ // Reset buffers for bin32 test
911+ arr = std .mem .zeroes ([0xfffff ]u8 );
912+ write_buffer = std .io .fixedBufferStream (& arr );
913+ read_buffer = std .io .fixedBufferStream (& arr );
914+ p = pack .init (& write_buffer , & read_buffer );
915+
916+ // Test bin32 (65536 bytes)
917+ const test_bin32 = try allocator .alloc (u8 , 65536 );
918+ defer allocator .free (test_bin32 );
919+ for (test_bin32 , 0.. ) | * byte , i | {
920+ byte .* = @intCast (i % 256 );
921+ }
922+
923+ try p .write (.{ .bin = msgpack .wrapBin (test_bin32 ) });
924+ {
925+ const val = try p .read (allocator );
926+ defer val .free (allocator );
927+ try expect (val .bin .value ().len == 65536 );
928+ try expect (val .bin .value ()[0 ] == 0 );
929+ try expect (val .bin .value ()[65535 ] == 255 );
930+ }
931+ }
932+
933+ // Test str16 and str32
934+ test "str16 and str32 write and read" {
935+ var arr : [0xfffff ]u8 = std .mem .zeroes ([0xfffff ]u8 );
936+ var write_buffer = std .io .fixedBufferStream (& arr );
937+ var read_buffer = std .io .fixedBufferStream (& arr );
938+ var p = pack .init (& write_buffer , & read_buffer );
939+
940+ // Test str16 (256 characters)
941+ const str16_data = "x" ** 256 ;
942+ const str16_payload = try Payload .strToPayload (str16_data , allocator );
943+ defer str16_payload .free (allocator );
944+ try p .write (str16_payload );
945+ {
946+ const val = try p .read (allocator );
947+ defer val .free (allocator );
948+ try expect (val .str .value ().len == 256 );
949+ try expect (u8eql (str16_data , val .str .value ()));
950+ }
951+
952+ // Reset buffers for str32 test
953+ arr = std .mem .zeroes ([0xfffff ]u8 );
954+ write_buffer = std .io .fixedBufferStream (& arr );
955+ read_buffer = std .io .fixedBufferStream (& arr );
956+ p = pack .init (& write_buffer , & read_buffer );
957+
958+ // Test str32 (65536 characters)
959+ const str32_data = try allocator .alloc (u8 , 65536 );
960+ defer allocator .free (str32_data );
961+ @memset (str32_data , 'A' );
962+
963+ const str32_payload = try Payload .strToPayload (str32_data , allocator );
964+ defer str32_payload .free (allocator );
965+ try p .write (str32_payload );
966+ {
967+ const val = try p .read (allocator );
968+ defer val .free (allocator );
969+ try expect (val .str .value ().len == 65536 );
970+ try expect (u8eql (str32_data , val .str .value ()));
971+ }
972+ }
973+
974+ // Test int64 and uint64 boundary values
975+ test "int64 uint64 boundary values" {
976+ var arr : [0xffff_f ]u8 = std .mem .zeroes ([0xffff_f ]u8 );
977+ var write_buffer = std .io .fixedBufferStream (& arr );
978+ var read_buffer = std .io .fixedBufferStream (& arr );
979+ var p = pack .init (& write_buffer , & read_buffer );
980+
981+ // Test max int64
982+ const max_i64 : i64 = std .math .maxInt (i64 );
983+ try p .write (.{ .int = max_i64 });
984+ {
985+ const val = try p .read (allocator );
986+ defer val .free (allocator );
987+ try expect (try val .getInt () == max_i64 );
988+ }
989+
990+ // Reset buffers
991+ arr = std .mem .zeroes ([0xffff_f ]u8 );
992+ write_buffer = std .io .fixedBufferStream (& arr );
993+ read_buffer = std .io .fixedBufferStream (& arr );
994+ p = pack .init (& write_buffer , & read_buffer );
995+
996+ // Test min int64
997+ const min_i64 : i64 = std .math .minInt (i64 );
998+ try p .write (.{ .int = min_i64 });
999+ {
1000+ const val = try p .read (allocator );
1001+ defer val .free (allocator );
1002+ try expect (val .int == min_i64 );
1003+ }
1004+
1005+ // Reset buffers
1006+ arr = std .mem .zeroes ([0xffff_f ]u8 );
1007+ write_buffer = std .io .fixedBufferStream (& arr );
1008+ read_buffer = std .io .fixedBufferStream (& arr );
1009+ p = pack .init (& write_buffer , & read_buffer );
1010+
1011+ // Test max uint64
1012+ const max_u64 : u64 = std .math .maxInt (u64 );
1013+ try p .write (.{ .uint = max_u64 });
1014+ {
1015+ const val = try p .read (allocator );
1016+ defer val .free (allocator );
1017+ try expect (val .uint == max_u64 );
1018+ }
1019+ }
1020+
1021+ // Test getUint method
1022+ test "getUint method" {
1023+ // Test uint payload
1024+ const uint_payload = Payload .uintToPayload (42 );
1025+ try expect (try uint_payload .getUint () == 42 );
1026+
1027+ // Test positive int payload converted to uint
1028+ const pos_int_payload = Payload .intToPayload (24 );
1029+ try expect (try pos_int_payload .getUint () == 24 );
1030+
1031+ // Test negative int payload should fail
1032+ const neg_int_payload = Payload .intToPayload (-5 );
1033+ const result = neg_int_payload .getUint ();
1034+ try expect (result == msgpack .MsGPackError .INVALID_TYPE );
1035+
1036+ // Test non-numeric payload should fail
1037+ const nil_payload = Payload .nilToPayload ();
1038+ const nil_result = nil_payload .getUint ();
1039+ try expect (nil_result == msgpack .MsGPackError .INVALID_TYPE );
1040+ }
1041+
1042+ // Test NaN and Infinity float values
1043+ test "nan and infinity float values" {
1044+ var arr : [0xffff_f ]u8 = std .mem .zeroes ([0xffff_f ]u8 );
1045+ var write_buffer = std .io .fixedBufferStream (& arr );
1046+ var read_buffer = std .io .fixedBufferStream (& arr );
1047+ var p = pack .init (& write_buffer , & read_buffer );
1048+
1049+ // Test positive infinity
1050+ try p .write (.{ .float = std .math .inf (f64 ) });
1051+ {
1052+ const val = try p .read (allocator );
1053+ defer val .free (allocator );
1054+ try expect (std .math .isInf (val .float ));
1055+ try expect (val .float > 0 );
1056+ }
1057+
1058+ // Reset buffers
1059+ arr = std .mem .zeroes ([0xffff_f ]u8 );
1060+ write_buffer = std .io .fixedBufferStream (& arr );
1061+ read_buffer = std .io .fixedBufferStream (& arr );
1062+ p = pack .init (& write_buffer , & read_buffer );
1063+
1064+ // Test negative infinity
1065+ try p .write (.{ .float = - std .math .inf (f64 ) });
1066+ {
1067+ const val = try p .read (allocator );
1068+ defer val .free (allocator );
1069+ try expect (std .math .isInf (val .float ));
1070+ try expect (val .float < 0 );
1071+ }
1072+
1073+ // Reset buffers
1074+ arr = std .mem .zeroes ([0xffff_f ]u8 );
1075+ write_buffer = std .io .fixedBufferStream (& arr );
1076+ read_buffer = std .io .fixedBufferStream (& arr );
1077+ p = pack .init (& write_buffer , & read_buffer );
1078+
1079+ // Test NaN
1080+ try p .write (.{ .float = std .math .nan (f64 ) });
1081+ {
1082+ const val = try p .read (allocator );
1083+ defer val .free (allocator );
1084+ try expect (std .math .isNan (val .float ));
1085+ }
1086+ }
1087+
1088+ // Test edge cases and error conditions
1089+ test "edge cases and error conditions" {
1090+ var arr : [100 ]u8 = std .mem .zeroes ([100 ]u8 );
1091+ var write_buffer = std .io .fixedBufferStream (& arr );
1092+ var read_buffer = std .io .fixedBufferStream (& arr );
1093+ var p = pack .init (& write_buffer , & read_buffer );
1094+
1095+ // Test array index out of bounds
1096+ var test_arr = try Payload .arrPayload (3 , allocator );
1097+ defer test_arr .free (allocator );
1098+
1099+ // This should work
1100+ try test_arr .setArrElement (0 , Payload .nilToPayload ());
1101+ try test_arr .setArrElement (1 , Payload .boolToPayload (true ));
1102+ try test_arr .setArrElement (2 , Payload .intToPayload (42 ));
1103+
1104+ try p .write (test_arr );
1105+ const val = try p .read (allocator );
1106+ defer val .free (allocator );
1107+
1108+ try expect ((try val .getArrLen ()) == 3 );
1109+ try expect ((try val .getArrElement (0 )) == .nil );
1110+ try expect ((try val .getArrElement (1 )).bool == true );
1111+ try expect (try (try val .getArrElement (2 )).getInt () == 42 );
1112+ }
1113+
1114+ // Test positive fixint boundary (0-127)
1115+ test "positive fixint boundary" {
1116+ var arr : [0xffff_f ]u8 = std .mem .zeroes ([0xffff_f ]u8 );
1117+ var write_buffer = std .io .fixedBufferStream (& arr );
1118+ var read_buffer = std .io .fixedBufferStream (& arr );
1119+ var p = pack .init (& write_buffer , & read_buffer );
1120+
1121+ // Test boundary values for positive fixint (0-127)
1122+ const boundary_values = [_ ]u64 { 0 , 1 , 126 , 127 , 128 };
1123+
1124+ for (boundary_values ) | val | {
1125+ try p .write (.{ .uint = val });
1126+ }
1127+
1128+ // Reset read buffer
1129+ read_buffer = std .io .fixedBufferStream (& arr );
1130+ p = pack .init (& write_buffer , & read_buffer );
1131+
1132+ for (boundary_values ) | expected | {
1133+ const result = try p .read (allocator );
1134+ defer result .free (allocator );
1135+ try expect (result .uint == expected );
1136+ }
1137+ }
1138+
1139+ // Test fixstr boundary (0-31 bytes)
1140+ test "fixstr boundary" {
1141+ var arr : [0xffff_f ]u8 = std .mem .zeroes ([0xffff_f ]u8 );
1142+ var write_buffer = std .io .fixedBufferStream (& arr );
1143+ var read_buffer = std .io .fixedBufferStream (& arr );
1144+ var p = pack .init (& write_buffer , & read_buffer );
1145+
1146+ // Test different fixstr lengths
1147+ const test_strings = [_ ][]const u8 {
1148+ "" , // 0 bytes
1149+ "a" , // 1 byte
1150+ "hello" , // 5 bytes
1151+ "a" ** 31 , // 31 bytes (max fixstr)
1152+ "b" ** 32 , // 32 bytes (should use str8)
1153+ };
1154+
1155+ for (test_strings ) | test_str | {
1156+ const str_payload = try Payload .strToPayload (test_str , allocator );
1157+ defer str_payload .free (allocator );
1158+ try p .write (str_payload );
1159+ }
1160+
1161+ // Reset read buffer
1162+ read_buffer = std .io .fixedBufferStream (& arr );
1163+ p = pack .init (& write_buffer , & read_buffer );
1164+
1165+ for (test_strings ) | expected | {
1166+ const result = try p .read (allocator );
1167+ defer result .free (allocator );
1168+ try expect (u8eql (expected , result .str .value ()));
1169+ }
1170+ }
1171+
1172+ // Test fixarray boundary (0-15 elements)
1173+ test "fixarray boundary" {
1174+ var arr : [0xffff_f ]u8 = std .mem .zeroes ([0xffff_f ]u8 );
1175+ var write_buffer = std .io .fixedBufferStream (& arr );
1176+ var read_buffer = std .io .fixedBufferStream (& arr );
1177+ var p = pack .init (& write_buffer , & read_buffer );
1178+
1179+ // Test different fixarray sizes
1180+ const test_sizes = [_ ]usize { 0 , 1 , 5 , 15 , 16 };
1181+
1182+ for (test_sizes ) | size | {
1183+ var test_payload = try Payload .arrPayload (size , allocator );
1184+ defer test_payload .free (allocator );
1185+
1186+ for (0.. size ) | i | {
1187+ try test_payload .setArrElement (i , Payload .uintToPayload (i ));
1188+ }
1189+
1190+ try p .write (test_payload );
1191+ }
1192+
1193+ // Reset read buffer
1194+ read_buffer = std .io .fixedBufferStream (& arr );
1195+ p = pack .init (& write_buffer , & read_buffer );
1196+
1197+ for (test_sizes ) | expected_size | {
1198+ const result = try p .read (allocator );
1199+ defer result .free (allocator );
1200+ try expect ((try result .getArrLen ()) == expected_size );
1201+
1202+ for (0.. expected_size ) | i | {
1203+ const element = try result .getArrElement (i );
1204+ try expect (element .uint == i );
1205+ }
1206+ }
1207+ }
1208+
1209+ // Test fixmap boundary (0-15 elements)
1210+ test "fixmap boundary" {
1211+ var arr : [0xffff_f ]u8 = std .mem .zeroes ([0xffff_f ]u8 );
1212+ var write_buffer = std .io .fixedBufferStream (& arr );
1213+ var read_buffer = std .io .fixedBufferStream (& arr );
1214+ var p = pack .init (& write_buffer , & read_buffer );
1215+
1216+ // Test different fixmap sizes
1217+ const test_sizes = [_ ]usize { 0 , 1 , 5 , 15 , 16 };
1218+
1219+ for (test_sizes ) | size | {
1220+ var test_map = Payload .mapPayload (allocator );
1221+ defer test_map .free (allocator );
1222+
1223+ for (0.. size ) | i | {
1224+ const key = try std .fmt .allocPrint (allocator , "k{d}" , .{i });
1225+ defer allocator .free (key );
1226+ try test_map .mapPut (key , Payload .uintToPayload (i ));
1227+ }
1228+
1229+ try p .write (test_map );
1230+ }
1231+
1232+ // Reset read buffer
1233+ read_buffer = std .io .fixedBufferStream (& arr );
1234+ p = pack .init (& write_buffer , & read_buffer );
1235+
1236+ for (test_sizes ) | expected_size | {
1237+ const result = try p .read (allocator );
1238+ defer result .free (allocator );
1239+ try expect (result .map .count () == expected_size );
1240+
1241+ for (0.. expected_size ) | i | {
1242+ const key = try std .fmt .allocPrint (allocator , "k{d}" , .{i });
1243+ defer allocator .free (key );
1244+ const value = try result .mapGet (key );
1245+ try expect (value != null );
1246+ try expect (value .? .uint == i );
1247+ }
1248+ }
1249+ }
0 commit comments