std: @Vector support for std.json.parse
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user