From 292d515e9119e2d02afa2197a255e1ec865d034e Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 10 Mar 2020 23:36:27 +1100 Subject: [PATCH 1/3] std: allow specifiying enums to be formatted as numbers --- lib/std/fmt.zig | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index db4232ec0e..28c90b06ec 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -359,11 +359,28 @@ pub fn formatType( }, .Enum => |enumInfo| { try out_stream.writeAll(@typeName(T)); + + var has_name: bool = undefined; if (enumInfo.is_exhaustive) { + has_name = true; + } else { + // TODO: when @tagName works on exhaustive enums print known enum strings + has_name = false; + } + + var use_name = has_name; + if (comptime std.mem.eql(u8, fmt, "x") or + comptime std.mem.eql(u8, fmt, "X") or + comptime std.mem.eql(u8, fmt, "d") or + comptime std.mem.eql(u8, fmt, "b")) + { + use_name = false; + } + + if (use_name) { try out_stream.writeAll("."); try out_stream.writeAll(@tagName(value)); } else { - // TODO: when @tagName works on exhaustive enums print known enum strings try out_stream.writeAll("("); try formatType(@enumToInt(value), fmt, options, out_stream, max_depth); try out_stream.writeAll(")"); @@ -1308,6 +1325,8 @@ test "enum" { const value = Enum.Two; try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value}); try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value}); + try testFmt("enum: Enum(0)\n", "enum: {x}\n", .{Enum.One}); + try testFmt("enum: Enum(1)\n", "enum: {X}\n", .{Enum.Two}); } test "non-exhaustive enum" { @@ -1321,6 +1340,7 @@ test "non-exhaustive enum" { try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); + try testFmt("enum: Enum(BEEF)\n", "enum: {X}\n", .{Enum.Two}); try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); } From 5cdeac3b0eaf61bc07e45012d9c335a74f437276 Mon Sep 17 00:00:00 2001 From: daurnimator Date: Tue, 10 Mar 2020 23:36:48 +1100 Subject: [PATCH 2/3] std: in fmt, use tag names of non-exhaustive enums when available --- lib/std/fmt.zig | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 28c90b06ec..a112528ab8 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -364,8 +364,14 @@ pub fn formatType( if (enumInfo.is_exhaustive) { has_name = true; } else { - // TODO: when @tagName works on exhaustive enums print known enum strings has_name = false; + // Use @tagName only if value is one of known fields + inline for (enumInfo.fields) |enumField| { + if (@enumToInt(value) == enumField.value) { + has_name = true; + break; + } + } } var use_name = has_name; @@ -1335,8 +1341,8 @@ test "non-exhaustive enum" { Two = 0xbeef, _, }; - try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One}); - try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two}); + try testFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One}); + try testFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two}); try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); From 62fefe864840e4d2c8bf4d6ad5509bcac141e7c3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 26 May 2020 12:15:08 -0400 Subject: [PATCH 3/3] std.fmt: non-exhaustive enums: avoid the loop when it's not necessary --- lib/std/fmt.zig | 52 ++++++++++++++++++------------------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index a112528ab8..f3c43c5590 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -359,38 +359,24 @@ pub fn formatType( }, .Enum => |enumInfo| { try out_stream.writeAll(@typeName(T)); - - var has_name: bool = undefined; if (enumInfo.is_exhaustive) { - has_name = true; - } else { - has_name = false; - // Use @tagName only if value is one of known fields - inline for (enumInfo.fields) |enumField| { - if (@enumToInt(value) == enumField.value) { - has_name = true; - break; - } + try out_stream.writeAll("."); + try out_stream.writeAll(@tagName(value)); + return; + } + + // Use @tagName only if value is one of known fields + inline for (enumInfo.fields) |enumField| { + if (@enumToInt(value) == enumField.value) { + try out_stream.writeAll("."); + try out_stream.writeAll(@tagName(value)); + return; } } - var use_name = has_name; - if (comptime std.mem.eql(u8, fmt, "x") or - comptime std.mem.eql(u8, fmt, "X") or - comptime std.mem.eql(u8, fmt, "d") or - comptime std.mem.eql(u8, fmt, "b")) - { - use_name = false; - } - - if (use_name) { - try out_stream.writeAll("."); - try out_stream.writeAll(@tagName(value)); - } else { - try out_stream.writeAll("("); - try formatType(@enumToInt(value), fmt, options, out_stream, max_depth); - try out_stream.writeAll(")"); - } + try out_stream.writeAll("("); + try formatType(@enumToInt(value), fmt, options, out_stream, max_depth); + try out_stream.writeAll(")"); }, .Union => { try out_stream.writeAll(@typeName(T)); @@ -1331,8 +1317,8 @@ test "enum" { const value = Enum.Two; try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value}); try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value}); - try testFmt("enum: Enum(0)\n", "enum: {x}\n", .{Enum.One}); - try testFmt("enum: Enum(1)\n", "enum: {X}\n", .{Enum.Two}); + try testFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One}); + try testFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two}); } test "non-exhaustive enum" { @@ -1344,9 +1330,9 @@ test "non-exhaustive enum" { try testFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One}); try testFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two}); try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); - try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); - try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); - try testFmt("enum: Enum(BEEF)\n", "enum: {X}\n", .{Enum.Two}); + try testFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One}); + try testFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two}); + try testFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two}); try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); }