| ... | @@ -24,7 +24,7 @@ | ... | @@ -24,7 +24,7 @@ |
| 24 | const std = @import("std"); | 24 | const std = @import("std"); |
| 25 | const assert = std.debug.assert; | 25 | const assert = std.debug.assert; |
| 26 | const Writer = std.Io.Writer; | 26 | const Writer = std.Io.Writer; |
| 27 | const Serializer = std.zon.Serializer; | 27 | const Serializer = @import("Serializer.zig"); |
| 28 | | 28 | |
| 29 | pub const SerializeOptions = struct { | 29 | pub const SerializeOptions = struct { |
| 30 | /// If false, whitespace is omitted. Otherwise whitespace is emitted in standard Zig style. | 30 | /// If false, whitespace is omitted. Otherwise whitespace is emitted in standard Zig style. |
| ... | @@ -37,6 +37,8 @@ pub const SerializeOptions = struct { | ... | @@ -37,6 +37,8 @@ pub const SerializeOptions = struct { |
| 37 | /// If false, struct fields are not written if they are equal to their default value. Comparison | 37 | /// If false, struct fields are not written if they are equal to their default value. Comparison |
| 38 | /// is done by `std.meta.eql`. | 38 | /// is done by `std.meta.eql`. |
| 39 | emit_default_optional_fields: bool = true, | 39 | emit_default_optional_fields: bool = true, |
| | 40 | /// If true, non-ASCII unicode characters are escaped. |
| | 41 | escape_non_ascii: bool = false, |
| 40 | }; | 42 | }; |
| 41 | | 43 | |
| 42 | /// Serialize the given value as ZON. | 44 | /// Serialize the given value as ZON. |
| ... | @@ -51,6 +53,7 @@ pub fn serialize(val: anytype, options: SerializeOptions, writer: *Writer) Write | ... | @@ -51,6 +53,7 @@ pub fn serialize(val: anytype, options: SerializeOptions, writer: *Writer) Write |
| 51 | .emit_codepoint_literals = options.emit_codepoint_literals, | 53 | .emit_codepoint_literals = options.emit_codepoint_literals, |
| 52 | .emit_strings_as_containers = options.emit_strings_as_containers, | 54 | .emit_strings_as_containers = options.emit_strings_as_containers, |
| 53 | .emit_default_optional_fields = options.emit_default_optional_fields, | 55 | .emit_default_optional_fields = options.emit_default_optional_fields, |
| | 56 | .escape_non_ascii = options.escape_non_ascii, |
| 54 | }); | 57 | }); |
| 55 | } | 58 | } |
| 56 | | 59 | |
| ... | @@ -72,6 +75,7 @@ pub fn serializeMaxDepth( | ... | @@ -72,6 +75,7 @@ pub fn serializeMaxDepth( |
| 72 | .emit_codepoint_literals = options.emit_codepoint_literals, | 75 | .emit_codepoint_literals = options.emit_codepoint_literals, |
| 73 | .emit_strings_as_containers = options.emit_strings_as_containers, | 76 | .emit_strings_as_containers = options.emit_strings_as_containers, |
| 74 | .emit_default_optional_fields = options.emit_default_optional_fields, | 77 | .emit_default_optional_fields = options.emit_default_optional_fields, |
| | 78 | .escape_non_ascii = options.escape_non_ascii, |
| 75 | }, depth); | 79 | }, depth); |
| 76 | } | 80 | } |
| 77 | | 81 | |
| ... | @@ -91,6 +95,7 @@ pub fn serializeArbitraryDepth( | ... | @@ -91,6 +95,7 @@ pub fn serializeArbitraryDepth( |
| 91 | .emit_codepoint_literals = options.emit_codepoint_literals, | 95 | .emit_codepoint_literals = options.emit_codepoint_literals, |
| 92 | .emit_strings_as_containers = options.emit_strings_as_containers, | 96 | .emit_strings_as_containers = options.emit_strings_as_containers, |
| 93 | .emit_default_optional_fields = options.emit_default_optional_fields, | 97 | .emit_default_optional_fields = options.emit_default_optional_fields, |
| | 98 | .escape_non_ascii = options.escape_non_ascii, |
| 94 | }); | 99 | }); |
| 95 | } | 100 | } |
| 96 | | 101 | |
| ... | @@ -588,7 +593,7 @@ test "std.zon stringify utf8 codepoints" { | ... | @@ -588,7 +593,7 @@ test "std.zon stringify utf8 codepoints" { |
| 588 | try std.testing.expectEqualStrings("97", aw.written()); | 593 | try std.testing.expectEqualStrings("97", aw.written()); |
| 589 | aw.clearRetainingCapacity(); | 594 | aw.clearRetainingCapacity(); |
| 590 | | 595 | |
| 591 | try s.codePoint('a'); | 596 | try s.codePoint('a', .{}); |
| 592 | try std.testing.expectEqualStrings("'a'", aw.written()); | 597 | try std.testing.expectEqualStrings("'a'", aw.written()); |
| 593 | aw.clearRetainingCapacity(); | 598 | aw.clearRetainingCapacity(); |
| 594 | | 599 | |
| ... | @@ -609,7 +614,7 @@ test "std.zon stringify utf8 codepoints" { | ... | @@ -609,7 +614,7 @@ test "std.zon stringify utf8 codepoints" { |
| 609 | try std.testing.expectEqualStrings("10", aw.written()); | 614 | try std.testing.expectEqualStrings("10", aw.written()); |
| 610 | aw.clearRetainingCapacity(); | 615 | aw.clearRetainingCapacity(); |
| 611 | | 616 | |
| 612 | try s.codePoint('\n'); | 617 | try s.codePoint('\n', .{}); |
| 613 | try std.testing.expectEqualStrings("'\\n'", aw.written()); | 618 | try std.testing.expectEqualStrings("'\\n'", aw.written()); |
| 614 | aw.clearRetainingCapacity(); | 619 | aw.clearRetainingCapacity(); |
| 615 | | 620 | |
| ... | @@ -630,11 +635,11 @@ test "std.zon stringify utf8 codepoints" { | ... | @@ -630,11 +635,11 @@ test "std.zon stringify utf8 codepoints" { |
| 630 | try std.testing.expectEqualStrings("9889", aw.written()); | 635 | try std.testing.expectEqualStrings("9889", aw.written()); |
| 631 | aw.clearRetainingCapacity(); | 636 | aw.clearRetainingCapacity(); |
| 632 | | 637 | |
| 633 | try s.codePoint('⚡'); | 638 | try s.codePoint('⚡', .{ .escape_non_ascii = true }); |
| 634 | try std.testing.expectEqualStrings("'\\u{26a1}'", aw.written()); | 639 | try std.testing.expectEqualStrings("'\\u{26a1}'", aw.written()); |
| 635 | aw.clearRetainingCapacity(); | 640 | aw.clearRetainingCapacity(); |
| 636 | | 641 | |
| 637 | try s.value('⚡', .{ .emit_codepoint_literals = .always }); | 642 | try s.value('⚡', .{ .emit_codepoint_literals = .always, .escape_non_ascii = true }); |
| 638 | try std.testing.expectEqualStrings("'\\u{26a1}'", aw.written()); | 643 | try std.testing.expectEqualStrings("'\\u{26a1}'", aw.written()); |
| 639 | aw.clearRetainingCapacity(); | 644 | aw.clearRetainingCapacity(); |
| 640 | | 645 | |
| ... | @@ -647,8 +652,7 @@ test "std.zon stringify utf8 codepoints" { | ... | @@ -647,8 +652,7 @@ test "std.zon stringify utf8 codepoints" { |
| 647 | aw.clearRetainingCapacity(); | 652 | aw.clearRetainingCapacity(); |
| 648 | | 653 | |
| 649 | // Invalid codepoint | 654 | // Invalid codepoint |
| 650 | try s.codePoint(0x110000 + 1); | 655 | try std.testing.expectError(error.InvalidCodepoint, s.codePoint(0x110000 + 1, .{ .escape_non_ascii = true })); |
| 651 | try std.testing.expectEqualStrings("'\\u{110001}'", aw.written()); | | |
| 652 | aw.clearRetainingCapacity(); | 656 | aw.clearRetainingCapacity(); |
| 653 | | 657 | |
| 654 | try s.int(0x110000 + 1); | 658 | try s.int(0x110000 + 1); |
| ... | @@ -681,7 +685,7 @@ test "std.zon stringify utf8 codepoints" { | ... | @@ -681,7 +685,7 @@ test "std.zon stringify utf8 codepoints" { |
| 681 | aw.clearRetainingCapacity(); | 685 | aw.clearRetainingCapacity(); |
| 682 | | 686 | |
| 683 | // Make sure value options are passed to children | 687 | // Make sure value options are passed to children |
| 684 | try s.value(.{ .c = '⚡' }, .{ .emit_codepoint_literals = .always }); | 688 | try s.value(.{ .c = '⚡' }, .{ .emit_codepoint_literals = .always, .escape_non_ascii = true }); |
| 685 | try std.testing.expectEqualStrings(".{ .c = '\\u{26a1}' }", aw.written()); | 689 | try std.testing.expectEqualStrings(".{ .c = '\\u{26a1}' }", aw.written()); |
| 686 | aw.clearRetainingCapacity(); | 690 | aw.clearRetainingCapacity(); |
| 687 | | 691 | |
| ... | @@ -696,11 +700,11 @@ test "std.zon stringify strings" { | ... | @@ -696,11 +700,11 @@ test "std.zon stringify strings" { |
| 696 | defer aw.deinit(); | 700 | defer aw.deinit(); |
| 697 | | 701 | |
| 698 | // Minimal case | 702 | // Minimal case |
| 699 | try s.string("abc⚡\n"); | 703 | try s.string("abc⚡ÿ\n", .{ .escape_non_ascii = true }); |
| 700 | try std.testing.expectEqualStrings("\"abc\\xe2\\x9a\\xa1\\n\"", aw.written()); | 704 | try std.testing.expectEqualStrings("\"abc\\u{26a1}\\u{ff}\\n\"", aw.written()); |
| 701 | aw.clearRetainingCapacity(); | 705 | aw.clearRetainingCapacity(); |
| 702 | | 706 | |
| 703 | try s.tuple("abc⚡\n", .{}); | 707 | try s.tuple("abc⚡ÿ\n", .{}); |
| 704 | try std.testing.expectEqualStrings( | 708 | try std.testing.expectEqualStrings( |
| 705 | \\.{ | 709 | \\.{ |
| 706 | \\ 97, | 710 | \\ 97, |
| ... | @@ -709,16 +713,18 @@ test "std.zon stringify strings" { | ... | @@ -709,16 +713,18 @@ test "std.zon stringify strings" { |
| 709 | \\ 226, | 713 | \\ 226, |
| 710 | \\ 154, | 714 | \\ 154, |
| 711 | \\ 161, | 715 | \\ 161, |
| | 716 | \\ 195, |
| | 717 | \\ 191, |
| 712 | \\ 10, | 718 | \\ 10, |
| 713 | \\} | 719 | \\} |
| 714 | , aw.written()); | 720 | , aw.written()); |
| 715 | aw.clearRetainingCapacity(); | 721 | aw.clearRetainingCapacity(); |
| 716 | | 722 | |
| 717 | try s.value("abc⚡\n", .{}); | 723 | try s.value("abc⚡ÿ\n", .{ .escape_non_ascii = false }); |
| 718 | try std.testing.expectEqualStrings("\"abc\\xe2\\x9a\\xa1\\n\"", aw.written()); | 724 | try std.testing.expectEqualStrings("\"abc⚡ÿ\\n\"", aw.written()); |
| 719 | aw.clearRetainingCapacity(); | 725 | aw.clearRetainingCapacity(); |
| 720 | | 726 | |
| 721 | try s.value("abc⚡\n", .{ .emit_strings_as_containers = true }); | 727 | try s.value("abc⚡ÿ\n", .{ .emit_strings_as_containers = true }); |
| 722 | try std.testing.expectEqualStrings( | 728 | try std.testing.expectEqualStrings( |
| 723 | \\.{ | 729 | \\.{ |
| 724 | \\ 97, | 730 | \\ 97, |
| ... | @@ -727,6 +733,8 @@ test "std.zon stringify strings" { | ... | @@ -727,6 +733,8 @@ test "std.zon stringify strings" { |
| 727 | \\ 226, | 733 | \\ 226, |
| 728 | \\ 154, | 734 | \\ 154, |
| 729 | \\ 161, | 735 | \\ 161, |
| | 736 | \\ 195, |
| | 737 | \\ 191, |
| 730 | \\ 10, | 738 | \\ 10, |
| 731 | \\} | 739 | \\} |
| 732 | , aw.written()); | 740 | , aw.written()); |
| ... | @@ -816,7 +824,7 @@ test "std.zon stringify multiline strings" { | ... | @@ -816,7 +824,7 @@ test "std.zon stringify multiline strings" { |
| 816 | | 824 | |
| 817 | { | 825 | { |
| 818 | const str: []const u8 = &.{ 'a', '\r', 'c' }; | 826 | const str: []const u8 = &.{ 'a', '\r', 'c' }; |
| 819 | try s.string(str); | 827 | try s.string(str, .{ .escape_non_ascii = false }); |
| 820 | try std.testing.expectEqualStrings("\"a\\rc\"", aw.written()); | 828 | try std.testing.expectEqualStrings("\"a\\rc\"", aw.written()); |
| 821 | aw.clearRetainingCapacity(); | 829 | aw.clearRetainingCapacity(); |
| 822 | } | 830 | } |