aboutsummaryrefslogtreecommitdiff
path: root/lib/std/meta.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-06-22 23:22:17 -0400
committerAndrew Kelley <andrew@ziglang.org>2020-06-22 23:22:17 -0400
commit6938245fcc1daa6a63bcfcb3ba1092d569efc875 (patch)
tree035b27a399c418cab679043f87282dc3de1ef5b1 /lib/std/meta.zig
parent7b68385d7d4448e81cc882d9a5464bf58d10dc0d (diff)
parent78c6d39cd49225bdfd2de4da7b1730ba26a41ba4 (diff)
downloadzig-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.zig94
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));
+}