authorgravatar for isaac.yonemoto@gmail.comIsaac Yonemoto <isaac.yonemoto@gmail.com> 2022-10-15 13:32:05-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-10-15 14:32:05-04:00
log99c3578f697fe0b0151049f74208b86244b4d171
tree9fff199f0fe9f3dd527379b512b396b2d6cb3e81
parentc0d7f6403665a8b81b0afebf08d1741cca1daef9
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

adds isTag function to std.meta (#11895)


1 files changed, 48 insertions(+), 0 deletions(-)

lib/std/meta.zig+48
......@@ -57,6 +57,54 @@ test "std.meta.tagName" {
5757 try testing.expect(mem.eql(u8, tagName(u2b), "D"));
5858}
5959
60/// Given an enum or tagged union, returns true if the comptime-supplied
61/// string matches the name of the tag value. This match process should
62/// be, at runtime, O(1) in the number of tags available to the enum or
63/// union, and it should also be O(1) in the length of the comptime tag
64/// names.
65pub fn isTag(tagged_value: anytype, comptime tag_name: []const u8) bool {
66 const T = @TypeOf(tagged_value);
67 const type_info = @typeInfo(T);
68 const type_name = @typeName(T);
69
70 // select the Enum type out of the type (in the case of the tagged union, extract it)
71 const E = if (.Enum == type_info) T else if (.Union == type_info) (if (type_info.Union.tag_type) |TT| TT else {
72 @compileError("attempted to use isTag on the untagged union " ++ type_name);
73 }) else {
74 @compileError("attempted to use isTag on a value of type (" ++ type_name ++ ") that isn't an enum or a union.");
75 };
76
77 return tagged_value == @field(E, tag_name);
78}
79
80test "std.meta.isTag for Enums" {
81 const EnumType = enum { a, b };
82 var a_type: EnumType = .a;
83 var b_type: EnumType = .b;
84
85 try testing.expect(isTag(a_type, "a"));
86 try testing.expect(!isTag(a_type, "b"));
87 try testing.expect(isTag(b_type, "b"));
88 try testing.expect(!isTag(b_type, "a"));
89}
90
91test "std.meta.isTag for Tagged Unions" {
92 const TaggedUnionEnum = enum { int, flt };
93
94 const TaggedUnionType = union(TaggedUnionEnum) {
95 int: i64,
96 flt: f64,
97 };
98
99 var int = TaggedUnionType{ .int = 1234 };
100 var flt = TaggedUnionType{ .flt = 12.34 };
101
102 try testing.expect(isTag(int, "int"));
103 try testing.expect(!isTag(int, "flt"));
104 try testing.expect(isTag(flt, "flt"));
105 try testing.expect(!isTag(flt, "int"));
106}
107
60108pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
61109 // Using ComptimeStringMap here is more performant, but it will start to take too
62110 // long to compile if the enum is large enough, due to the current limits of comptime