diff options
| author | tgschultz <tgschultz@gmail.com> | 2018-08-27 16:25:33 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2018-08-27 17:25:33 -0400 |
| commit | ecc54640243ba84ffa3656b73aa7dd6b53474462 (patch) | |
| tree | 3a133b1343b4589a3871c704c727fca13d876c5f /std | |
| parent | 009e90f446ec7a81d602906fda9b17a6af1859f5 (diff) | |
| download | zig-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.zig | 115 |
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 { |
