diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-06-22 23:22:17 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-06-22 23:22:17 -0400 |
| commit | 6938245fcc1daa6a63bcfcb3ba1092d569efc875 (patch) | |
| tree | 035b27a399c418cab679043f87282dc3de1ef5b1 /lib/std/meta.zig | |
| parent | 7b68385d7d4448e81cc882d9a5464bf58d10dc0d (diff) | |
| parent | 78c6d39cd49225bdfd2de4da7b1730ba26a41ba4 (diff) | |
| download | zig-6938245fcc1daa6a63bcfcb3ba1092d569efc875.tar.gz zig-6938245fcc1daa6a63bcfcb3ba1092d569efc875.zip | |
Merge remote-tracking branch 'origin/master' into zig-ast-to-zir
Diffstat (limited to 'lib/std/meta.zig')
| -rw-r--r-- | lib/std/meta.zig | 94 |
1 files changed, 88 insertions, 6 deletions
diff --git a/lib/std/meta.zig b/lib/std/meta.zig index 75f507da74..6c10941aa7 100644 --- a/lib/std/meta.zig +++ b/lib/std/meta.zig @@ -250,7 +250,7 @@ test "std.meta.containerLayout" { testing.expect(containerLayout(U3) == .Extern); } -pub fn declarations(comptime T: type) []TypeInfo.Declaration { +pub fn declarations(comptime T: type) []const TypeInfo.Declaration { return switch (@typeInfo(T)) { .Struct => |info| info.decls, .Enum => |info| info.decls, @@ -274,7 +274,7 @@ test "std.meta.declarations" { fn a() void {} }; - const decls = comptime [_][]TypeInfo.Declaration{ + const decls = comptime [_][]const TypeInfo.Declaration{ declarations(E1), declarations(S1), declarations(U1), @@ -323,10 +323,10 @@ test "std.meta.declarationInfo" { } pub fn fields(comptime T: type) switch (@typeInfo(T)) { - .Struct => []TypeInfo.StructField, - .Union => []TypeInfo.UnionField, - .ErrorSet => []TypeInfo.Error, - .Enum => []TypeInfo.EnumField, + .Struct => []const TypeInfo.StructField, + .Union => []const TypeInfo.UnionField, + .ErrorSet => []const TypeInfo.Error, + .Enum => []const TypeInfo.EnumField, else => @compileError("Expected struct, union, error set or enum type, found '" ++ @typeName(T) ++ "'"), } { return switch (@typeInfo(T)) { @@ -693,3 +693,85 @@ pub fn Vector(comptime len: u32, comptime child: type) type { }, }); } + +/// Given a type and value, cast the value to the type as c would. +/// This is for translate-c and is not intended for general use. +pub fn cast(comptime DestType: type, target: var) DestType { + const TargetType = @TypeOf(target); + switch (@typeInfo(DestType)) { + .Pointer => { + switch (@typeInfo(TargetType)) { + .Int, .ComptimeInt => { + return @intToPtr(DestType, target); + }, + .Pointer => |ptr| { + return @ptrCast(DestType, @alignCast(ptr.alignment, target)); + }, + .Optional => |opt| { + if (@typeInfo(opt.child) == .Pointer) { + return @ptrCast(DestType, @alignCast(@alignOf(opt.child.Child), target)); + } + }, + else => {}, + } + }, + .Optional => |opt| { + if (@typeInfo(opt.child) == .Pointer) { + switch (@typeInfo(TargetType)) { + .Int, .ComptimeInt => { + return @intToPtr(DestType, target); + }, + .Pointer => |ptr| { + return @ptrCast(DestType, @alignCast(ptr.alignment, target)); + }, + .Optional => |target_opt| { + if (@typeInfo(target_opt.child) == .Pointer) { + return @ptrCast(DestType, @alignCast(@alignOf(target_opt.child.Child), target)); + } + }, + else => {}, + } + } + }, + .Enum, .EnumLiteral => { + if (@typeInfo(TargetType) == .Int or @typeInfo(TargetType) == .ComptimeInt) { + return @intToEnum(DestType, target); + } + }, + .Int, .ComptimeInt => { + switch (@typeInfo(TargetType)) { + .Pointer => { + return @as(DestType, @ptrToInt(target)); + }, + .Optional => |opt| { + if (@typeInfo(opt.child) == .Pointer) { + return @as(DestType, @ptrToInt(target)); + } + }, + .Enum, .EnumLiteral => { + return @as(DestType, @enumToInt(target)); + }, + else => {}, + } + }, + else => {}, + } + return @as(DestType, target); +} + +test "std.meta.cast" { + const E = enum(u2) { + Zero, + One, + Two, + }; + + var i = @as(i64, 10); + + testing.expect(cast(?*c_void, 0) == @intToPtr(?*c_void, 0)); + testing.expect(cast(*u8, 16) == @intToPtr(*u8, 16)); + testing.expect(cast(u64, @as(u32, 10)) == @as(u64, 10)); + testing.expect(cast(E, 1) == .One); + testing.expect(cast(u8, E.Two) == 2); + testing.expect(cast(*u64, &i).* == @as(u64, 10)); +} |
