| ... | ... | @@ -1122,15 +1122,66 @@ pub inline fn hasFn(comptime T: type, comptime name: []const u8) bool { |
| 1122 | 1122 | return @typeInfo(@TypeOf(@field(T, name))) == .Fn; |
| 1123 | 1123 | } |
| 1124 | 1124 | |
| 1125 | test "hasFn" { |
| 1126 | const S1 = struct { |
| 1127 | pub fn foo() void {} |
| 1128 | }; |
| 1129 | |
| 1130 | try std.testing.expect(hasFn(S1, "foo")); |
| 1131 | try std.testing.expect(!hasFn(S1, "bar")); |
| 1132 | try std.testing.expect(!hasFn(*S1, "foo")); |
| 1133 | |
| 1134 | const S2 = struct { |
| 1135 | foo: fn () void, |
| 1136 | }; |
| 1137 | |
| 1138 | try std.testing.expect(!hasFn(S2, "foo")); |
| 1139 | } |
| 1140 | |
| 1125 | 1141 | /// Returns true if a type has a `name` method; `false` otherwise. |
| 1126 | 1142 | /// Result is always comptime-known. |
| 1127 | 1143 | pub inline fn hasMethod(comptime T: type, comptime name: []const u8) bool { |
| 1128 | 1144 | return switch (@typeInfo(T)) { |
| 1129 | | .Pointer => |P| hasFn(P.child, name), |
| 1145 | .Pointer => |P| switch (P.size) { |
| 1146 | .One => hasFn(P.child, name), |
| 1147 | .Many, .Slice, .C => false, |
| 1148 | }, |
| 1130 | 1149 | else => hasFn(T, name), |
| 1131 | 1150 | }; |
| 1132 | 1151 | } |
| 1133 | 1152 | |
| 1153 | test "hasMethod" { |
| 1154 | try std.testing.expect(!hasMethod(u32, "foo")); |
| 1155 | try std.testing.expect(!hasMethod([]u32, "len")); |
| 1156 | try std.testing.expect(!hasMethod(struct { u32, u64 }, "len")); |
| 1157 | |
| 1158 | const S1 = struct { |
| 1159 | pub fn foo() void {} |
| 1160 | }; |
| 1161 | |
| 1162 | try std.testing.expect(hasMethod(S1, "foo")); |
| 1163 | try std.testing.expect(hasMethod(*S1, "foo")); |
| 1164 | |
| 1165 | try std.testing.expect(!hasMethod(S1, "bar")); |
| 1166 | try std.testing.expect(!hasMethod(*[1]S1, "foo")); |
| 1167 | try std.testing.expect(!hasMethod(*[10]S1, "foo")); |
| 1168 | try std.testing.expect(!hasMethod([]S1, "foo")); |
| 1169 | |
| 1170 | const S2 = struct { |
| 1171 | foo: fn () void, |
| 1172 | }; |
| 1173 | |
| 1174 | try std.testing.expect(!hasMethod(S2, "foo")); |
| 1175 | |
| 1176 | const U = union { |
| 1177 | pub fn foo() void {} |
| 1178 | }; |
| 1179 | |
| 1180 | try std.testing.expect(hasMethod(U, "foo")); |
| 1181 | try std.testing.expect(hasMethod(*U, "foo")); |
| 1182 | try std.testing.expect(!hasMethod(U, "bar")); |
| 1183 | } |
| 1184 | |
| 1134 | 1185 | /// True if every value of the type `T` has a unique bit pattern representing it. |
| 1135 | 1186 | /// In other words, `T` has no unused bits and no padding. |
| 1136 | 1187 | /// Result is always comptime-known. |