aboutsummaryrefslogtreecommitdiff
path: root/lib/std/meta.zig
diff options
context:
space:
mode:
authorRyan Liptak <squeek502@hotmail.com>2020-05-26 22:31:36 -0700
committerRyan Liptak <squeek502@hotmail.com>2020-05-26 23:10:13 -0700
commitb683498ae8065ba820700944b4417e8d2174d068 (patch)
treef9396915c27bee46277041c77babb76adb2e3c54 /lib/std/meta.zig
parentdfafafac7b701feb154e28981e77aa6f66624e8f (diff)
downloadzig-b683498ae8065ba820700944b4417e8d2174d068.tar.gz
zig-b683498ae8065ba820700944b4417e8d2174d068.zip
Use ComptimeStringMap in std.meta.stringToEnum when feasible
Diffstat (limited to 'lib/std/meta.zig')
-rw-r--r--lib/std/meta.zig33
1 files changed, 29 insertions, 4 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 68426323b2..3e3a886343 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -53,12 +53,37 @@ test "std.meta.tagName" {
}
pub fn stringToEnum(comptime T: type, str: []const u8) ?T {
- inline for (@typeInfo(T).Enum.fields) |enumField| {
- if (mem.eql(u8, str, enumField.name)) {
- return @field(T, enumField.name);
+ // Using ComptimeStringMap here is more performant, but it will start to take too
+ // long to compile if the enum is large enough, due to the current limits of comptime
+ // performance when doing things like constructing lookup maps at comptime.
+ // TODO The '100' here is arbitrary and should be increased when possible:
+ // - https://github.com/ziglang/zig/issues/4055
+ // - https://github.com/ziglang/zig/issues/3863
+ if (@typeInfo(T).Enum.fields.len <= 100) {
+ const kvs = comptime build_kvs: {
+ // In order to generate an array of structs that play nice with anonymous
+ // list literals, we need to give them "0" and "1" field names.
+ // TODO https://github.com/ziglang/zig/issues/4335
+ const EnumKV = struct {
+ @"0": []const u8,
+ @"1": T,
+ };
+ var kvs_array: [@typeInfo(T).Enum.fields.len]EnumKV = undefined;
+ inline for (@typeInfo(T).Enum.fields) |enumField, i| {
+ kvs_array[i] = .{.@"0" = enumField.name, .@"1" = @field(T, enumField.name)};
+ }
+ break :build_kvs kvs_array[0..];
+ };
+ const map = std.ComptimeStringMap(T, kvs);
+ return map.get(str);
+ } else {
+ inline for (@typeInfo(T).Enum.fields) |enumField| {
+ if (mem.eql(u8, str, enumField.name)) {
+ return @field(T, enumField.name);
+ }
}
+ return null;
}
- return null;
}
test "std.meta.stringToEnum" {