Commit 61236c2aa1
lib/std/json/test.zig
@@ -2550,6 +2550,25 @@ test "parse into double recursive union definition" {
try testing.expectEqual(@as(i64, 58), r.values.array[0].array[0].integer);
}
+test "parse into vector" {
+ const options = ParseOptions{ .allocator = testing.allocator };
+ const T = struct {
+ vec_i32: @Vector(4, i32),
+ vec_f32: @Vector(2, f32),
+ };
+ var ts = TokenStream.init(
+ \\{
+ \\ "vec_f32": [1.5, 2.5],
+ \\ "vec_i32": [4, 5, 6, 7]
+ \\}
+ );
+ const r = try parse(T, &ts, options);
+ defer parseFree(T, r, options);
+ try testing.expectApproxEqAbs(@as(f32, 1.5), r.vec_f32[0], 0.0000001);
+ try testing.expectApproxEqAbs(@as(f32, 2.5), r.vec_f32[1], 0.0000001);
+ try testing.expectEqual(@Vector(4, i32){ 4, 5, 6, 7 }, r.vec_i32);
+}
+
test "json.parser.dynamic" {
var p = Parser.init(testing.allocator, false);
defer p.deinit();
lib/std/json.zig
@@ -1389,6 +1389,11 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ
UnescapeValidStringError ||
ParseInternalErrorImpl(arrayInfo.child, inferred_types ++ [_]type{T});
},
+ .Vector => |vecInfo| {
+ return error{ UnexpectedEndOfJson, UnexpectedToken, LengthMismatch } || TokenStream.Error ||
+ UnescapeValidStringError ||
+ ParseInternalErrorImpl(vecInfo.child, inferred_types ++ [_]type{T});
+ },
.Pointer => |ptrInfo| {
var errors = error{AllocatorRequired} || std.mem.Allocator.Error;
switch (ptrInfo.size) {
@@ -1408,6 +1413,35 @@ fn ParseInternalErrorImpl(comptime T: type, comptime inferred_types: []const typ
unreachable;
}
+fn parseInternalArray(
+ comptime T: type,
+ comptime Elt: type,
+ comptime arr_len: usize,
+ tokens: *TokenStream,
+ options: ParseOptions,
+) ParseInternalError(T)!T {
+ var r: T = undefined;
+ var i: usize = 0;
+ var child_options = options;
+ child_options.allow_trailing_data = true;
+ errdefer {
+ // Without the r.len check `r[i]` is not allowed
+ if (arr_len > 0) while (true) : (i -= 1) {
+ parseFree(Elt, r[i], options);
+ if (i == 0) break;
+ };
+ }
+ if (arr_len > 0) while (i < arr_len) : (i += 1) {
+ r[i] = try parse(Elt, tokens, child_options);
+ };
+ const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
+ switch (tok) {
+ .ArrayEnd => {},
+ else => return error.UnexpectedToken,
+ }
+ return r;
+}
+
fn parseInternal(
comptime T: type,
token: Token,
@@ -1624,26 +1658,8 @@ fn parseInternal(
.Array => |arrayInfo| {
switch (token) {
.ArrayBegin => {
- var r: T = undefined;
- var i: usize = 0;
- var child_options = options;
- child_options.allow_trailing_data = true;
- errdefer {
- // Without the r.len check `r[i]` is not allowed
- if (r.len > 0) while (true) : (i -= 1) {
- parseFree(arrayInfo.child, r[i], options);
- if (i == 0) break;
- };
- }
- while (i < r.len) : (i += 1) {
- r[i] = try parse(arrayInfo.child, tokens, child_options);
- }
- const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
- switch (tok) {
- .ArrayEnd => {},
- else => return error.UnexpectedToken,
- }
- return r;
+ const len = @typeInfo(T).Array.len;
+ return parseInternalArray(T, arrayInfo.child, len, tokens, options);
},
.String => |stringToken| {
if (arrayInfo.child != u8) return error.UnexpectedToken;
@@ -1659,6 +1675,15 @@ fn parseInternal(
else => return error.UnexpectedToken,
}
},
+ .Vector => |vecInfo| {
+ switch (token) {
+ .ArrayBegin => {
+ const len = @typeInfo(T).Vector.len;
+ return parseInternalArray(T, vecInfo.child, len, tokens, options);
+ },
+ else => return error.UnexpectedToken,
+ }
+ },
.Pointer => |ptrInfo| {
const allocator = options.allocator orelse return error.AllocatorRequired;
switch (ptrInfo.size) {
@@ -1804,6 +1829,13 @@ pub fn parseFree(comptime T: type, value: T, options: ParseOptions) void {
parseFree(arrayInfo.child, v, options);
}
},
+ .Vector => |vecInfo| {
+ var i: usize = 0;
+ var v_len: usize = @typeInfo(@TypeOf(value)).Vector.len;
+ while (i < v_len) : (i += 1) {
+ parseFree(vecInfo.child, value[i], options);
+ }
+ },
.Pointer => |ptrInfo| {
const allocator = options.allocator orelse unreachable;
switch (ptrInfo.size) {