Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const std = @import("std");
- const mem = @import("std").mem;
- const typeinfo = @import("builtin").TypeInfo;
- const typeid = @import("builtin").TypeId;
- const Definition = typeinfo.Definition;
- const Data = Definition.Data;
- fn definitions(comptime any: type) []Definition {
- const type_kind = @typeInfo(any);
- switch (type_kind) {
- typeid.Struct => |info| {
- return info.defs;
- },
- typeid.Enum => |info| {
- return info.defs;
- },
- typeid.Union => |info| {
- return info.defs;
- },
- else => @compileError("Definitions are only available on Structs, Enums and Unions. Found type `" ++ @typeName(any) ++ "`."),
- }
- }
- fn definition_fn_names(comptime definition_list: []Definition) [][]const u8 {
- var names: [definition_list.len][]const u8 = undefined;
- var missers = 0;
- for (definition_list) |definition, idx| {
- switch (definition.data) {
- Data.Fn => {
- names[idx - missers] = definition.name;
- },
- else => missers += 1,
- }
- }
- return names[0..names.len - missers];
- }
- fn definition_fn_signatures(comptime definition_list: []Definition) [][]const u8 {
- var types: [definition_list.len][]const u8 = undefined;
- var missers = 0;
- for(definition_list) |definition, idx| {
- const data_type = switch(definition.data) {
- Data.Fn => |Fn| {
- types[idx - missers] = @typeName(Fn.fn_type);
- },
- else => missers += 1,
- };
- }
- return types[0..types.len - missers];
- }
- /// Has `Type` a function with the name `name`, and the signature of `signature` (signature is in []const u8)
- fn has_fn(comptime Type: type, name: []const u8, signature: []const u8) bool {
- // type_definition_names is a list of all the names of the functions of the trait,
- // type_definitions_fn_signatures a list of all the signatures (in []const u8).
- // These are seperate lists, but they are in order, and indexing into the same index corresponds to the same function.
- comptime var type_definitions = comptime definitions(Type);
- comptime var type_definitions_names = comptime definition_fn_names(type_definitions);
- comptime var type_definitions_fn_signatures = comptime definition_fn_signatures(type_definitions);
- for(type_definitions_names) |type_def_name, idx| {
- if (mem.eql(u8, type_def_name, name)) {
- if (mem.eql(u8, type_definitions_fn_signatures[idx], signature)) {
- return true;
- }
- }
- }
- return false;
- }
- fn require(comptime Type: type, comptime Trait: type) void {
- // trait_definition_names is a list of all the names of the functions of the trait,
- // trait_definitions_fn_signatures a list of all the signatures (in []const u8).
- // These are seperate lists, but they are in order, and indexing into the same index corresponds to the same function.
- comptime var trait_definitions = comptime definitions(Trait);
- comptime var trait_definitions_names = comptime definition_fn_names(trait_definitions);
- comptime var trait_definitions_fn_signatures = comptime definition_fn_signatures(trait_definitions);
- for (trait_definitions_names) |trait_def_name, idx| {
- if (!has_fn(Type, trait_def_name, trait_definitions_fn_signatures[idx])) {
- // signature starts with `fn`, but we dont wont to print that
- @compileError("Function `" ++ trait_def_name ++ "" ++ trait_definitions_fn_signatures[idx][2..] ++ "` from trait " ++ @typeName(Trait) ++ " not found in type `" ++ @typeName(Type) ++ "`." );
- }
- }
- }
- //////////////////////////////////
- ///////////// TRAITS /////////////
- //////////////////////////////////
- fn AsRef(comptime T: type, comptime Target: type) type {
- return struct {
- fn as_ref(self: *const T) *const Target {
- return self.as_ref();
- }
- };
- }
- fn AsMut(comptime T: type, comptime Target: type) type {
- comptime require(T, AsRef(T, Target));
- return struct {
- fn as_mut(self: *T) *Target {
- return self.as_mut();
- }
- };
- }
- //////////////////////////////////
- //////////////////////////////////
- //////////////////////////////////
- ///////// EXAMPLE STRUCT /////////
- //////////////////////////////////
- const Foo = struct {
- n: i64,
- fn as_ref(self: *const @This()) *const i64 {
- return &self.n;
- }
- fn as_mut(self: *@This()) *i64 {
- return &self.n;
- }
- };
- //////////////////////////////////
- //////////////////////////////////
- fn example(comptime S: type, s: *S) void {
- comptime require(S, AsMut(S, i64));
- s.as_mut().* += 1;
- }
- pub fn main() void {
- var foo = Foo {.n = 10,};
- example(Foo, &foo);
- std.debug.warn("{}\n", foo);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement