1 /** 2 * tools to get Interface meta info for auto-generate implementation. 3 * 4 * Copied from https://github.com/boolangery/d-autointf 5 * Modified to remove extra vibe.d dependency for better footprint size. 6 * 7 * Copyright: © 2018 Eliott Dumeix 8 * License: Subject to the terms of the MIT license 9 * 10 */ 11 module trpc.ifinfo; 12 13 14 import std.traits : hasUDA, moduleName; 15 16 /** 17 * No-Auto-Implement attribute 18 */ 19 package struct NoAutoImplMethod { 20 } 21 22 /** 23 * noImpl attribute 24 */ 25 NoAutoImplMethod noImpl() @safe 26 { 27 return NoAutoImplMethod(); 28 } 29 30 /* attributes utils */ 31 private enum isEnabledMethod(alias M) = !hasUDA!(M, NoAutoImplMethod); 32 33 /// Method Param 34 struct MethodParam { 35 string name; /// param name 36 string type; /// param type 37 string storetype; /// param storage-type : in or out 38 } 39 40 /// Method info 41 struct MethodInfo { 42 string name; /// method name 43 MethodParam[] params; /// method params 44 string rettype; /// method return type 45 string[] _customtypes; /// method related user defined types 46 } 47 48 /// Get Interfaces Info for a class or pure interface. 49 struct IfInfo(T) if (is(T == class) || is(T == interface)) 50 { 51 import std.traits : InterfacesTuple, Parameters, ReturnType, 52 ParameterStorageClassTuple, ParameterStorageClass, ParameterIdentifierTuple, isBuiltinType; 53 import std.typetuple : TypeTuple; 54 55 alias _interfaces = InterfacesTuple!(T); 56 57 static if (is(T == interface)) 58 alias I = T; 59 else 60 alias I = _interfaces[0]; 61 62 /// members 63 static immutable membernames = [__traits(allMembers, I)]; 64 65 //pragma(msg, "member is ", membernames); 66 67 /// Aliases to all interface methods (Compile-time). 68 alias Members = GetMembers!(); 69 70 /** Aliases for each method (Compile-time). 71 This tuple has the same number of entries as `methods`. */ 72 alias Methods = GetMethods!(); 73 74 /// Number of methods 75 enum mthcnt = membernames.length; 76 77 /// the method Infos of an Interface or Class 78 MethodInfo[mthcnt] methodInfos; 79 80 /// Fills the struct with information. 81 this(int dummy) { 82 getInfos(); 83 } 84 85 // copying this struct is costly, so we forbid it 86 @disable this(this); 87 88 /// Get all interface method infos. 89 MethodInfo[] getInfos() { 90 foreach (i, f; Methods) { 91 methodInfos[i].name = membernames[i]; 92 alias _paramtypes = Parameters!f; 93 alias _paramident = ParameterIdentifierTuple!f; 94 alias _paramstoretype = ParameterStorageClassTuple!f; 95 //pragma(msg, "ptype: ", _paramtypes); 96 //pragma(msg, "paramstoretype: ", _paramstoretype); 97 foreach (pi, p; _paramtypes) { 98 MethodParam pr; 99 pr.type = p.stringof; 100 if (! isBuiltinType!p) { 101 methodInfos[i]._customtypes ~= p.stringof; 102 } 103 pr.name = _paramident[pi]; 104 if (_paramstoretype[pi] == ParameterStorageClass.out_) 105 pr.storetype = "out"; 106 else if (_paramstoretype[pi] == ParameterStorageClass.ref_) 107 pr.storetype = "ref"; 108 else if (_paramstoretype[pi] == ParameterStorageClass.return_) 109 pr.storetype = "return"; 110 else if (_paramstoretype[pi] == ParameterStorageClass.none) 111 pr.storetype = "none"; 112 static if (__VERSION__ > 2093L) { 113 if (_paramstoretype[pi] == ParameterStorageClass.in_) 114 pr.storetype = "in"; 115 } 116 methodInfos[i].params ~= pr; 117 } 118 methodInfos[i].rettype = ReturnType!f.stringof; 119 if (! isBuiltinType!(ReturnType!f)) { 120 methodInfos[i]._customtypes ~= methodInfos[i].rettype; 121 } 122 } 123 124 return methodInfos; 125 } 126 127 private template SubInterfaceType(alias F) { 128 import std.traits : ReturnType, isInstanceOf; 129 130 alias RT = ReturnType!F; 131 static if (is(RT == interface)) 132 alias SubInterfaceType = RT; 133 else 134 alias SubInterfaceType = void; 135 } 136 137 private template GetMembers() { 138 import std.traits : MemberFunctionsTuple; 139 template Impl(size_t idx) { 140 static if (idx < membernames.length) { 141 enum name = membernames[idx]; 142 static if (name.length != 0) 143 alias Impl = TypeTuple!(MemberFunctionsTuple!(I, name), Impl!(idx + 1)); 144 else 145 alias Impl = Impl!(idx + 1); 146 } 147 else 148 alias Impl = TypeTuple!(); 149 } 150 151 alias GetMembers = Impl!0; 152 } 153 154 private template GetMethods() { 155 template Impl(size_t idx) { 156 static if (idx < Members.length) { 157 alias F = Members[idx]; 158 alias SI = SubInterfaceType!F; 159 static if (is(SI == void) && isEnabledMethod!F) 160 alias Impl = TypeTuple!(F, Impl!(idx + 1)); 161 else 162 alias Impl = Impl!(idx + 1); 163 } 164 else 165 alias Impl = TypeTuple!(); 166 } 167 168 alias GetMethods = Impl!0; 169 } 170 }