authorgravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2023-03-08 19:26:03+01:00
committergravatar for r00ster91@proton.meWooster <r00ster91@proton.me> 2023-03-08 19:26:03+01:00
logc0789b4814989f2d91d3d2145d227dcdec3e2770
tree9df748fd5e898355d9d4b06ebc1dfe8e7f1f81eb
parent7e3591bedd41bde8bcca892885376e2f4a8163a3

std.json.stringify: support [*:0]const u8


1 files changed, 16 insertions(+), 7 deletions(-)

lib/std/json.zig+16-7
...@@ -2350,10 +2350,13 @@ pub fn stringify(...@@ -2350,10 +2350,13 @@ pub fn stringify(
2350 return stringify(value.*, options, out_stream);2350 return stringify(value.*, options, out_stream);
2351 },2351 },
2352 },2352 },
2353 // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972)2353 .Many, .Slice => {
2354 .Slice => {2354 if (ptr_info.size == .Many and ptr_info.sentinel == null)
2355 if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) {2355 @compileError("unable to stringify type '" ++ @typeName(T) ++ "' without sentinel");
2356 try encodeJsonString(value, options, out_stream);2356 const slice = if (ptr_info.size == .Many) mem.span(value) else value;
2357
2358 if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(slice)) {
2359 try encodeJsonString(slice, options, out_stream);
2357 return;2360 return;
2358 }2361 }
23592362
...@@ -2362,7 +2365,7 @@ pub fn stringify(...@@ -2362,7 +2365,7 @@ pub fn stringify(
2362 if (child_options.whitespace) |*whitespace| {2365 if (child_options.whitespace) |*whitespace| {
2363 whitespace.indent_level += 1;2366 whitespace.indent_level += 1;
2364 }2367 }
2365 for (value, 0..) |x, i| {2368 for (slice, 0..) |x, i| {
2366 if (i != 0) {2369 if (i != 0) {
2367 try out_stream.writeByte(',');2370 try out_stream.writeByte(',');
2368 }2371 }
...@@ -2371,7 +2374,7 @@ pub fn stringify(...@@ -2371,7 +2374,7 @@ pub fn stringify(
2371 }2374 }
2372 try stringify(x, child_options, out_stream);2375 try stringify(x, child_options, out_stream);
2373 }2376 }
2374 if (value.len != 0) {2377 if (slice.len != 0) {
2375 if (options.whitespace) |whitespace| {2378 if (options.whitespace) |whitespace| {
2376 try whitespace.outputIndent(out_stream);2379 try whitespace.outputIndent(out_stream);
2377 }2380 }
...@@ -2526,6 +2529,12 @@ test "stringify string" {...@@ -2526,6 +2529,12 @@ test "stringify string" {
2526 try teststringify("\"\\/\"", "/", StringifyOptions{ .string = .{ .String = .{ .escape_solidus = true } } });2529 try teststringify("\"\\/\"", "/", StringifyOptions{ .string = .{ .String = .{ .escape_solidus = true } } });
2527}2530}
25282531
2532test "stringify many-item sentinel-terminated string" {
2533 try teststringify("\"hello\"", @as([*:0]const u8, "hello"), StringifyOptions{});
2534 try teststringify("\"with\\nescapes\\r\"", @as([*:0]const u8, "with\nescapes\r"), StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
2535 try teststringify("\"with unicode\\u0001\"", @as([*:0]const u8, "with unicode\u{1}"), StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } });
2536}
2537
2529test "stringify tagged unions" {2538test "stringify tagged unions" {
2530 try teststringify("42", union(enum) {2539 try teststringify("42", union(enum) {
2531 Foo: u32,2540 Foo: u32,
...@@ -2712,7 +2721,7 @@ test "encodesTo" {...@@ -2712,7 +2721,7 @@ test "encodesTo" {
2712 try testing.expectEqual(true, encodesTo("withąunicode😂", "with\\u0105unicode\\ud83d\\ude02"));2721 try testing.expectEqual(true, encodesTo("withąunicode😂", "with\\u0105unicode\\ud83d\\ude02"));
2713}2722}
27142723
2715test "issue 14600" {2724test "deserializing string with escape sequence into sentinel slice" {
2716 const json = "\"\\n\"";2725 const json = "\"\\n\"";
2717 var token_stream = std.json.TokenStream.init(json);2726 var token_stream = std.json.TokenStream.init(json);
2718 const options = ParseOptions{ .allocator = std.testing.allocator };2727 const options = ParseOptions{ .allocator = std.testing.allocator };