| ... | ... | @@ -890,38 +890,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType { |
| 890 | 890 | // this function should behave like transCCast in translate-c, except it's for macros and enums |
| 891 | 891 | const SourceType = @TypeOf(target); |
| 892 | 892 | switch (@typeInfo(DestType)) { |
| 893 | | .Pointer => { |
| 894 | | switch (@typeInfo(SourceType)) { |
| 895 | | .Int, .ComptimeInt => { |
| 896 | | return @intToPtr(DestType, target); |
| 897 | | }, |
| 898 | | .Pointer => { |
| 899 | | return castPtr(DestType, target); |
| 900 | | }, |
| 901 | | .Optional => |opt| { |
| 902 | | if (@typeInfo(opt.child) == .Pointer) { |
| 903 | | return castPtr(DestType, target); |
| 904 | | } |
| 905 | | }, |
| 906 | | else => {}, |
| 907 | | } |
| 908 | | }, |
| 893 | .Pointer => return castToPtr(DestType, SourceType, target), |
| 909 | 894 | .Optional => |dest_opt| { |
| 910 | 895 | if (@typeInfo(dest_opt.child) == .Pointer) { |
| 911 | | switch (@typeInfo(SourceType)) { |
| 912 | | .Int, .ComptimeInt => { |
| 913 | | return @intToPtr(DestType, target); |
| 914 | | }, |
| 915 | | .Pointer => { |
| 916 | | return castPtr(DestType, target); |
| 917 | | }, |
| 918 | | .Optional => |target_opt| { |
| 919 | | if (@typeInfo(target_opt.child) == .Pointer) { |
| 920 | | return castPtr(DestType, target); |
| 921 | | } |
| 922 | | }, |
| 923 | | else => {}, |
| 924 | | } |
| 896 | return castToPtr(DestType, SourceType, target); |
| 925 | 897 | } |
| 926 | 898 | }, |
| 927 | 899 | .Enum => |enum_type| { |
| ... | ... | @@ -977,6 +949,30 @@ fn castPtr(comptime DestType: type, target: anytype) DestType { |
| 977 | 949 | return @ptrCast(DestType, @alignCast(dest.alignment, target)); |
| 978 | 950 | } |
| 979 | 951 | |
| 952 | fn castToPtr(comptime DestType: type, comptime SourceType: type, target: anytype) DestType { |
| 953 | switch (@typeInfo(SourceType)) { |
| 954 | .Int => { |
| 955 | return @intToPtr(DestType, castInt(usize, target)); |
| 956 | }, |
| 957 | .ComptimeInt => { |
| 958 | if (target < 0) |
| 959 | return @intToPtr(DestType, @bitCast(usize, @intCast(isize, target))) |
| 960 | else |
| 961 | return @intToPtr(DestType, @intCast(usize, target)); |
| 962 | }, |
| 963 | .Pointer => { |
| 964 | return castPtr(DestType, target); |
| 965 | }, |
| 966 | .Optional => |target_opt| { |
| 967 | if (@typeInfo(target_opt.child) == .Pointer) { |
| 968 | return castPtr(DestType, target); |
| 969 | } |
| 970 | }, |
| 971 | else => {}, |
| 972 | } |
| 973 | return @as(DestType, target); |
| 974 | } |
| 975 | |
| 980 | 976 | fn ptrInfo(comptime PtrType: type) TypeInfo.Pointer { |
| 981 | 977 | return switch (@typeInfo(PtrType)) { |
| 982 | 978 | .Optional => |opt_info| @typeInfo(opt_info.child).Pointer, |
| ... | ... | @@ -1026,6 +1022,12 @@ test "std.meta.cast" { |
| 1026 | 1022 | try testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B); |
| 1027 | 1023 | try testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B); |
| 1028 | 1024 | try testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42)); |
| 1025 | |
| 1026 | var foo: c_int = -1; |
| 1027 | try testing.expect(cast(*c_void, -1) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)))); |
| 1028 | try testing.expect(cast(*c_void, foo) == @intToPtr(*c_void, @bitCast(usize, @as(isize, -1)))); |
| 1029 | try testing.expect(cast(?*c_void, -1) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1)))); |
| 1030 | try testing.expect(cast(?*c_void, foo) == @intToPtr(?*c_void, @bitCast(usize, @as(isize, -1)))); |
| 1029 | 1031 | } |
| 1030 | 1032 | |
| 1031 | 1033 | /// Given a value returns its size as C's sizeof operator would. |