| author | |
| committer | |
| log | a365971a337116dd23df2b1bc86468d54885b4b2 |
| tree | 070dfe739796151d4d1256a3cedd83989609be42 |
| parent | a3693aae3a9417c4298788af570762945b21ccba |
Also use an optional as the return type instead of an error code.9 files changed, 64 insertions(+), 67 deletions(-)
lib/compiler/resinator/cli.zig+2-2| ... | ... | @@ -354,9 +354,9 @@ pub const Options = struct { |
| 354 | 354 | |
| 355 | 355 | const language_id = self.default_language_id orelse res.Language.default; |
| 356 | 356 | const language_name = language_name: { |
| 357 | if (std.meta.intToEnum(lang.LanguageId, language_id)) |lang_enum_val| { | |
| 357 | if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| { | |
| 358 | 358 | break :language_name @tagName(lang_enum_val); |
| 359 | } else |_| {} | |
| 359 | } | |
| 360 | 360 | if (language_id == lang.LOCALE_CUSTOM_UNSPECIFIED) { |
| 361 | 361 | break :language_name "LOCALE_CUSTOM_UNSPECIFIED"; |
| 362 | 362 | } |
lib/compiler/resinator/res.zig+2-2| ... | ... | @@ -173,9 +173,9 @@ pub const Language = packed struct(u16) { |
| 173 | 173 | _ = options; |
| 174 | 174 | const language_id = language.asInt(); |
| 175 | 175 | const language_name = language_name: { |
| 176 | if (std.meta.intToEnum(lang.LanguageId, language_id)) |lang_enum_val| { | |
| 176 | if (std.enums.fromInt(lang.LanguageId, language_id)) |lang_enum_val| { | |
| 177 | 177 | break :language_name @tagName(lang_enum_val); |
| 178 | } else |_| {} | |
| 178 | } | |
| 179 | 179 | if (language_id == lang.LOCALE_CUSTOM_UNSPECIFIED) { |
| 180 | 180 | break :language_name "LOCALE_CUSTOM_UNSPECIFIED"; |
| 181 | 181 | } |
lib/std/Build/Step/CheckObject.zig+5-5| ... | ... | @@ -2445,7 +2445,7 @@ const WasmDumper = struct { |
| 2445 | 2445 | switch (check.kind) { |
| 2446 | 2446 | .headers => { |
| 2447 | 2447 | while (reader.readByte()) |current_byte| { |
| 2448 | const section = std.meta.intToEnum(std.wasm.Section, current_byte) catch { | |
| 2448 | const section = std.enums.fromInt(std.wasm.Section, current_byte) orelse { | |
| 2449 | 2449 | return step.fail("Found invalid section id '{d}'", .{current_byte}); |
| 2450 | 2450 | }; |
| 2451 | 2451 | |
| ... | ... | @@ -2551,7 +2551,7 @@ const WasmDumper = struct { |
| 2551 | 2551 | const name = data[fbs.pos..][0..name_len]; |
| 2552 | 2552 | fbs.pos += name_len; |
| 2553 | 2553 | |
| 2554 | const kind = std.meta.intToEnum(std.wasm.ExternalKind, try reader.readByte()) catch { | |
| 2554 | const kind = std.enums.fromInt(std.wasm.ExternalKind, try reader.readByte()) orelse { | |
| 2555 | 2555 | return step.fail("invalid import kind", .{}); |
| 2556 | 2556 | }; |
| 2557 | 2557 | |
| ... | ... | @@ -2613,7 +2613,7 @@ const WasmDumper = struct { |
| 2613 | 2613 | const name = data[fbs.pos..][0..name_len]; |
| 2614 | 2614 | fbs.pos += name_len; |
| 2615 | 2615 | const kind_byte = try std.leb.readUleb128(u8, reader); |
| 2616 | const kind = std.meta.intToEnum(std.wasm.ExternalKind, kind_byte) catch { | |
| 2616 | const kind = std.enums.fromInt(std.wasm.ExternalKind, kind_byte) orelse { | |
| 2617 | 2617 | return step.fail("invalid export kind value '{d}'", .{kind_byte}); |
| 2618 | 2618 | }; |
| 2619 | 2619 | const index = try std.leb.readUleb128(u32, reader); |
| ... | ... | @@ -2664,7 +2664,7 @@ const WasmDumper = struct { |
| 2664 | 2664 | |
| 2665 | 2665 | fn parseDumpType(step: *Step, comptime E: type, reader: anytype, writer: anytype) !E { |
| 2666 | 2666 | const byte = try reader.readByte(); |
| 2667 | const tag = std.meta.intToEnum(E, byte) catch { | |
| 2667 | const tag = std.enums.fromInt(E, byte) orelse { | |
| 2668 | 2668 | return step.fail("invalid wasm type value '{d}'", .{byte}); |
| 2669 | 2669 | }; |
| 2670 | 2670 | try writer.print("type {s}\n", .{@tagName(tag)}); |
| ... | ... | @@ -2683,7 +2683,7 @@ const WasmDumper = struct { |
| 2683 | 2683 | |
| 2684 | 2684 | fn parseDumpInit(step: *Step, reader: anytype, writer: anytype) !void { |
| 2685 | 2685 | const byte = try reader.readByte(); |
| 2686 | const opcode = std.meta.intToEnum(std.wasm.Opcode, byte) catch { | |
| 2686 | const opcode = std.enums.fromInt(std.wasm.Opcode, byte) orelse { | |
| 2687 | 2687 | return step.fail("invalid wasm opcode '{d}'", .{byte}); |
| 2688 | 2688 | }; |
| 2689 | 2689 | switch (opcode) { |
lib/std/enums.zig+43| ... | ... | @@ -8,6 +8,25 @@ const EnumField = std.builtin.Type.EnumField; |
| 8 | 8 | /// Increment this value when adding APIs that add single backwards branches. |
| 9 | 9 | const eval_branch_quota_cushion = 10; |
| 10 | 10 | |
| 11 | pub fn fromInt(comptime E: type, integer: anytype) ?E { | |
| 12 | const enum_info = @typeInfo(E).@"enum"; | |
| 13 | if (!enum_info.is_exhaustive) { | |
| 14 | if (std.math.cast(enum_info.tag_type, integer)) |tag| { | |
| 15 | return @enumFromInt(tag); | |
| 16 | } | |
| 17 | return null; | |
| 18 | } | |
| 19 | // We don't directly iterate over the fields of E, as that | |
| 20 | // would require an inline loop. Instead, we create an array of | |
| 21 | // values that is comptime-know, but can be iterated at runtime | |
| 22 | // without requiring an inline loop. | |
| 23 | // This generates better machine code. | |
| 24 | for (values(E)) |value| { | |
| 25 | if (@intFromEnum(value) == integer) return @enumFromInt(integer); | |
| 26 | } | |
| 27 | return null; | |
| 28 | } | |
| 29 | ||
| 11 | 30 | /// Returns a struct with a field matching each unique named enum element. |
| 12 | 31 | /// If the enum is extern and has multiple names for the same value, only |
| 13 | 32 | /// the first name is used. Each field is of type Data and has the provided |
| ... | ... | @@ -239,6 +258,30 @@ test nameCast { |
| 239 | 258 | try testing.expectEqual(B.b, nameCast(B, "b")); |
| 240 | 259 | } |
| 241 | 260 | |
| 261 | test fromInt { | |
| 262 | const E1 = enum { | |
| 263 | A, | |
| 264 | }; | |
| 265 | const E2 = enum { | |
| 266 | A, | |
| 267 | B, | |
| 268 | }; | |
| 269 | const E3 = enum(i8) { A, _ }; | |
| 270 | ||
| 271 | var zero: u8 = 0; | |
| 272 | var one: u16 = 1; | |
| 273 | _ = &zero; | |
| 274 | _ = &one; | |
| 275 | try testing.expect(fromInt(E1, zero).? == E1.A); | |
| 276 | try testing.expect(fromInt(E2, one).? == E2.B); | |
| 277 | try testing.expect(fromInt(E3, zero).? == E3.A); | |
| 278 | try testing.expect(fromInt(E3, 127).? == @as(E3, @enumFromInt(127))); | |
| 279 | try testing.expect(fromInt(E3, -128).? == @as(E3, @enumFromInt(-128))); | |
| 280 | try testing.expectEqual(null, fromInt(E1, one)); | |
| 281 | try testing.expectEqual(null, fromInt(E3, 128)); | |
| 282 | try testing.expectEqual(null, fromInt(E3, -129)); | |
| 283 | } | |
| 284 | ||
| 242 | 285 | /// A set of enum elements, backed by a bitfield. If the enum |
| 243 | 286 | /// is exhaustive but not dense, a mapping will be constructed from enum values |
| 244 | 287 | /// to dense indices. This type does no dynamic allocation and |
lib/std/json/static.zig+2-2| ... | ... | @@ -595,7 +595,7 @@ pub fn innerParseFromValue( |
| 595 | 595 | |
| 596 | 596 | switch (source) { |
| 597 | 597 | .float => return error.InvalidEnumTag, |
| 598 | .integer => |i| return std.meta.intToEnum(T, i), | |
| 598 | .integer => |i| return std.enums.fromInt(T, i) orelse return error.InvalidEnumTag, | |
| 599 | 599 | .number_string, .string => |s| return sliceToEnum(T, s), |
| 600 | 600 | else => return error.UnexpectedToken, |
| 601 | 601 | } |
| ... | ... | @@ -780,7 +780,7 @@ fn sliceToEnum(comptime T: type, slice: []const u8) !T { |
| 780 | 780 | // Check for a numeric value. |
| 781 | 781 | if (!isNumberFormattedLikeAnInteger(slice)) return error.InvalidEnumTag; |
| 782 | 782 | const n = std.fmt.parseInt(@typeInfo(T).@"enum".tag_type, slice, 10) catch return error.InvalidEnumTag; |
| 783 | return std.meta.intToEnum(T, n); | |
| 783 | return std.enums.fromInt(T, n) orelse return error.InvalidEnumTag; | |
| 784 | 784 | } |
| 785 | 785 | |
| 786 | 786 | fn fillDefaultStructValues(comptime T: type, r: *T, fields_seen: *[@typeInfo(T).@"struct".fields.len]bool) !void { |
lib/std/meta.zig+3-49| ... | ... | @@ -857,58 +857,12 @@ test eql { |
| 857 | 857 | try testing.expect(!eql(CU{ .a = {} }, .b)); |
| 858 | 858 | } |
| 859 | 859 | |
| 860 | test intToEnum { | |
| 861 | const E1 = enum { | |
| 862 | A, | |
| 863 | }; | |
| 864 | const E2 = enum { | |
| 865 | A, | |
| 866 | B, | |
| 867 | }; | |
| 868 | const E3 = enum(i8) { A, _ }; | |
| 869 | ||
| 870 | var zero: u8 = 0; | |
| 871 | var one: u16 = 1; | |
| 872 | _ = &zero; | |
| 873 | _ = &one; | |
| 874 | try testing.expect(intToEnum(E1, zero) catch unreachable == E1.A); | |
| 875 | try testing.expect(intToEnum(E2, one) catch unreachable == E2.B); | |
| 876 | try testing.expect(intToEnum(E3, zero) catch unreachable == E3.A); | |
| 877 | try testing.expect(intToEnum(E3, 127) catch unreachable == @as(E3, @enumFromInt(127))); | |
| 878 | try testing.expect(intToEnum(E3, -128) catch unreachable == @as(E3, @enumFromInt(-128))); | |
| 879 | try testing.expectError(error.InvalidEnumTag, intToEnum(E1, one)); | |
| 880 | try testing.expectError(error.InvalidEnumTag, intToEnum(E3, 128)); | |
| 881 | try testing.expectError(error.InvalidEnumTag, intToEnum(E3, -129)); | |
| 882 | } | |
| 883 | ||
| 860 | /// Deprecated: use `std.enums.fromInt` instead and handle null. | |
| 884 | 861 | pub const IntToEnumError = error{InvalidEnumTag}; |
| 885 | 862 | |
| 863 | /// Deprecated: use `std.enums.fromInt` instead and handle null instead of an error. | |
| 886 | 864 | pub fn intToEnum(comptime EnumTag: type, tag_int: anytype) IntToEnumError!EnumTag { |
| 887 | const enum_info = @typeInfo(EnumTag).@"enum"; | |
| 888 | ||
| 889 | if (!enum_info.is_exhaustive) { | |
| 890 | if (std.math.cast(enum_info.tag_type, tag_int)) |tag| { | |
| 891 | return @as(EnumTag, @enumFromInt(tag)); | |
| 892 | } | |
| 893 | return error.InvalidEnumTag; | |
| 894 | } | |
| 895 | ||
| 896 | // We don't directly iterate over the fields of EnumTag, as that | |
| 897 | // would require an inline loop. Instead, we create an array of | |
| 898 | // values that is comptime-know, but can be iterated at runtime | |
| 899 | // without requiring an inline loop. This generates better | |
| 900 | // machine code. | |
| 901 | const values = comptime blk: { | |
| 902 | var result: [enum_info.fields.len]enum_info.tag_type = undefined; | |
| 903 | for (&result, enum_info.fields) |*dst, src| { | |
| 904 | dst.* = src.value; | |
| 905 | } | |
| 906 | break :blk result; | |
| 907 | }; | |
| 908 | for (values) |v| { | |
| 909 | if (v == tag_int) return @enumFromInt(tag_int); | |
| 910 | } | |
| 911 | return error.InvalidEnumTag; | |
| 865 | return std.enums.fromInt(EnumTag, tag_int) orelse return error.InvalidEnumTag; | |
| 912 | 866 | } |
| 913 | 867 | |
| 914 | 868 | /// Given a type and a name, return the field index according to source order. |
src/Package/Fetch/git.zig+2-2| ... | ... | @@ -313,7 +313,7 @@ pub const Repository = struct { |
| 313 | 313 | unused: u3, |
| 314 | 314 | type: u4, |
| 315 | 315 | } = @bitCast(std.fmt.parseUnsigned(u16, iterator.data[iterator.pos..mode_end], 8) catch return error.InvalidTree); |
| 316 | const @"type" = std.meta.intToEnum(Entry.Type, mode.type) catch return error.InvalidTree; | |
| 316 | const @"type" = std.enums.fromInt(Entry.Type, mode.type) orelse return error.InvalidTree; | |
| 317 | 317 | const executable = switch (mode.permission) { |
| 318 | 318 | 0 => if (@"type" == .file) return error.InvalidTree else false, |
| 319 | 319 | 0o644 => if (@"type" != .file) return error.InvalidTree else false, |
| ... | ... | @@ -1144,7 +1144,7 @@ const EntryHeader = union(Type) { |
| 1144 | 1144 | const rest_len = if (initial.has_next) try readSizeVarInt(reader) else 0; |
| 1145 | 1145 | var uncompressed_length: u64 = initial.len; |
| 1146 | 1146 | uncompressed_length |= std.math.shlExact(u64, rest_len, 4) catch return error.InvalidFormat; |
| 1147 | const @"type" = std.meta.intToEnum(EntryHeader.Type, initial.type) catch return error.InvalidFormat; | |
| 1147 | const @"type" = std.enums.fromInt(EntryHeader.Type, initial.type) orelse return error.InvalidFormat; | |
| 1148 | 1148 | return switch (@"type") { |
| 1149 | 1149 | inline .commit, .tree, .blob, .tag => |tag| @unionInit(EntryHeader, @tagName(tag), .{ |
| 1150 | 1150 | .uncompressed_length = uncompressed_length, |
src/Value.zig+1-1| ... | ... | @@ -3814,7 +3814,7 @@ pub fn interpret(val: Value, comptime T: type, pt: Zcu.PerThread) error{ OutOfMe |
| 3814 | 3814 | .@"enum" => switch (interpret_mode) { |
| 3815 | 3815 | .direct => { |
| 3816 | 3816 | const int = val.getUnsignedInt(zcu) orelse return error.TypeMismatch; |
| 3817 | return std.meta.intToEnum(T, int) catch error.TypeMismatch; | |
| 3817 | return std.enums.fromInt(T, int) orelse error.TypeMismatch; | |
| 3818 | 3818 | }, |
| 3819 | 3819 | .by_name => { |
| 3820 | 3820 | const field_index = ty.enumTagFieldIndex(val, zcu) orelse return error.TypeMismatch; |
test/behavior/enum.zig+4-4| ... | ... | @@ -19,16 +19,16 @@ test "enum to int" { |
| 19 | 19 | try shouldEqual(Number.Four, 4); |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | fn testIntToEnumEval(x: i32) !void { | |
| 23 | try expect(@as(IntToEnumNumber, @enumFromInt(x)) == IntToEnumNumber.Three); | |
| 22 | fn testEnumFromIntEval(x: i32) !void { | |
| 23 | try expect(@as(EnumFromIntNumber, @enumFromInt(x)) == EnumFromIntNumber.Three); | |
| 24 | 24 | } |
| 25 | const IntToEnumNumber = enum { Zero, One, Two, Three, Four }; | |
| 25 | const EnumFromIntNumber = enum { Zero, One, Two, Three, Four }; | |
| 26 | 26 | |
| 27 | 27 | test "int to enum" { |
| 28 | 28 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 29 | 29 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 30 | 30 | |
| 31 | try testIntToEnumEval(3); | |
| 31 | try testEnumFromIntEval(3); | |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | const ValueCount1 = enum { |