@@ -28,12 +28,15 @@ pub fn decodeAlloc(comptime T: type, allocator: std.mem.Allocator, data: []const
2828 },
2929 .optional = > | info | decodeOption (info .child , allocator , data , decodeAlloc ),
3030 .pointer = > | info | {
31- if (info .size == .slice and info . child == u8 ) {
32- return decodeStringAlloc ( allocator , data );
31+ if (info .size == .slice ) {
32+ return decodeSlice ( info . child , allocator , data , decodeAlloc );
3333 } else {
3434 return error .UnsupportedType ;
3535 }
3636 },
37+ .array = > | info | {
38+ return decodeSlice (info .child , allocator , data , decodeAlloc );
39+ },
3740 .@"struct" = > {
3841 return decodeTuple (T , allocator , data );
3942 },
@@ -94,24 +97,46 @@ fn decodeCompact(comptime T: type, data: []const u8) !DecodeResult(T) {
9497 }
9598}
9699
97- fn decodeStringAlloc (allocator : std.mem.Allocator , data : []const u8 ) ! DecodeResult ([]const u8 ) {
98- // Use u64 to handle larger string lengths, but ensure they fit in usize
99- const length = try decodeCompact (u64 , data );
100- const start = length .bytes_read ;
101-
102- // Check if length fits in usize
103- if (length .value > std .math .maxInt (usize )) return error .BigIntegerNotSupported ;
104-
105- const len : usize = @intCast (length .value );
106- const end = start + len ;
100+ fn decodeSlice (comptime T : type , allocator : std.mem.Allocator , data : []const u8 , decoder : anytype ) ! DecodeResult (if (T == u8 ) []const u8 else []T ) {
101+ const length = try decodeCompact (u32 , data );
102+ var offset = length .bytes_read ;
107103
108- if (data .len < end ) return error .InsufficientData ;
104+ if (T == u8 ) {
105+ // For strings, just copy the raw bytes
106+ const end = offset + length .value ;
107+ if (data .len < end ) return error .InsufficientData ;
108+
109+ const duped = try allocator .dupe (u8 , data [offset .. end ]);
110+ return .{
111+ .value = duped ,
112+ .bytes_read = end ,
113+ };
114+ } else {
115+ // For other types, decode each element individually
116+ var items = try allocator .alloc (T , length .value );
117+ errdefer allocator .free (items );
118+
119+ var i : usize = 0 ;
120+ while (i < length .value ) : (i += 1 ) {
121+ if (offset >= data .len ) return error .UnexpectedEndOfData ;
122+ // Use function parameter introspection to check the decoder signature
123+ const decoder_info = @typeInfo (@TypeOf (decoder ));
124+ const is_allocator_first_param = decoder_info .@"fn" .params .len == 2 and
125+ decoder_info .@"fn" .params [0 ].type orelse void == std .mem .Allocator ;
126+ const is_type_first_param = decoder_info .@"fn" .params .len == 3 and
127+ decoder_info .@"fn" .params [0 ].type orelse void == type ;
128+ const result = if (is_allocator_first_param )
129+ try decoder (allocator , data [offset .. ])
130+ else if (is_type_first_param )
131+ try decoder (T , allocator , data [offset .. ])
132+ else
133+ try decoder (data [offset .. ]);
134+ items [i ] = result .value ;
135+ offset += result .bytes_read ;
136+ }
109137
110- const duped = try allocator .dupe (u8 , data [start .. end ]);
111- return .{
112- .value = duped ,
113- .bytes_read = end ,
114- };
138+ return .{ .value = items , .bytes_read = offset };
139+ }
115140}
116141
117142fn decodeBool (data : []const u8 ) ! DecodeResult (bool ) {
@@ -148,31 +173,6 @@ fn decodeOption(comptime T: type, allocator: std.mem.Allocator, data: []const u8
148173 };
149174}
150175
151- fn decodeArray (comptime T : type , allocator : std.mem.Allocator , data : []const u8 , decoder : anytype ) ! DecodeResult ([]T ) {
152- const length = try decodeCompact (u32 , data );
153- var offset = length .bytes_read ;
154-
155- var items = try allocator .alloc (T , length .value );
156- errdefer allocator .free (items );
157-
158- var i : usize = 0 ;
159- while (i < length .value ) : (i += 1 ) {
160- if (offset >= data .len ) return error .UnexpectedEndOfData ;
161- // Use function parameter introspection to check if the first parameter is an allocator
162- const decoder_info = @typeInfo (@TypeOf (decoder ));
163- const is_allocator_first_param = decoder_info .@"fn" .params .len == 2 and
164- decoder_info .@"fn" .params [0 ].type orelse void == std .mem .Allocator ;
165- const result = if (is_allocator_first_param )
166- try decoder (allocator , data [offset .. ])
167- else
168- try decoder (data [offset .. ]);
169- items [i ] = result .value ;
170- offset += result .bytes_read ;
171- }
172-
173- return .{ .value = items , .bytes_read = offset };
174- }
175-
176176fn decodeUnsigned (comptime T : type , data : []const u8 ) ! DecodeResult (T ) {
177177 const size = @sizeOf (T );
178178 if (data .len < size ) return error .InsufficientData ;
0 commit comments