| ... | @@ -894,34 +894,32 @@ pub const errno = struct { | ... | @@ -894,34 +894,32 @@ pub const errno = struct { |
| 894 | return null; | 894 | return null; |
| 895 | } | 895 | } |
| 896 | | 896 | |
| 897 | const map = blk: { | 897 | comptime { |
| 898 | const KV = struct { []const u8, Error }; | 898 | // assert Enum is sequential |
| 899 | var kvs: []const KV = &.{}; | 899 | var value: c_ushort = 0; // SUCCESS |
| 900 | for (std.meta.fields(Enum)) |field| { | 900 | for (std.enums.values(Enum)) |val| { |
| 901 | kvs = kvs ++ &[1]KV{.{ field.name, @field(Error, field.name) }}; | 901 | std.debug.assert(@intFromEnum(val) > value); |
| | 902 | value = @intFromEnum(val); |
| 902 | } | 903 | } |
| 903 | break :blk std.StaticStringMap(Error).initComptime(kvs); | 904 | } |
| | 905 | comptime { |
| | 906 | // sanity test |
| | 907 | std.debug.assert(@intFromEnum(Enum.EPERM) == 1); |
| | 908 | } |
| | 909 | const list = blk: { |
| | 910 | const values = std.enums.values(Enum); |
| | 911 | const len = @intFromEnum(values[values.len - 1]) + 1; |
| | 912 | var errors: [len]Error = @splat(error.Unexpected); |
| | 913 | for (values) |f| errors[@intFromEnum(f)] = @field(Error, @tagName(f)); |
| | 914 | const final = errors; |
| | 915 | break :blk final; |
| 904 | }; | 916 | }; |
| 905 | | 917 | |
| 906 | pub fn fromInt(code: c_int) Error { | 918 | pub fn fromInt(code: c_int) Error { |
| 907 | const errors_are_seqential = comptime blk: { | 919 | @setRuntimeSafety(false); |
| 908 | if (@intFromEnum(Enum.EPERM) != 1) break :blk false; | 920 | if (code >= list.len) return error.Unexpected; |
| 909 | var prev: u16 = @intFromError(Error.EPERM); | 921 | if (code <= 0) return error.Unexpected; |
| 910 | for (std.meta.fields(Error)[1..]) |field| { | 922 | return list[@intCast(code)]; |
| 911 | const int = @intFromError(@field(anyerror, field.name)); | | |
| 912 | if (int != prev + 1) break :blk false; | | |
| 913 | prev = int; | | |
| 914 | } | | |
| 915 | break :blk true; | | |
| 916 | }; | | |
| 917 | if (errors_are_seqential) { | | |
| 918 | // avoid an inline for and N comparisons | | |
| 919 | if (code < 1) return error.Unexpected; | | |
| 920 | if (code > std.meta.fields(Enum).len) return error.Unexpected; | | |
| 921 | const ucode: c_ushort = @intCast(code); | | |
| 922 | return @errorCast(@errorFromInt(@intFromError(Error.EPERM) + ucode - @intFromEnum(Enum.EPERM))); | | |
| 923 | } | | |
| 924 | return map.get(std.enums.tagName(Enum, @enumFromInt(code)) orelse return error.Unexpected).?; | | |
| 925 | } | 923 | } |
| 926 | | 924 | |
| 927 | pub fn fromLibC() c_int { | 925 | pub fn fromLibC() c_int { |