authorgravatar for tgschultz@gmail.comtgschultz <tgschultz@gmail.com> 2018-08-27 16:25:33-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-08-27 17:25:33-04:00
logecc54640243ba84ffa3656b73aa7dd6b53474462
tree3a133b1343b4589a3871c704c727fca13d876c5f
parent009e90f446ec7a81d602906fda9b17a6af1859f5

Handle unions differently in std.fmt (#1432)

* Handle unions differently in std.fmt Print the active tag's value in tagged unions. Untagged unions considered unsafe to print and treated like a pointer or an array.

1 files changed, 98 insertions(+), 17 deletions(-)

std/fmt/index.zig+98-17
...@@ -163,26 +163,47 @@ pub fn formatType(...@@ -163,26 +163,47 @@ pub fn formatType(
163 }163 }
164 break :cf false;164 break :cf false;
165 };165 };
166
167 if (has_cust_fmt) return value.format(fmt, context, Errors, output);166 if (has_cust_fmt) return value.format(fmt, context, Errors, output);
167
168 try output(context, @typeName(T));168 try output(context, @typeName(T));
169 if (comptime @typeId(T) == builtin.TypeId.Enum) {169 switch (comptime @typeId(T)) {
170 try output(context, ".");170 builtin.TypeId.Enum => {
171 try formatType(@tagName(value), "", context, Errors, output);171 try output(context, ".");
172 return;172 try formatType(@tagName(value), "", context, Errors, output);
173 }173 return;
174 comptime var field_i = 0;174 },
175 inline while (field_i < @memberCount(T)) : (field_i += 1) {175 builtin.TypeId.Struct => {
176 if (field_i == 0) {176 comptime var field_i = 0;
177 try output(context, "{ .");177 inline while (field_i < @memberCount(T)) : (field_i += 1) {
178 } else {178 if (field_i == 0) {
179 try output(context, ", .");179 try output(context, "{ .");
180 }180 } else {
181 try output(context, @memberName(T, field_i));181 try output(context, ", .");
182 try output(context, " = ");182 }
183 try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output);183 try output(context, @memberName(T, field_i));
184 try output(context, " = ");
185 try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output);
186 }
187 try output(context, " }");
188 },
189 builtin.TypeId.Union => {
190 const info = @typeInfo(T).Union;
191 if(info.tag_type) |UnionTagType| {
192 try output(context, "{ .");
193 try output(context, @tagName(UnionTagType(value)));
194 try output(context, " = ");
195 inline for(info.fields) |u_field| {
196 if(@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
197 try formatType(@field(value, u_field.name), "", context, Errors, output);
198 }
199 }
200 try output(context, " }");
201 } else {
202 try format(context, Errors, output, "@{x}", @ptrToInt(&value));
203 }
204 },
205 else => unreachable,
184 }206 }
185 try output(context, " }");
186 return;207 return;
187 },208 },
188 builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) {209 builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) {
...@@ -1194,6 +1215,66 @@ test "fmt.format" {...@@ -1194,6 +1215,66 @@ test "fmt.format" {
1194 try testFmt("point: (10.200,2.220)\n", "point: {}\n", value);1215 try testFmt("point: (10.200,2.220)\n", "point: {}\n", value);
1195 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);1216 try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);
1196 }1217 }
1218 //struct format
1219 {
1220 const S = struct {
1221 a: u32,
1222 b: error,
1223 };
1224
1225 const inst = S {
1226 .a = 456,
1227 .b = error.Unused,
1228 };
1229
1230 try testFmt("S{ .a = 456, .b = error.Unused }", "{}", inst);
1231 }
1232 //union format
1233 {
1234 const TU = union(enum)
1235 {
1236 float: f32,
1237 int: u32,
1238 };
1239
1240 const UU = union
1241 {
1242 float: f32,
1243 int: u32,
1244 };
1245
1246 const EU = extern union
1247 {
1248 float: f32,
1249 int: u32,
1250 };
1251
1252 const tu_inst = TU{ .int = 123, };
1253 const uu_inst = UU{ .int = 456, };
1254 const eu_inst = EU{ .float = 321.123, };
1255
1256 try testFmt("TU{ .int = 123 }", "{}", tu_inst);
1257
1258 var buf: [100]u8 = undefined;
1259 const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
1260 debug.assert(mem.eql(u8, uu_result[0..3], "UU@"));
1261
1262 const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
1263 debug.assert(mem.eql(u8, uu_result[0..3], "EU@"));
1264 }
1265 //enum format
1266 {
1267 const E = enum
1268 {
1269 One,
1270 Two,
1271 Three,
1272 };
1273
1274 const inst = E.Two;
1275
1276 try testFmt("E.Two", "{}", inst);
1277 }
1197}1278}
11981279
1199fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {1280fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {