mirror of
https://github.com/ziglang/zig.git
synced 2025-12-27 08:33:15 +00:00
std.json: support tuples
This commit is contained in:
parent
cd3575b0f0
commit
1e087d3a64
@ -1511,6 +1511,34 @@ fn parseInternal(
|
||||
}
|
||||
},
|
||||
.Struct => |structInfo| {
|
||||
if (structInfo.is_tuple) {
|
||||
switch (token) {
|
||||
.ArrayBegin => {},
|
||||
else => return error.UnexpectedToken,
|
||||
}
|
||||
var r: T = undefined;
|
||||
var child_options = options;
|
||||
child_options.allow_trailing_data = true;
|
||||
var fields_seen: usize = 0;
|
||||
errdefer {
|
||||
inline for (0..structInfo.fields.len) |i| {
|
||||
if (i < fields_seen) {
|
||||
parseFree(structInfo.fields[i].type, r[i], options);
|
||||
}
|
||||
}
|
||||
}
|
||||
inline for (0..structInfo.fields.len) |i| {
|
||||
r[i] = try parse(structInfo.fields[i].type, tokens, child_options);
|
||||
fields_seen = i + 1;
|
||||
}
|
||||
const tok = (try tokens.next()) orelse return error.UnexpectedEndOfJson;
|
||||
switch (tok) {
|
||||
.ArrayEnd => {},
|
||||
else => return error.UnexpectedToken,
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
switch (token) {
|
||||
.ObjectBegin => {},
|
||||
else => return error.UnexpectedToken,
|
||||
@ -2290,7 +2318,7 @@ pub fn stringify(
|
||||
return value.jsonStringify(options, out_stream);
|
||||
}
|
||||
|
||||
try out_stream.writeByte('{');
|
||||
try out_stream.writeByte(if (S.is_tuple) '[' else '{');
|
||||
var field_output = false;
|
||||
var child_options = options;
|
||||
if (child_options.whitespace) |*child_whitespace| {
|
||||
@ -2320,11 +2348,13 @@ pub fn stringify(
|
||||
if (child_options.whitespace) |child_whitespace| {
|
||||
try child_whitespace.outputIndent(out_stream);
|
||||
}
|
||||
try encodeJsonString(Field.name, options, out_stream);
|
||||
try out_stream.writeByte(':');
|
||||
if (child_options.whitespace) |child_whitespace| {
|
||||
if (child_whitespace.separator) {
|
||||
try out_stream.writeByte(' ');
|
||||
if (!S.is_tuple) {
|
||||
try encodeJsonString(Field.name, options, out_stream);
|
||||
try out_stream.writeByte(':');
|
||||
if (child_options.whitespace) |child_whitespace| {
|
||||
if (child_whitespace.separator) {
|
||||
try out_stream.writeByte(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
try stringify(@field(value, Field.name), child_options, out_stream);
|
||||
@ -2335,7 +2365,7 @@ pub fn stringify(
|
||||
try whitespace.outputIndent(out_stream);
|
||||
}
|
||||
}
|
||||
try out_stream.writeByte('}');
|
||||
try out_stream.writeByte(if (S.is_tuple) ']' else '}');
|
||||
return;
|
||||
},
|
||||
.ErrorSet => return stringify(@as([]const u8, @errorName(value)), options, out_stream),
|
||||
@ -2649,6 +2679,10 @@ test "stringify vector" {
|
||||
try teststringify("[1,1]", @splat(2, @as(u32, 1)), StringifyOptions{});
|
||||
}
|
||||
|
||||
test "stringify tuple" {
|
||||
try teststringify("[\"foo\",42]", std.meta.Tuple(&.{ []const u8, usize }){ "foo", 42 }, StringifyOptions{});
|
||||
}
|
||||
|
||||
fn teststringify(expected: []const u8, value: anytype, options: StringifyOptions) !void {
|
||||
const ValidationWriter = struct {
|
||||
const Self = @This();
|
||||
|
||||
@ -2459,6 +2459,56 @@ test "parse into struct ignoring unknown fields" {
|
||||
try testing.expectEqualSlices(u8, "zig", r.language);
|
||||
}
|
||||
|
||||
test "parse into tuple" {
|
||||
const options = ParseOptions{ .allocator = testing.allocator };
|
||||
const Union = union(enum) {
|
||||
char: u8,
|
||||
float: f64,
|
||||
string: []const u8,
|
||||
};
|
||||
const T = std.meta.Tuple(&.{
|
||||
i64,
|
||||
f64,
|
||||
bool,
|
||||
[]const u8,
|
||||
?bool,
|
||||
struct {
|
||||
foo: i32,
|
||||
bar: []const u8,
|
||||
},
|
||||
std.meta.Tuple(&.{ u8, []const u8, u8 }),
|
||||
Union,
|
||||
});
|
||||
var ts = TokenStream.init(
|
||||
\\[
|
||||
\\ 420,
|
||||
\\ 3.14,
|
||||
\\ true,
|
||||
\\ "zig",
|
||||
\\ null,
|
||||
\\ {
|
||||
\\ "foo": 1,
|
||||
\\ "bar": "zero"
|
||||
\\ },
|
||||
\\ [4, "två", 42],
|
||||
\\ 12.34
|
||||
\\]
|
||||
);
|
||||
const r = try parse(T, &ts, options);
|
||||
defer parseFree(T, r, options);
|
||||
try testing.expectEqual(@as(i64, 420), r[0]);
|
||||
try testing.expectEqual(@as(f64, 3.14), r[1]);
|
||||
try testing.expectEqual(true, r[2]);
|
||||
try testing.expectEqualSlices(u8, "zig", r[3]);
|
||||
try testing.expectEqual(@as(?bool, null), r[4]);
|
||||
try testing.expectEqual(@as(i32, 1), r[5].foo);
|
||||
try testing.expectEqualSlices(u8, "zero", r[5].bar);
|
||||
try testing.expectEqual(@as(u8, 4), r[6][0]);
|
||||
try testing.expectEqualSlices(u8, "två", r[6][1]);
|
||||
try testing.expectEqual(@as(u8, 42), r[6][2]);
|
||||
try testing.expectEqual(Union{ .float = 12.34 }, r[7]);
|
||||
}
|
||||
|
||||
const ParseIntoRecursiveUnionDefinitionValue = union(enum) {
|
||||
integer: i64,
|
||||
array: []const ParseIntoRecursiveUnionDefinitionValue,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user