aboutsummaryrefslogtreecommitdiff
path: root/std
diff options
context:
space:
mode:
authortgschultz <tgschultz@gmail.com>2018-08-27 16:25:33 -0500
committerAndrew Kelley <superjoe30@gmail.com>2018-08-27 17:25:33 -0400
commitecc54640243ba84ffa3656b73aa7dd6b53474462 (patch)
tree3a133b1343b4589a3871c704c727fca13d876c5f /std
parent009e90f446ec7a81d602906fda9b17a6af1859f5 (diff)
downloadzig-ecc54640243ba84ffa3656b73aa7dd6b53474462.tar.gz
zig-ecc54640243ba84ffa3656b73aa7dd6b53474462.zip
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.
Diffstat (limited to 'std')
-rw-r--r--std/fmt/index.zig115
1 files changed, 98 insertions, 17 deletions
diff --git a/std/fmt/index.zig b/std/fmt/index.zig
index 82e9a5ba39..17039f3953 100644
--- a/std/fmt/index.zig
+++ b/std/fmt/index.zig
@@ -163,26 +163,47 @@ pub fn formatType(
}
break :cf false;
};
-
if (has_cust_fmt) return value.format(fmt, context, Errors, output);
+
try output(context, @typeName(T));
- if (comptime @typeId(T) == builtin.TypeId.Enum) {
- try output(context, ".");
- try formatType(@tagName(value), "", context, Errors, output);
- return;
- }
- comptime var field_i = 0;
- inline while (field_i < @memberCount(T)) : (field_i += 1) {
- if (field_i == 0) {
- try output(context, "{ .");
- } else {
- try output(context, ", .");
- }
- try output(context, @memberName(T, field_i));
- try output(context, " = ");
- try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output);
+ switch (comptime @typeId(T)) {
+ builtin.TypeId.Enum => {
+ try output(context, ".");
+ try formatType(@tagName(value), "", context, Errors, output);
+ return;
+ },
+ builtin.TypeId.Struct => {
+ comptime var field_i = 0;
+ inline while (field_i < @memberCount(T)) : (field_i += 1) {
+ if (field_i == 0) {
+ try output(context, "{ .");
+ } else {
+ try output(context, ", .");
+ }
+ try output(context, @memberName(T, field_i));
+ try output(context, " = ");
+ try formatType(@field(value, @memberName(T, field_i)), "", context, Errors, output);
+ }
+ try output(context, " }");
+ },
+ builtin.TypeId.Union => {
+ const info = @typeInfo(T).Union;
+ if(info.tag_type) |UnionTagType| {
+ try output(context, "{ .");
+ try output(context, @tagName(UnionTagType(value)));
+ try output(context, " = ");
+ inline for(info.fields) |u_field| {
+ if(@enumToInt(UnionTagType(value)) == u_field.enum_field.?.value) {
+ try formatType(@field(value, u_field.name), "", context, Errors, output);
+ }
+ }
+ try output(context, " }");
+ } else {
+ try format(context, Errors, output, "@{x}", @ptrToInt(&value));
+ }
+ },
+ else => unreachable,
}
- try output(context, " }");
return;
},
builtin.TypeId.Pointer => |ptr_info| switch (ptr_info.size) {
@@ -1194,6 +1215,66 @@ test "fmt.format" {
try testFmt("point: (10.200,2.220)\n", "point: {}\n", value);
try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", value);
}
+ //struct format
+ {
+ const S = struct {
+ a: u32,
+ b: error,
+ };
+
+ const inst = S {
+ .a = 456,
+ .b = error.Unused,
+ };
+
+ try testFmt("S{ .a = 456, .b = error.Unused }", "{}", inst);
+ }
+ //union format
+ {
+ const TU = union(enum)
+ {
+ float: f32,
+ int: u32,
+ };
+
+ const UU = union
+ {
+ float: f32,
+ int: u32,
+ };
+
+ const EU = extern union
+ {
+ float: f32,
+ int: u32,
+ };
+
+ const tu_inst = TU{ .int = 123, };
+ const uu_inst = UU{ .int = 456, };
+ const eu_inst = EU{ .float = 321.123, };
+
+ try testFmt("TU{ .int = 123 }", "{}", tu_inst);
+
+ var buf: [100]u8 = undefined;
+ const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
+ debug.assert(mem.eql(u8, uu_result[0..3], "UU@"));
+
+ const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
+ debug.assert(mem.eql(u8, uu_result[0..3], "EU@"));
+ }
+ //enum format
+ {
+ const E = enum
+ {
+ One,
+ Two,
+ Three,
+ };
+
+ const inst = E.Two;
+
+ try testFmt("E.Two", "{}", inst);
+ }
}
fn testFmt(expected: []const u8, comptime template: []const u8, args: ...) !void {