mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 21:38:33 +00:00
commit
cd3575b0f0
@ -1534,30 +1534,25 @@ fn parseInternal(
|
||||
child_options.allow_trailing_data = true;
|
||||
var found = false;
|
||||
inline for (structInfo.fields, 0..) |field, i| {
|
||||
// TODO: using switches here segfault the compiler (#2727?)
|
||||
if ((stringToken.escapes == .None and mem.eql(u8, field.name, key_source_slice)) or (stringToken.escapes == .Some and (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)))) {
|
||||
// if (switch (stringToken.escapes) {
|
||||
// .None => mem.eql(u8, field.name, key_source_slice),
|
||||
// .Some => (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)),
|
||||
// }) {
|
||||
if (switch (stringToken.escapes) {
|
||||
.None => mem.eql(u8, field.name, key_source_slice),
|
||||
.Some => (field.name.len == stringToken.decodedLength() and encodesTo(field.name, key_source_slice)),
|
||||
}) {
|
||||
if (fields_seen[i]) {
|
||||
// switch (options.duplicate_field_behavior) {
|
||||
// .UseFirst => {},
|
||||
// .Error => {},
|
||||
// .UseLast => {},
|
||||
// }
|
||||
if (options.duplicate_field_behavior == .UseFirst) {
|
||||
// unconditonally ignore value. for comptime fields, this skips check against default_value
|
||||
parseFree(field.type, try parse(field.type, tokens, child_options), child_options);
|
||||
found = true;
|
||||
break;
|
||||
} else if (options.duplicate_field_behavior == .Error) {
|
||||
return error.DuplicateJSONField;
|
||||
} else if (options.duplicate_field_behavior == .UseLast) {
|
||||
if (!field.is_comptime) {
|
||||
parseFree(field.type, @field(r, field.name), child_options);
|
||||
}
|
||||
fields_seen[i] = false;
|
||||
switch (options.duplicate_field_behavior) {
|
||||
.UseFirst => {
|
||||
// unconditonally ignore value. for comptime fields, this skips check against default_value
|
||||
parseFree(field.type, try parse(field.type, tokens, child_options), child_options);
|
||||
found = true;
|
||||
break;
|
||||
},
|
||||
.Error => return error.DuplicateJSONField,
|
||||
.UseLast => {
|
||||
if (!field.is_comptime) {
|
||||
parseFree(field.type, @field(r, field.name), child_options);
|
||||
}
|
||||
fields_seen[i] = false;
|
||||
},
|
||||
}
|
||||
}
|
||||
if (field.is_comptime) {
|
||||
@ -2355,10 +2350,13 @@ pub fn stringify(
|
||||
return stringify(value.*, options, out_stream);
|
||||
},
|
||||
},
|
||||
// TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)
|
||||
.Slice => {
|
||||
if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) {
|
||||
try encodeJsonString(value, options, out_stream);
|
||||
.Many, .Slice => {
|
||||
if (ptr_info.size == .Many and ptr_info.sentinel == null)
|
||||
@compileError("unable to stringify type '" ++ @typeName(T) ++ "' without sentinel");
|
||||
const slice = if (ptr_info.size == .Many) mem.span(value) else value;
|
||||
|
||||
if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(slice)) {
|
||||
try encodeJsonString(slice, options, out_stream);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2367,7 +2365,7 @@ pub fn stringify(
|
||||
if (child_options.whitespace) |*whitespace| {
|
||||
whitespace.indent_level += 1;
|
||||
}
|
||||
for (value, 0..) |x, i| {
|
||||
for (slice, 0..) |x, i| {
|
||||
if (i != 0) {
|
||||
try out_stream.writeByte(',');
|
||||
}
|
||||
@ -2376,7 +2374,7 @@ pub fn stringify(
|
||||
}
|
||||
try stringify(x, child_options, out_stream);
|
||||
}
|
||||
if (value.len != 0) {
|
||||
if (slice.len != 0) {
|
||||
if (options.whitespace) |whitespace| {
|
||||
try whitespace.outputIndent(out_stream);
|
||||
}
|
||||
@ -2531,6 +2529,12 @@ test "stringify string" {
|
||||
try teststringify("\"\\/\"", "/", StringifyOptions{ .string = .{ .String = .{ .escape_solidus = true } } });
|
||||
}
|
||||
|
||||
test "stringify many-item sentinel-terminated string" {
|
||||
try teststringify("\"hello\"", @as([*:0]const u8, "hello"), StringifyOptions{});
|
||||
try teststringify("\"with\\nescapes\\r\"", @as([*:0]const u8, "with\nescapes\r"), StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
||||
try teststringify("\"with unicode\\u0001\"", @as([*:0]const u8, "with unicode\u{1}"), StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
|
||||
}
|
||||
|
||||
test "stringify tagged unions" {
|
||||
try teststringify("42", union(enum) {
|
||||
Foo: u32,
|
||||
@ -2717,7 +2721,7 @@ test "encodesTo" {
|
||||
try testing.expectEqual(true, encodesTo("withąunicode😂", "with\\u0105unicode\\ud83d\\ude02"));
|
||||
}
|
||||
|
||||
test "issue 14600" {
|
||||
test "deserializing string with escape sequence into sentinel slice" {
|
||||
const json = "\"\\n\"";
|
||||
var token_stream = std.json.TokenStream.init(json);
|
||||
const options = ParseOptions{ .allocator = std.testing.allocator };
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user