aboutsummaryrefslogtreecommitdiff
path: root/lib/std/meta.zig
diff options
context:
space:
mode:
authorMason Remaley <MasonRemaley@users.noreply.github.com>2023-05-01 01:03:46 -0400
committerGitHub <noreply@github.com>2023-05-01 05:03:46 +0000
commite963793e37f93d84f1e5295d309ebe0c738b663d (patch)
tree46eae49bf1a983385eac9eab56b633f33e511099 /lib/std/meta.zig
parent6ae19fa48d7853430ba45f2de90550cd48cf5b4c (diff)
downloadzig-e963793e37f93d84f1e5295d309ebe0c738b663d.tar.gz
zig-e963793e37f93d84f1e5295d309ebe0c738b663d.zip
Updates std.meta.intToEnum to support non-exhaustive enums (#15491)
This was preventing `std.json` from deserializing non-exhaustive enums.
Diffstat (limited to 'lib/std/meta.zig')
-rw-r--r--lib/std/meta.zig17
1 files changed, 16 insertions, 1 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 97c2ff4fb0..7be3b71347 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -965,18 +965,33 @@ test "intToEnum with error return" {
A,
B,
};
+ const E3 = enum(i8) { A, _ };
var zero: u8 = 0;
var one: u16 = 1;
try testing.expect(intToEnum(E1, zero) catch unreachable == E1.A);
try testing.expect(intToEnum(E2, one) catch unreachable == E2.B);
+ try testing.expect(intToEnum(E3, zero) catch unreachable == E3.A);
+ try testing.expect(intToEnum(E3, 127) catch unreachable == @intToEnum(E3, 127));
+ try testing.expect(intToEnum(E3, -128) catch unreachable == @intToEnum(E3, -128));
try testing.expectError(error.InvalidEnumTag, intToEnum(E1, one));
+ try testing.expectError(error.InvalidEnumTag, intToEnum(E3, 128));
+ try testing.expectError(error.InvalidEnumTag, intToEnum(E3, -129));
}
pub const IntToEnumError = error{InvalidEnumTag};
pub fn intToEnum(comptime EnumTag: type, tag_int: anytype) IntToEnumError!EnumTag {
- inline for (@typeInfo(EnumTag).Enum.fields) |f| {
+ const enum_info = @typeInfo(EnumTag).Enum;
+
+ if (!enum_info.is_exhaustive) {
+ if (std.math.cast(enum_info.tag_type, tag_int)) |tag| {
+ return @intToEnum(EnumTag, tag);
+ }
+ return error.InvalidEnumTag;
+ }
+
+ inline for (enum_info.fields) |f| {
const this_tag_value = @field(EnumTag, f.name);
if (tag_int == @enumToInt(this_tag_value)) {
return this_tag_value;