| ... | @@ -2357,13 +2357,22 @@ pub const StringifyOptions = struct { | ... | @@ -2357,13 +2357,22 @@ pub const StringifyOptions = struct { |
| 2357 | /// Controls the whitespace emitted | 2357 | /// Controls the whitespace emitted |
| 2358 | whitespace: ?Whitespace = null, | 2358 | whitespace: ?Whitespace = null, |
| 2359 | | 2359 | |
| 2360 | /// Should '/' be escaped in strings? | 2360 | /// Should []u8 be serialised as a string? or an array? |
| 2361 | escape_solidus: bool = false, | 2361 | pub const StringOptions = union(enum) { |
| | 2362 | Array, |
| 2362 | | 2363 | |
| 2363 | /// Should unicode characters be escaped in strings? | 2364 | /// String output options |
| 2364 | escape_unicode: bool = false, | 2365 | const StringOutputOptions = struct { |
| | 2366 | /// Should '/' be escaped in strings? |
| | 2367 | escape_solidus: bool = false, |
| 2365 | | 2368 | |
| 2366 | // TODO: allow picking if []u8 is string or array? | 2369 | /// Should unicode characters be escaped in strings? |
| | 2370 | escape_unicode: bool = false, |
| | 2371 | }; |
| | 2372 | String: StringOutputOptions, |
| | 2373 | }; |
| | 2374 | |
| | 2375 | string: StringOptions = StringOptions{ .String = .{} }, |
| 2367 | }; | 2376 | }; |
| 2368 | | 2377 | |
| 2369 | fn outputUnicodeEscape( | 2378 | fn outputUnicodeEscape( |
| ... | @@ -2490,7 +2499,7 @@ pub fn stringify( | ... | @@ -2490,7 +2499,7 @@ pub fn stringify( |
| 2490 | }, | 2499 | }, |
| 2491 | // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) | 2500 | // TODO: .Many when there is a sentinel (waiting for https://github.com/ziglang/zig/pull/3972) |
| 2492 | .Slice => { | 2501 | .Slice => { |
| 2493 | if (ptr_info.child == u8 and std.unicode.utf8ValidateSlice(value)) { | 2502 | if (ptr_info.child == u8 and options.string == .String and std.unicode.utf8ValidateSlice(value)) { |
| 2494 | try out_stream.writeByte('\"'); | 2503 | try out_stream.writeByte('\"'); |
| 2495 | var i: usize = 0; | 2504 | var i: usize = 0; |
| 2496 | while (i < value.len) : (i += 1) { | 2505 | while (i < value.len) : (i += 1) { |
| ... | @@ -2502,7 +2511,7 @@ pub fn stringify( | ... | @@ -2502,7 +2511,7 @@ pub fn stringify( |
| 2502 | '\"' => try out_stream.writeAll("\\\""), | 2511 | '\"' => try out_stream.writeAll("\\\""), |
| 2503 | // solidus is optional to escape | 2512 | // solidus is optional to escape |
| 2504 | '/' => { | 2513 | '/' => { |
| 2505 | if (options.escape_solidus) { | 2514 | if (options.string.String.escape_solidus) { |
| 2506 | try out_stream.writeAll("\\/"); | 2515 | try out_stream.writeAll("\\/"); |
| 2507 | } else { | 2516 | } else { |
| 2508 | try out_stream.writeByte('\\'); | 2517 | try out_stream.writeByte('\\'); |
| ... | @@ -2518,7 +2527,7 @@ pub fn stringify( | ... | @@ -2518,7 +2527,7 @@ pub fn stringify( |
| 2518 | else => { | 2527 | else => { |
| 2519 | const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; | 2528 | const ulen = std.unicode.utf8ByteSequenceLength(value[i]) catch unreachable; |
| 2520 | // control characters (only things left with 1 byte length) should always be printed as unicode escapes | 2529 | // control characters (only things left with 1 byte length) should always be printed as unicode escapes |
| 2521 | if (ulen == 1 or options.escape_unicode) { | 2530 | if (ulen == 1 or options.string.String.escape_unicode) { |
| 2522 | const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable; | 2531 | const codepoint = std.unicode.utf8Decode(value[i .. i + ulen]) catch unreachable; |
| 2523 | try outputUnicodeEscape(codepoint, out_stream); | 2532 | try outputUnicodeEscape(codepoint, out_stream); |
| 2524 | } else { | 2533 | } else { |
| ... | @@ -2636,25 +2645,25 @@ test "stringify basic types" { | ... | @@ -2636,25 +2645,25 @@ test "stringify basic types" { |
| 2636 | test "stringify string" { | 2645 | test "stringify string" { |
| 2637 | try teststringify("\"hello\"", "hello", StringifyOptions{}); | 2646 | try teststringify("\"hello\"", "hello", StringifyOptions{}); |
| 2638 | try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r", StringifyOptions{}); | 2647 | try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r", StringifyOptions{}); |
| 2639 | try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r", StringifyOptions{ .escape_unicode = true }); | 2648 | try teststringify("\"with\\nescapes\\r\"", "with\nescapes\r", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2640 | try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}", StringifyOptions{}); | 2649 | try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}", StringifyOptions{}); |
| 2641 | try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}", StringifyOptions{ .escape_unicode = true }); | 2650 | try teststringify("\"with unicode\\u0001\"", "with unicode\u{1}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2642 | try teststringify("\"with unicode\u{80}\"", "with unicode\u{80}", StringifyOptions{}); | 2651 | try teststringify("\"with unicode\u{80}\"", "with unicode\u{80}", StringifyOptions{}); |
| 2643 | try teststringify("\"with unicode\\u0080\"", "with unicode\u{80}", StringifyOptions{ .escape_unicode = true }); | 2652 | try teststringify("\"with unicode\\u0080\"", "with unicode\u{80}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2644 | try teststringify("\"with unicode\u{FF}\"", "with unicode\u{FF}", StringifyOptions{}); | 2653 | try teststringify("\"with unicode\u{FF}\"", "with unicode\u{FF}", StringifyOptions{}); |
| 2645 | try teststringify("\"with unicode\\u00ff\"", "with unicode\u{FF}", StringifyOptions{ .escape_unicode = true }); | 2654 | try teststringify("\"with unicode\\u00ff\"", "with unicode\u{FF}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2646 | try teststringify("\"with unicode\u{100}\"", "with unicode\u{100}", StringifyOptions{}); | 2655 | try teststringify("\"with unicode\u{100}\"", "with unicode\u{100}", StringifyOptions{}); |
| 2647 | try teststringify("\"with unicode\\u0100\"", "with unicode\u{100}", StringifyOptions{ .escape_unicode = true }); | 2656 | try teststringify("\"with unicode\\u0100\"", "with unicode\u{100}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2648 | try teststringify("\"with unicode\u{800}\"", "with unicode\u{800}", StringifyOptions{}); | 2657 | try teststringify("\"with unicode\u{800}\"", "with unicode\u{800}", StringifyOptions{}); |
| 2649 | try teststringify("\"with unicode\\u0800\"", "with unicode\u{800}", StringifyOptions{ .escape_unicode = true }); | 2658 | try teststringify("\"with unicode\\u0800\"", "with unicode\u{800}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2650 | try teststringify("\"with unicode\u{8000}\"", "with unicode\u{8000}", StringifyOptions{}); | 2659 | try teststringify("\"with unicode\u{8000}\"", "with unicode\u{8000}", StringifyOptions{}); |
| 2651 | try teststringify("\"with unicode\\u8000\"", "with unicode\u{8000}", StringifyOptions{ .escape_unicode = true }); | 2660 | try teststringify("\"with unicode\\u8000\"", "with unicode\u{8000}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2652 | try teststringify("\"with unicode\u{D799}\"", "with unicode\u{D799}", StringifyOptions{}); | 2661 | try teststringify("\"with unicode\u{D799}\"", "with unicode\u{D799}", StringifyOptions{}); |
| 2653 | try teststringify("\"with unicode\\ud799\"", "with unicode\u{D799}", StringifyOptions{ .escape_unicode = true }); | 2662 | try teststringify("\"with unicode\\ud799\"", "with unicode\u{D799}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2654 | try teststringify("\"with unicode\u{10000}\"", "with unicode\u{10000}", StringifyOptions{}); | 2663 | try teststringify("\"with unicode\u{10000}\"", "with unicode\u{10000}", StringifyOptions{}); |
| 2655 | try teststringify("\"with unicode\\ud800\\udc00\"", "with unicode\u{10000}", StringifyOptions{ .escape_unicode = true }); | 2664 | try teststringify("\"with unicode\\ud800\\udc00\"", "with unicode\u{10000}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2656 | try teststringify("\"with unicode\u{10FFFF}\"", "with unicode\u{10FFFF}", StringifyOptions{}); | 2665 | try teststringify("\"with unicode\u{10FFFF}\"", "with unicode\u{10FFFF}", StringifyOptions{}); |
| 2657 | try teststringify("\"with unicode\\udbff\\udfff\"", "with unicode\u{10FFFF}", StringifyOptions{ .escape_unicode = true }); | 2666 | try teststringify("\"with unicode\\udbff\\udfff\"", "with unicode\u{10FFFF}", StringifyOptions{ .string = .{ .String = .{ .escape_unicode = true } } }); |
| 2658 | } | 2667 | } |
| 2659 | | 2668 | |
| 2660 | test "stringify tagged unions" { | 2669 | test "stringify tagged unions" { |