authorgravatar for mason@anthropicstudios.comMason Remaley <mason@anthropicstudios.com> 2025-02-21 18:40:57-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-02-21 21:40:57-05:00
log339b628d4c8a850c6d819e88fb3b84b86e8b5927
treecb31173da17ada279298a0a37224fefed9024f02
parent65e7ede4994237f160e8db558e74da113f886f98
signaturebadge-check Signed by PGP key B5690EEEBB952194

Output `zig targets` as ZON instead of JSON (#22939)

* Adds startTupleField/startStructField, makes pattern in print targets less verbose * Makes some enums into strings * Start/finish renamed to begin/end I feel bad changing this, but I don't know why I named them this way in the first place. Begin/end is consistent with the json API, and with other APIs in the wild that follow this pattern. Better to change now than later.

2 files changed, 277 insertions(+), 189 deletions(-)

lib/std/zon/stringify.zig+196-88
...@@ -438,17 +438,17 @@ pub const SerializeContainerOptions = struct {...@@ -438,17 +438,17 @@ pub const SerializeContainerOptions = struct {
438/// * `multilineString`438/// * `multilineString`
439///439///
440/// For manual serialization of containers, see:440/// For manual serialization of containers, see:
441/// * `startStruct`441/// * `beginStruct`
442/// * `startTuple`442/// * `beginTuple`
443///443///
444/// # Example444/// # Example
445/// ```zig445/// ```zig
446/// var sz = serializer(writer, .{});446/// var sz = serializer(writer, .{});
447/// var vec2 = try sz.startStruct(.{});447/// var vec2 = try sz.beginStruct(.{});
448/// try vec2.field("x", 1.5, .{});448/// try vec2.field("x", 1.5, .{});
449/// try vec2.fieldPrefix();449/// try vec2.fieldPrefix();
450/// try sz.value(2.5);450/// try sz.value(2.5);
451/// try vec2.finish();451/// try vec2.end();
452/// ```452/// ```
453pub fn Serializer(Writer: type) type {453pub fn Serializer(Writer: type) type {
454 return struct {454 return struct {
...@@ -525,22 +525,22 @@ pub fn Serializer(Writer: type) type {...@@ -525,22 +525,22 @@ pub fn Serializer(Writer: type) type {
525 }525 }
526 },526 },
527 .array => {527 .array => {
528 var container = try self.startTuple(528 var container = try self.beginTuple(
529 .{ .whitespace_style = .{ .fields = val.len } },529 .{ .whitespace_style = .{ .fields = val.len } },
530 );530 );
531 for (val) |item_val| {531 for (val) |item_val| {
532 try container.fieldArbitraryDepth(item_val, options);532 try container.fieldArbitraryDepth(item_val, options);
533 }533 }
534 try container.finish();534 try container.end();
535 },535 },
536 .@"struct" => |@"struct"| if (@"struct".is_tuple) {536 .@"struct" => |@"struct"| if (@"struct".is_tuple) {
537 var container = try self.startTuple(537 var container = try self.beginTuple(
538 .{ .whitespace_style = .{ .fields = @"struct".fields.len } },538 .{ .whitespace_style = .{ .fields = @"struct".fields.len } },
539 );539 );
540 inline for (val) |field_value| {540 inline for (val) |field_value| {
541 try container.fieldArbitraryDepth(field_value, options);541 try container.fieldArbitraryDepth(field_value, options);
542 }542 }
543 try container.finish();543 try container.end();
544 } else {544 } else {
545 // Decide which fields to emit545 // Decide which fields to emit
546 const fields, const skipped: [@"struct".fields.len]bool = if (options.emit_default_optional_fields) b: {546 const fields, const skipped: [@"struct".fields.len]bool = if (options.emit_default_optional_fields) b: {
...@@ -562,7 +562,7 @@ pub fn Serializer(Writer: type) type {...@@ -562,7 +562,7 @@ pub fn Serializer(Writer: type) type {
562 };562 };
563563
564 // Emit those fields564 // Emit those fields
565 var container = try self.startStruct(565 var container = try self.beginStruct(
566 .{ .whitespace_style = .{ .fields = fields } },566 .{ .whitespace_style = .{ .fields = fields } },
567 );567 );
568 inline for (@"struct".fields, skipped) |field_info, skip| {568 inline for (@"struct".fields, skipped) |field_info, skip| {
...@@ -574,7 +574,7 @@ pub fn Serializer(Writer: type) type {...@@ -574,7 +574,7 @@ pub fn Serializer(Writer: type) type {
574 );574 );
575 }575 }
576 }576 }
577 try container.finish();577 try container.end();
578 },578 },
579 .@"union" => |@"union"| {579 .@"union" => |@"union"| {
580 comptime assert(@"union".tag_type != null);580 comptime assert(@"union".tag_type != null);
...@@ -582,7 +582,7 @@ pub fn Serializer(Writer: type) type {...@@ -582,7 +582,7 @@ pub fn Serializer(Writer: type) type {
582 inline else => |pl, tag| if (@TypeOf(pl) == void)582 inline else => |pl, tag| if (@TypeOf(pl) == void)
583 try self.writer.print(".{s}", .{@tagName(tag)})583 try self.writer.print(".{s}", .{@tagName(tag)})
584 else {584 else {
585 var container = try self.startStruct(.{ .whitespace_style = .{ .fields = 1 } });585 var container = try self.beginStruct(.{ .whitespace_style = .{ .fields = 1 } });
586586
587 try container.fieldArbitraryDepth(587 try container.fieldArbitraryDepth(
588 @tagName(tag),588 @tagName(tag),
...@@ -590,7 +590,7 @@ pub fn Serializer(Writer: type) type {...@@ -590,7 +590,7 @@ pub fn Serializer(Writer: type) type {
590 options,590 options,
591 );591 );
592592
593 try container.finish();593 try container.end();
594 },594 },
595 }595 }
596 },596 },
...@@ -600,13 +600,13 @@ pub fn Serializer(Writer: type) type {...@@ -600,13 +600,13 @@ pub fn Serializer(Writer: type) type {
600 try self.writer.writeAll("null");600 try self.writer.writeAll("null");
601 },601 },
602 .vector => |vector| {602 .vector => |vector| {
603 var container = try self.startTuple(603 var container = try self.beginTuple(
604 .{ .whitespace_style = .{ .fields = vector.len } },604 .{ .whitespace_style = .{ .fields = vector.len } },
605 );605 );
606 for (0..vector.len) |i| {606 for (0..vector.len) |i| {
607 try container.fieldArbitraryDepth(val[i], options);607 try container.fieldArbitraryDepth(val[i], options);
608 }608 }
609 try container.finish();609 try container.end();
610 },610 },
611611
612 else => comptime unreachable,612 else => comptime unreachable,
...@@ -691,18 +691,18 @@ pub fn Serializer(Writer: type) type {...@@ -691,18 +691,18 @@ pub fn Serializer(Writer: type) type {
691 comptime assert(canSerializeType(@TypeOf(val)));691 comptime assert(canSerializeType(@TypeOf(val)));
692 switch (@typeInfo(@TypeOf(val))) {692 switch (@typeInfo(@TypeOf(val))) {
693 .@"struct" => {693 .@"struct" => {
694 var container = try self.startTuple(.{ .whitespace_style = .{ .fields = val.len } });694 var container = try self.beginTuple(.{ .whitespace_style = .{ .fields = val.len } });
695 inline for (val) |item_val| {695 inline for (val) |item_val| {
696 try container.fieldArbitraryDepth(item_val, options);696 try container.fieldArbitraryDepth(item_val, options);
697 }697 }
698 try container.finish();698 try container.end();
699 },699 },
700 .pointer, .array => {700 .pointer, .array => {
701 var container = try self.startTuple(.{ .whitespace_style = .{ .fields = val.len } });701 var container = try self.beginTuple(.{ .whitespace_style = .{ .fields = val.len } });
702 for (val) |item_val| {702 for (val) |item_val| {
703 try container.fieldArbitraryDepth(item_val, options);703 try container.fieldArbitraryDepth(item_val, options);
704 }704 }
705 try container.finish();705 try container.end();
706 },706 },
707 else => comptime unreachable,707 else => comptime unreachable,
708 }708 }
...@@ -767,19 +767,19 @@ pub fn Serializer(Writer: type) type {...@@ -767,19 +767,19 @@ pub fn Serializer(Writer: type) type {
767 }767 }
768768
769 /// Create a `Struct` for writing ZON structs field by field.769 /// Create a `Struct` for writing ZON structs field by field.
770 pub fn startStruct(770 pub fn beginStruct(
771 self: *Self,771 self: *Self,
772 options: SerializeContainerOptions,772 options: SerializeContainerOptions,
773 ) Writer.Error!Struct {773 ) Writer.Error!Struct {
774 return Struct.start(self, options);774 return Struct.begin(self, options);
775 }775 }
776776
777 /// Creates a `Tuple` for writing ZON tuples field by field.777 /// Creates a `Tuple` for writing ZON tuples field by field.
778 pub fn startTuple(778 pub fn beginTuple(
779 self: *Self,779 self: *Self,
780 options: SerializeContainerOptions,780 options: SerializeContainerOptions,
781 ) Writer.Error!Tuple {781 ) Writer.Error!Tuple {
782 return Tuple.start(self, options);782 return Tuple.begin(self, options);
783 }783 }
784784
785 fn indent(self: *Self) Writer.Error!void {785 fn indent(self: *Self) Writer.Error!void {
...@@ -812,17 +812,17 @@ pub fn Serializer(Writer: type) type {...@@ -812,17 +812,17 @@ pub fn Serializer(Writer: type) type {
812 pub const Tuple = struct {812 pub const Tuple = struct {
813 container: Container,813 container: Container,
814814
815 fn start(parent: *Self, options: SerializeContainerOptions) Writer.Error!Tuple {815 fn begin(parent: *Self, options: SerializeContainerOptions) Writer.Error!Tuple {
816 return .{816 return .{
817 .container = try Container.start(parent, .anon, options),817 .container = try Container.begin(parent, .anon, options),
818 };818 };
819 }819 }
820820
821 /// Finishes serializing the tuple.821 /// Finishes serializing the tuple.
822 ///822 ///
823 /// Prints a trailing comma as configured when appropriate, and the closing bracket.823 /// Prints a trailing comma as configured when appropriate, and the closing bracket.
824 pub fn finish(self: *Tuple) Writer.Error!void {824 pub fn end(self: *Tuple) Writer.Error!void {
825 try self.container.finish();825 try self.container.end();
826 self.* = undefined;826 self.* = undefined;
827 }827 }
828828
...@@ -855,6 +855,24 @@ pub fn Serializer(Writer: type) type {...@@ -855,6 +855,24 @@ pub fn Serializer(Writer: type) type {
855 try self.container.fieldArbitraryDepth(null, val, options);855 try self.container.fieldArbitraryDepth(null, val, options);
856 }856 }
857857
858 /// Starts a field with a struct as a value. Returns the struct.
859 pub fn beginStructField(
860 self: *Tuple,
861 options: SerializeContainerOptions,
862 ) Writer.Error!Struct {
863 try self.fieldPrefix();
864 return self.container.serializer.beginStruct(options);
865 }
866
867 /// Starts a field with a tuple as a value. Returns the tuple.
868 pub fn beginTupleField(
869 self: *Tuple,
870 options: SerializeContainerOptions,
871 ) Writer.Error!Tuple {
872 try self.fieldPrefix();
873 return self.container.serializer.beginTuple(options);
874 }
875
858 /// Print a field prefix. This prints any necessary commas, and whitespace as876 /// Print a field prefix. This prints any necessary commas, and whitespace as
859 /// configured. Useful if you want to serialize the field value yourself.877 /// configured. Useful if you want to serialize the field value yourself.
860 pub fn fieldPrefix(self: *Tuple) Writer.Error!void {878 pub fn fieldPrefix(self: *Tuple) Writer.Error!void {
...@@ -866,17 +884,17 @@ pub fn Serializer(Writer: type) type {...@@ -866,17 +884,17 @@ pub fn Serializer(Writer: type) type {
866 pub const Struct = struct {884 pub const Struct = struct {
867 container: Container,885 container: Container,
868886
869 fn start(parent: *Self, options: SerializeContainerOptions) Writer.Error!Struct {887 fn begin(parent: *Self, options: SerializeContainerOptions) Writer.Error!Struct {
870 return .{888 return .{
871 .container = try Container.start(parent, .named, options),889 .container = try Container.begin(parent, .named, options),
872 };890 };
873 }891 }
874892
875 /// Finishes serializing the struct.893 /// Finishes serializing the struct.
876 ///894 ///
877 /// Prints a trailing comma as configured when appropriate, and the closing bracket.895 /// Prints a trailing comma as configured when appropriate, and the closing bracket.
878 pub fn finish(self: *Struct) Writer.Error!void {896 pub fn end(self: *Struct) Writer.Error!void {
879 try self.container.finish();897 try self.container.end();
880 self.* = undefined;898 self.* = undefined;
881 }899 }
882900
...@@ -912,6 +930,26 @@ pub fn Serializer(Writer: type) type {...@@ -912,6 +930,26 @@ pub fn Serializer(Writer: type) type {
912 try self.container.fieldArbitraryDepth(name, val, options);930 try self.container.fieldArbitraryDepth(name, val, options);
913 }931 }
914932
933 /// Starts a field with a struct as a value. Returns the struct.
934 pub fn beginStructField(
935 self: *Struct,
936 name: []const u8,
937 options: SerializeContainerOptions,
938 ) Writer.Error!Struct {
939 try self.fieldPrefix(name);
940 return self.container.serializer.beginStruct(options);
941 }
942
943 /// Starts a field with a tuple as a value. Returns the tuple.
944 pub fn beginTupleField(
945 self: *Struct,
946 name: []const u8,
947 options: SerializeContainerOptions,
948 ) Writer.Error!Tuple {
949 try self.fieldPrefix(name);
950 return self.container.serializer.beginTuple(options);
951 }
952
915 /// Print a field prefix. This prints any necessary commas, the field name (escaped if953 /// Print a field prefix. This prints any necessary commas, the field name (escaped if
916 /// necessary) and whitespace as configured. Useful if you want to serialize the field954 /// necessary) and whitespace as configured. Useful if you want to serialize the field
917 /// value yourself.955 /// value yourself.
...@@ -928,7 +966,7 @@ pub fn Serializer(Writer: type) type {...@@ -928,7 +966,7 @@ pub fn Serializer(Writer: type) type {
928 options: SerializeContainerOptions,966 options: SerializeContainerOptions,
929 empty: bool,967 empty: bool,
930968
931 fn start(969 fn begin(
932 sz: *Self,970 sz: *Self,
933 field_style: FieldStyle,971 field_style: FieldStyle,
934 options: SerializeContainerOptions,972 options: SerializeContainerOptions,
...@@ -943,7 +981,7 @@ pub fn Serializer(Writer: type) type {...@@ -943,7 +981,7 @@ pub fn Serializer(Writer: type) type {
943 };981 };
944 }982 }
945983
946 fn finish(self: *Container) Writer.Error!void {984 fn end(self: *Container) Writer.Error!void {
947 if (self.options.shouldWrap()) self.serializer.indent_level -|= 1;985 if (self.options.shouldWrap()) self.serializer.indent_level -|= 1;
948 if (!self.empty) {986 if (!self.empty) {
949 if (self.options.shouldWrap()) {987 if (self.options.shouldWrap()) {
...@@ -1139,52 +1177,52 @@ test "std.zon stringify whitespace, low level API" {...@@ -1139,52 +1177,52 @@ test "std.zon stringify whitespace, low level API" {
11391177
1140 // Empty containers1178 // Empty containers
1141 {1179 {
1142 var container = try sz.startStruct(.{});1180 var container = try sz.beginStruct(.{});
1143 try container.finish();1181 try container.end();
1144 try std.testing.expectEqualStrings(".{}", buf.items);1182 try std.testing.expectEqualStrings(".{}", buf.items);
1145 buf.clearRetainingCapacity();1183 buf.clearRetainingCapacity();
1146 }1184 }
11471185
1148 {1186 {
1149 var container = try sz.startTuple(.{});1187 var container = try sz.beginTuple(.{});
1150 try container.finish();1188 try container.end();
1151 try std.testing.expectEqualStrings(".{}", buf.items);1189 try std.testing.expectEqualStrings(".{}", buf.items);
1152 buf.clearRetainingCapacity();1190 buf.clearRetainingCapacity();
1153 }1191 }
11541192
1155 {1193 {
1156 var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });1194 var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
1157 try container.finish();1195 try container.end();
1158 try std.testing.expectEqualStrings(".{}", buf.items);1196 try std.testing.expectEqualStrings(".{}", buf.items);
1159 buf.clearRetainingCapacity();1197 buf.clearRetainingCapacity();
1160 }1198 }
11611199
1162 {1200 {
1163 var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });1201 var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
1164 try container.finish();1202 try container.end();
1165 try std.testing.expectEqualStrings(".{}", buf.items);1203 try std.testing.expectEqualStrings(".{}", buf.items);
1166 buf.clearRetainingCapacity();1204 buf.clearRetainingCapacity();
1167 }1205 }
11681206
1169 {1207 {
1170 var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 0 } });1208 var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 0 } });
1171 try container.finish();1209 try container.end();
1172 try std.testing.expectEqualStrings(".{}", buf.items);1210 try std.testing.expectEqualStrings(".{}", buf.items);
1173 buf.clearRetainingCapacity();1211 buf.clearRetainingCapacity();
1174 }1212 }
11751213
1176 {1214 {
1177 var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 0 } });1215 var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 0 } });
1178 try container.finish();1216 try container.end();
1179 try std.testing.expectEqualStrings(".{}", buf.items);1217 try std.testing.expectEqualStrings(".{}", buf.items);
1180 buf.clearRetainingCapacity();1218 buf.clearRetainingCapacity();
1181 }1219 }
11821220
1183 // Size 11221 // Size 1
1184 {1222 {
1185 var container = try sz.startStruct(.{});1223 var container = try sz.beginStruct(.{});
1186 try container.field("a", 1, .{});1224 try container.field("a", 1, .{});
1187 try container.finish();1225 try container.end();
1188 if (whitespace) {1226 if (whitespace) {
1189 try std.testing.expectEqualStrings(1227 try std.testing.expectEqualStrings(
1190 \\.{1228 \\.{
...@@ -1198,9 +1236,9 @@ test "std.zon stringify whitespace, low level API" {...@@ -1198,9 +1236,9 @@ test "std.zon stringify whitespace, low level API" {
1198 }1236 }
11991237
1200 {1238 {
1201 var container = try sz.startTuple(.{});1239 var container = try sz.beginTuple(.{});
1202 try container.field(1, .{});1240 try container.field(1, .{});
1203 try container.finish();1241 try container.end();
1204 if (whitespace) {1242 if (whitespace) {
1205 try std.testing.expectEqualStrings(1243 try std.testing.expectEqualStrings(
1206 \\.{1244 \\.{
...@@ -1214,9 +1252,9 @@ test "std.zon stringify whitespace, low level API" {...@@ -1214,9 +1252,9 @@ test "std.zon stringify whitespace, low level API" {
1214 }1252 }
12151253
1216 {1254 {
1217 var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });1255 var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
1218 try container.field("a", 1, .{});1256 try container.field("a", 1, .{});
1219 try container.finish();1257 try container.end();
1220 if (whitespace) {1258 if (whitespace) {
1221 try std.testing.expectEqualStrings(".{ .a = 1 }", buf.items);1259 try std.testing.expectEqualStrings(".{ .a = 1 }", buf.items);
1222 } else {1260 } else {
...@@ -1228,9 +1266,9 @@ test "std.zon stringify whitespace, low level API" {...@@ -1228,9 +1266,9 @@ test "std.zon stringify whitespace, low level API" {
1228 {1266 {
1229 // We get extra spaces here, since we didn't know up front that there would only be one1267 // We get extra spaces here, since we didn't know up front that there would only be one
1230 // field.1268 // field.
1231 var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });1269 var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
1232 try container.field(1, .{});1270 try container.field(1, .{});
1233 try container.finish();1271 try container.end();
1234 if (whitespace) {1272 if (whitespace) {
1235 try std.testing.expectEqualStrings(".{ 1 }", buf.items);1273 try std.testing.expectEqualStrings(".{ 1 }", buf.items);
1236 } else {1274 } else {
...@@ -1240,9 +1278,9 @@ test "std.zon stringify whitespace, low level API" {...@@ -1240,9 +1278,9 @@ test "std.zon stringify whitespace, low level API" {
1240 }1278 }
12411279
1242 {1280 {
1243 var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 1 } });1281 var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 1 } });
1244 try container.field("a", 1, .{});1282 try container.field("a", 1, .{});
1245 try container.finish();1283 try container.end();
1246 if (whitespace) {1284 if (whitespace) {
1247 try std.testing.expectEqualStrings(".{ .a = 1 }", buf.items);1285 try std.testing.expectEqualStrings(".{ .a = 1 }", buf.items);
1248 } else {1286 } else {
...@@ -1252,19 +1290,19 @@ test "std.zon stringify whitespace, low level API" {...@@ -1252,19 +1290,19 @@ test "std.zon stringify whitespace, low level API" {
1252 }1290 }
12531291
1254 {1292 {
1255 var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 1 } });1293 var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 1 } });
1256 try container.field(1, .{});1294 try container.field(1, .{});
1257 try container.finish();1295 try container.end();
1258 try std.testing.expectEqualStrings(".{1}", buf.items);1296 try std.testing.expectEqualStrings(".{1}", buf.items);
1259 buf.clearRetainingCapacity();1297 buf.clearRetainingCapacity();
1260 }1298 }
12611299
1262 // Size 21300 // Size 2
1263 {1301 {
1264 var container = try sz.startStruct(.{});1302 var container = try sz.beginStruct(.{});
1265 try container.field("a", 1, .{});1303 try container.field("a", 1, .{});
1266 try container.field("b", 2, .{});1304 try container.field("b", 2, .{});
1267 try container.finish();1305 try container.end();
1268 if (whitespace) {1306 if (whitespace) {
1269 try std.testing.expectEqualStrings(1307 try std.testing.expectEqualStrings(
1270 \\.{1308 \\.{
...@@ -1279,10 +1317,10 @@ test "std.zon stringify whitespace, low level API" {...@@ -1279,10 +1317,10 @@ test "std.zon stringify whitespace, low level API" {
1279 }1317 }
12801318
1281 {1319 {
1282 var container = try sz.startTuple(.{});1320 var container = try sz.beginTuple(.{});
1283 try container.field(1, .{});1321 try container.field(1, .{});
1284 try container.field(2, .{});1322 try container.field(2, .{});
1285 try container.finish();1323 try container.end();
1286 if (whitespace) {1324 if (whitespace) {
1287 try std.testing.expectEqualStrings(1325 try std.testing.expectEqualStrings(
1288 \\.{1326 \\.{
...@@ -1297,10 +1335,10 @@ test "std.zon stringify whitespace, low level API" {...@@ -1297,10 +1335,10 @@ test "std.zon stringify whitespace, low level API" {
1297 }1335 }
12981336
1299 {1337 {
1300 var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });1338 var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
1301 try container.field("a", 1, .{});1339 try container.field("a", 1, .{});
1302 try container.field("b", 2, .{});1340 try container.field("b", 2, .{});
1303 try container.finish();1341 try container.end();
1304 if (whitespace) {1342 if (whitespace) {
1305 try std.testing.expectEqualStrings(".{ .a = 1, .b = 2 }", buf.items);1343 try std.testing.expectEqualStrings(".{ .a = 1, .b = 2 }", buf.items);
1306 } else {1344 } else {
...@@ -1310,10 +1348,10 @@ test "std.zon stringify whitespace, low level API" {...@@ -1310,10 +1348,10 @@ test "std.zon stringify whitespace, low level API" {
1310 }1348 }
13111349
1312 {1350 {
1313 var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });1351 var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
1314 try container.field(1, .{});1352 try container.field(1, .{});
1315 try container.field(2, .{});1353 try container.field(2, .{});
1316 try container.finish();1354 try container.end();
1317 if (whitespace) {1355 if (whitespace) {
1318 try std.testing.expectEqualStrings(".{ 1, 2 }", buf.items);1356 try std.testing.expectEqualStrings(".{ 1, 2 }", buf.items);
1319 } else {1357 } else {
...@@ -1323,10 +1361,10 @@ test "std.zon stringify whitespace, low level API" {...@@ -1323,10 +1361,10 @@ test "std.zon stringify whitespace, low level API" {
1323 }1361 }
13241362
1325 {1363 {
1326 var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 2 } });1364 var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 2 } });
1327 try container.field("a", 1, .{});1365 try container.field("a", 1, .{});
1328 try container.field("b", 2, .{});1366 try container.field("b", 2, .{});
1329 try container.finish();1367 try container.end();
1330 if (whitespace) {1368 if (whitespace) {
1331 try std.testing.expectEqualStrings(".{ .a = 1, .b = 2 }", buf.items);1369 try std.testing.expectEqualStrings(".{ .a = 1, .b = 2 }", buf.items);
1332 } else {1370 } else {
...@@ -1336,10 +1374,10 @@ test "std.zon stringify whitespace, low level API" {...@@ -1336,10 +1374,10 @@ test "std.zon stringify whitespace, low level API" {
1336 }1374 }
13371375
1338 {1376 {
1339 var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 2 } });1377 var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 2 } });
1340 try container.field(1, .{});1378 try container.field(1, .{});
1341 try container.field(2, .{});1379 try container.field(2, .{});
1342 try container.finish();1380 try container.end();
1343 if (whitespace) {1381 if (whitespace) {
1344 try std.testing.expectEqualStrings(".{ 1, 2 }", buf.items);1382 try std.testing.expectEqualStrings(".{ 1, 2 }", buf.items);
1345 } else {1383 } else {
...@@ -1350,11 +1388,11 @@ test "std.zon stringify whitespace, low level API" {...@@ -1350,11 +1388,11 @@ test "std.zon stringify whitespace, low level API" {
13501388
1351 // Size 31389 // Size 3
1352 {1390 {
1353 var container = try sz.startStruct(.{});1391 var container = try sz.beginStruct(.{});
1354 try container.field("a", 1, .{});1392 try container.field("a", 1, .{});
1355 try container.field("b", 2, .{});1393 try container.field("b", 2, .{});
1356 try container.field("c", 3, .{});1394 try container.field("c", 3, .{});
1357 try container.finish();1395 try container.end();
1358 if (whitespace) {1396 if (whitespace) {
1359 try std.testing.expectEqualStrings(1397 try std.testing.expectEqualStrings(
1360 \\.{1398 \\.{
...@@ -1370,11 +1408,11 @@ test "std.zon stringify whitespace, low level API" {...@@ -1370,11 +1408,11 @@ test "std.zon stringify whitespace, low level API" {
1370 }1408 }
13711409
1372 {1410 {
1373 var container = try sz.startTuple(.{});1411 var container = try sz.beginTuple(.{});
1374 try container.field(1, .{});1412 try container.field(1, .{});
1375 try container.field(2, .{});1413 try container.field(2, .{});
1376 try container.field(3, .{});1414 try container.field(3, .{});
1377 try container.finish();1415 try container.end();
1378 if (whitespace) {1416 if (whitespace) {
1379 try std.testing.expectEqualStrings(1417 try std.testing.expectEqualStrings(
1380 \\.{1418 \\.{
...@@ -1390,11 +1428,11 @@ test "std.zon stringify whitespace, low level API" {...@@ -1390,11 +1428,11 @@ test "std.zon stringify whitespace, low level API" {
1390 }1428 }
13911429
1392 {1430 {
1393 var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });1431 var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
1394 try container.field("a", 1, .{});1432 try container.field("a", 1, .{});
1395 try container.field("b", 2, .{});1433 try container.field("b", 2, .{});
1396 try container.field("c", 3, .{});1434 try container.field("c", 3, .{});
1397 try container.finish();1435 try container.end();
1398 if (whitespace) {1436 if (whitespace) {
1399 try std.testing.expectEqualStrings(".{ .a = 1, .b = 2, .c = 3 }", buf.items);1437 try std.testing.expectEqualStrings(".{ .a = 1, .b = 2, .c = 3 }", buf.items);
1400 } else {1438 } else {
...@@ -1404,11 +1442,11 @@ test "std.zon stringify whitespace, low level API" {...@@ -1404,11 +1442,11 @@ test "std.zon stringify whitespace, low level API" {
1404 }1442 }
14051443
1406 {1444 {
1407 var container = try sz.startTuple(.{ .whitespace_style = .{ .wrap = false } });1445 var container = try sz.beginTuple(.{ .whitespace_style = .{ .wrap = false } });
1408 try container.field(1, .{});1446 try container.field(1, .{});
1409 try container.field(2, .{});1447 try container.field(2, .{});
1410 try container.field(3, .{});1448 try container.field(3, .{});
1411 try container.finish();1449 try container.end();
1412 if (whitespace) {1450 if (whitespace) {
1413 try std.testing.expectEqualStrings(".{ 1, 2, 3 }", buf.items);1451 try std.testing.expectEqualStrings(".{ 1, 2, 3 }", buf.items);
1414 } else {1452 } else {
...@@ -1418,11 +1456,11 @@ test "std.zon stringify whitespace, low level API" {...@@ -1418,11 +1456,11 @@ test "std.zon stringify whitespace, low level API" {
1418 }1456 }
14191457
1420 {1458 {
1421 var container = try sz.startStruct(.{ .whitespace_style = .{ .fields = 3 } });1459 var container = try sz.beginStruct(.{ .whitespace_style = .{ .fields = 3 } });
1422 try container.field("a", 1, .{});1460 try container.field("a", 1, .{});
1423 try container.field("b", 2, .{});1461 try container.field("b", 2, .{});
1424 try container.field("c", 3, .{});1462 try container.field("c", 3, .{});
1425 try container.finish();1463 try container.end();
1426 if (whitespace) {1464 if (whitespace) {
1427 try std.testing.expectEqualStrings(1465 try std.testing.expectEqualStrings(
1428 \\.{1466 \\.{
...@@ -1438,11 +1476,11 @@ test "std.zon stringify whitespace, low level API" {...@@ -1438,11 +1476,11 @@ test "std.zon stringify whitespace, low level API" {
1438 }1476 }
14391477
1440 {1478 {
1441 var container = try sz.startTuple(.{ .whitespace_style = .{ .fields = 3 } });1479 var container = try sz.beginTuple(.{ .whitespace_style = .{ .fields = 3 } });
1442 try container.field(1, .{});1480 try container.field(1, .{});
1443 try container.field(2, .{});1481 try container.field(2, .{});
1444 try container.field(3, .{});1482 try container.field(3, .{});
1445 try container.finish();1483 try container.end();
1446 if (whitespace) {1484 if (whitespace) {
1447 try std.testing.expectEqualStrings(1485 try std.testing.expectEqualStrings(
1448 \\.{1486 \\.{
...@@ -1459,10 +1497,10 @@ test "std.zon stringify whitespace, low level API" {...@@ -1459,10 +1497,10 @@ test "std.zon stringify whitespace, low level API" {
14591497
1460 // Nested objects where the outer container doesn't wrap but the inner containers do1498 // Nested objects where the outer container doesn't wrap but the inner containers do
1461 {1499 {
1462 var container = try sz.startStruct(.{ .whitespace_style = .{ .wrap = false } });1500 var container = try sz.beginStruct(.{ .whitespace_style = .{ .wrap = false } });
1463 try container.field("first", .{ 1, 2, 3 }, .{});1501 try container.field("first", .{ 1, 2, 3 }, .{});
1464 try container.field("second", .{ 4, 5, 6 }, .{});1502 try container.field("second", .{ 4, 5, 6 }, .{});
1465 try container.finish();1503 try container.end();
1466 if (whitespace) {1504 if (whitespace) {
1467 try std.testing.expectEqualStrings(1505 try std.testing.expectEqualStrings(
1468 \\.{ .first = .{1506 \\.{ .first = .{
...@@ -2016,26 +2054,26 @@ test "std.zon depth limits" {...@@ -2016,26 +2054,26 @@ test "std.zon depth limits" {
2016 try sz.value(3, .{});2054 try sz.value(3, .{});
2017 try sz.valueArbitraryDepth(maybe_recurse, .{});2055 try sz.valueArbitraryDepth(maybe_recurse, .{});
20182056
2019 var s = try sz.startStruct(.{});2057 var s = try sz.beginStruct(.{});
2020 try std.testing.expectError(error.ExceededMaxDepth, s.fieldMaxDepth("a", 1, .{}, 0));2058 try std.testing.expectError(error.ExceededMaxDepth, s.fieldMaxDepth("a", 1, .{}, 0));
2021 try s.fieldMaxDepth("b", 4, .{}, 1);2059 try s.fieldMaxDepth("b", 4, .{}, 1);
2022 try s.field("c", 5, .{});2060 try s.field("c", 5, .{});
2023 try s.fieldArbitraryDepth("d", maybe_recurse, .{});2061 try s.fieldArbitraryDepth("d", maybe_recurse, .{});
2024 try s.finish();2062 try s.end();
20252063
2026 var t = try sz.startTuple(.{});2064 var t = try sz.beginTuple(.{});
2027 try std.testing.expectError(error.ExceededMaxDepth, t.fieldMaxDepth(1, .{}, 0));2065 try std.testing.expectError(error.ExceededMaxDepth, t.fieldMaxDepth(1, .{}, 0));
2028 try t.fieldMaxDepth(6, .{}, 1);2066 try t.fieldMaxDepth(6, .{}, 1);
2029 try t.field(7, .{});2067 try t.field(7, .{});
2030 try t.fieldArbitraryDepth(maybe_recurse, .{});2068 try t.fieldArbitraryDepth(maybe_recurse, .{});
2031 try t.finish();2069 try t.end();
20322070
2033 var a = try sz.startTuple(.{});2071 var a = try sz.beginTuple(.{});
2034 try std.testing.expectError(error.ExceededMaxDepth, a.fieldMaxDepth(1, .{}, 0));2072 try std.testing.expectError(error.ExceededMaxDepth, a.fieldMaxDepth(1, .{}, 0));
2035 try a.fieldMaxDepth(8, .{}, 1);2073 try a.fieldMaxDepth(8, .{}, 1);
2036 try a.field(9, .{});2074 try a.field(9, .{});
2037 try a.fieldArbitraryDepth(maybe_recurse, .{});2075 try a.fieldArbitraryDepth(maybe_recurse, .{});
2038 try a.finish();2076 try a.end();
20392077
2040 try std.testing.expectEqualStrings(2078 try std.testing.expectEqualStrings(
2041 \\23.{}.{2079 \\23.{}.{
...@@ -2315,3 +2353,73 @@ test "std.zon pointers" {...@@ -2315,3 +2353,73 @@ test "std.zon pointers" {
2315 , val, .{});2353 , val, .{});
2316 }2354 }
2317}2355}
2356
2357test "std.zon tuple/struct field" {
2358 var buf = std.ArrayList(u8).init(std.testing.allocator);
2359 defer buf.deinit();
2360 var sz = serializer(buf.writer(), .{});
2361
2362 // Test on structs
2363 {
2364 var root = try sz.beginStruct(.{});
2365 {
2366 var tuple = try root.beginTupleField("foo", .{});
2367 try tuple.field(0, .{});
2368 try tuple.field(1, .{});
2369 try tuple.end();
2370 }
2371 {
2372 var strct = try root.beginStructField("bar", .{});
2373 try strct.field("a", 0, .{});
2374 try strct.field("b", 1, .{});
2375 try strct.end();
2376 }
2377 try root.end();
2378
2379 try std.testing.expectEqualStrings(
2380 \\.{
2381 \\ .foo = .{
2382 \\ 0,
2383 \\ 1,
2384 \\ },
2385 \\ .bar = .{
2386 \\ .a = 0,
2387 \\ .b = 1,
2388 \\ },
2389 \\}
2390 , buf.items);
2391 buf.clearRetainingCapacity();
2392 }
2393
2394 // Test on tuples
2395 {
2396 var root = try sz.beginTuple(.{});
2397 {
2398 var tuple = try root.beginTupleField(.{});
2399 try tuple.field(0, .{});
2400 try tuple.field(1, .{});
2401 try tuple.end();
2402 }
2403 {
2404 var strct = try root.beginStructField(.{});
2405 try strct.field("a", 0, .{});
2406 try strct.field("b", 1, .{});
2407 try strct.end();
2408 }
2409 try root.end();
2410
2411 try std.testing.expectEqualStrings(
2412 \\.{
2413 \\ .{
2414 \\ 0,
2415 \\ 1,
2416 \\ },
2417 \\ .{
2418 \\ .a = 0,
2419 \\ .b = 1,
2420 \\ },
2421 \\}
2422 , buf.items);
2423 buf.clearRetainingCapacity();
2424 }
2425}
src/print_targets.zig+81-101
...@@ -40,121 +40,101 @@ pub fn cmdTargets(...@@ -40,121 +40,101 @@ pub fn cmdTargets(
4040
41 var bw = io.bufferedWriter(stdout);41 var bw = io.bufferedWriter(stdout);
42 const w = bw.writer();42 const w = bw.writer();
43 var jws = std.json.writeStream(w, .{ .whitespace = .indent_1 });43 var sz = std.zon.stringify.serializer(w, .{});
4444
45 try jws.beginObject();45 {
4646 var root_obj = try sz.beginStruct(.{});
47 try jws.objectField("arch");
48 try jws.beginArray();
49 for (meta.fieldNames(Target.Cpu.Arch)) |field| {
50 try jws.write(field);
51 }
52 try jws.endArray();
5347
54 try jws.objectField("os");48 try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{});
55 try jws.beginArray();49 try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{});
56 for (meta.fieldNames(Target.Os.Tag)) |field| {50 try root_obj.field("abi", meta.fieldNames(Target.Abi), .{});
57 try jws.write(field);
58 }
59 try jws.endArray();
6051
61 try jws.objectField("abi");52 {
62 try jws.beginArray();53 var libc_obj = try root_obj.beginTupleField("libc", .{});
63 for (meta.fieldNames(Target.Abi)) |field| {54 for (std.zig.target.available_libcs) |libc| {
64 try jws.write(field);55 const tmp = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{
65 }56 @tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
66 try jws.endArray();57 });
6758 defer allocator.free(tmp);
68 try jws.objectField("libc");59 try libc_obj.field(tmp, .{});
69 try jws.beginArray();
70 for (std.zig.target.available_libcs) |libc| {
71 const tmp = try std.fmt.allocPrint(allocator, "{s}-{s}-{s}", .{
72 @tagName(libc.arch), @tagName(libc.os), @tagName(libc.abi),
73 });
74 defer allocator.free(tmp);
75 try jws.write(tmp);
76 }
77 try jws.endArray();
78
79 try jws.objectField("glibc");
80 try jws.beginArray();
81 for (glibc_abi.all_versions) |ver| {
82 const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
83 defer allocator.free(tmp);
84 try jws.write(tmp);
85 }
86 try jws.endArray();
87
88 try jws.objectField("cpus");
89 try jws.beginObject();
90 for (meta.tags(Target.Cpu.Arch)) |arch| {
91 try jws.objectField(@tagName(arch));
92 try jws.beginObject();
93 for (arch.allCpuModels()) |model| {
94 try jws.objectField(model.name);
95 try jws.beginArray();
96 for (arch.allFeaturesList(), 0..) |feature, i_usize| {
97 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
98 if (model.features.isEnabled(index)) {
99 try jws.write(feature.name);
100 }
101 }60 }
102 try jws.endArray();61 try libc_obj.end();
103 }62 }
104 try jws.endObject();63
105 }64 {
106 try jws.endObject();65 var glibc_obj = try root_obj.beginTupleField("glibc", .{});
10766 for (glibc_abi.all_versions) |ver| {
108 try jws.objectField("cpuFeatures");67 const tmp = try std.fmt.allocPrint(allocator, "{}", .{ver});
109 try jws.beginObject();68 defer allocator.free(tmp);
110 for (meta.tags(Target.Cpu.Arch)) |arch| {69 try glibc_obj.field(tmp, .{});
111 try jws.objectField(@tagName(arch));70 }
112 try jws.beginArray();71 try glibc_obj.end();
113 for (arch.allFeaturesList()) |feature| {
114 try jws.write(feature.name);
115 }72 }
116 try jws.endArray();
117 }
118 try jws.endObject();
11973
120 try jws.objectField("native");74 {
121 try jws.beginObject();75 var cpus_obj = try root_obj.beginStructField("cpus", .{});
122 {76 for (meta.tags(Target.Cpu.Arch)) |arch| {
123 const triple = try native_target.zigTriple(allocator);77 var arch_obj = try cpus_obj.beginStructField(@tagName(arch), .{});
124 defer allocator.free(triple);78 for (arch.allCpuModels()) |model| {
125 try jws.objectField("triple");79 var features = try arch_obj.beginTupleField(model.name, .{});
126 try jws.write(triple);80 for (arch.allFeaturesList(), 0..) |feature, i_usize| {
127 }81 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
128 {82 if (model.features.isEnabled(index)) {
129 try jws.objectField("cpu");83 try features.field(feature.name, .{});
130 try jws.beginObject();84 }
131 try jws.objectField("arch");85 }
132 try jws.write(@tagName(native_target.cpu.arch));86 try features.end();
87 }
88 try arch_obj.end();
89 }
90 try cpus_obj.end();
91 }
13392
134 try jws.objectField("name");93 {
135 const cpu = native_target.cpu;94 var cpu_features_obj = try root_obj.beginStructField("cpu_features", .{});
136 try jws.write(cpu.model.name);95 for (meta.tags(Target.Cpu.Arch)) |arch| {
96 var arch_features = try cpu_features_obj.beginTupleField(@tagName(arch), .{});
97 for (arch.allFeaturesList()) |feature| {
98 try arch_features.field(feature.name, .{});
99 }
100 try arch_features.end();
101 }
102 try cpu_features_obj.end();
103 }
137104
138 {105 {
139 try jws.objectField("features");106 var native_obj = try root_obj.beginStructField("native", .{});
140 try jws.beginArray();107 {
141 for (native_target.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {108 const triple = try native_target.zigTriple(allocator);
142 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));109 defer allocator.free(triple);
143 if (cpu.features.isEnabled(index)) {110 try native_obj.field("triple", triple, .{});
144 try jws.write(feature.name);111 }
112 {
113 var cpu_obj = try native_obj.beginStructField("cpu", .{});
114 try cpu_obj.field("arch", @tagName(native_target.cpu.arch), .{});
115
116 try cpu_obj.field("name", native_target.cpu.model.name, .{});
117
118 {
119 var features = try native_obj.beginTupleField("features", .{});
120 for (native_target.cpu.arch.allFeaturesList(), 0..) |feature, i_usize| {
121 const index = @as(Target.Cpu.Feature.Set.Index, @intCast(i_usize));
122 if (native_target.cpu.features.isEnabled(index)) {
123 try features.field(feature.name, .{});
124 }
125 }
126 try features.end();
145 }127 }
128 try cpu_obj.end();
146 }129 }
147 try jws.endArray();130
131 try native_obj.field("os", @tagName(native_target.os.tag), .{});
132 try native_obj.field("abi", @tagName(native_target.abi), .{});
133 try native_obj.end();
148 }134 }
149 try jws.endObject();
150 }
151 try jws.objectField("os");
152 try jws.write(@tagName(native_target.os.tag));
153 try jws.objectField("abi");
154 try jws.write(@tagName(native_target.abi));
155 try jws.endObject();
156135
157 try jws.endObject();136 try root_obj.end();
137 }
158138
159 try w.writeByte('\n');139 try w.writeByte('\n');
160 return bw.flush();140 return bw.flush();