1 module buffer.rpc.server; 2 3 import std.traits; 4 import std.algorithm.searching; 5 import std.conv : to; 6 import std.variant; 7 8 import buffer.message; 9 10 class Server(Business) 11 { 12 static immutable string[] builtinFunctions = [ "__ctor", "__dtor", "opEquals", "opCmp", "toHash", "toString", "Monitor", "factory" ]; 13 Business business = new Business(); 14 15 ubyte[] Handler(ubyte[] data) 16 { 17 ushort messageId; 18 TypeInfo_Class messageName; 19 string method; 20 Variant[] params = Message.deserialize(data, messageId, messageName, method); 21 22 if (params is null) 23 { 24 return null; 25 } 26 27 foreach (member; __traits(allMembers, Business)) 28 { 29 alias MemberFunctionsTuple!(Business, member) funcs; 30 31 static if (funcs.length > 0 && !canFind(builtinFunctions, member)) 32 { 33 static assert(funcs.length == 1, "The function of RPC call doesn't allow the overloads, function: " ~ member); 34 35 alias typeof(funcs[0]) func; 36 alias ParameterTypeTuple!func ParameterTypes; 37 alias ReturnType!func T; 38 39 static assert(( 40 is(T == byte) || is(T == ubyte) || is(T == short) || is(T == ushort) || is(T == int) || is(T == uint) 41 || is(T == long) || is(T == ulong) || is(T == float) || is(T == double) || is(T == bool) || is(T == char) 42 || is(T == string) || (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message))), 43 "The function of RPC call return type is incorrect, function: " ~ member); 44 45 static if (isBuiltinType!T) 46 { 47 mixin(` 48 if (method == "` ~ member ~ `") 49 { 50 assert(` ~ ParameterTypes.length.to!string ~ ` == params.length, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 51 T ret = business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 52 return Message.serialize_without_msginfo(method, ret); 53 } 54 `); 55 } 56 else 57 { 58 mixin(` 59 if (method == "` ~ member ~ `") 60 { 61 assert(` ~ ParameterTypes.length.to!string ~ ` == params.length, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 62 T ret = business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 63 return ret.serialize(); 64 } 65 `); 66 } 67 } 68 } 69 70 assert(0, "The server does not implement client call method: " ~ method); 71 } 72 73 static string combineParams(ParameterTypes...)() 74 { 75 string s; 76 77 foreach (i, type; ParameterTypes) 78 { 79 if (i > 0) 80 s ~= ", "; 81 s ~= ("params[" ~ i.to!string ~ "].get!" ~ type.stringof); 82 } 83 84 return s; 85 } 86 }