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 private Business business = new Business(); 14 15 this() 16 { 17 business = new Business(); 18 } 19 20 ubyte[] Handler(string Package = string.init, Stuff...)(ubyte[] data, Stuff stuff) 21 { 22 string name; 23 string method; 24 Variant[] params = Message.deserialize(data, name, method); 25 foreach (s; stuff) 26 { 27 params ~= Variant(s); 28 } 29 30 foreach (member; __traits(allMembers, Business)) 31 { 32 alias MemberFunctionsTuple!(Business, member) funcs; 33 34 static if (funcs.length > 0 && !canFind(builtinFunctions, member)) 35 { 36 static assert(funcs.length == 1, "The function of RPC call doesn't allow the overloads, function: " ~ member); 37 38 alias typeof(funcs[0]) func; 39 alias ParameterTypeTuple!func ParameterTypes; 40 alias ReturnType!func T; 41 42 static assert(( 43 is(T == byte) || is(T == ubyte) || is(T == short) || is(T == ushort) || is(T == int) || is(T == uint) 44 || is(T == long) || is(T == ulong) || is(T == float) || is(T == double) || is(T == real) || is(T == bool) 45 || is(T == char) || is(T == string) || ((BaseTypeTuple!T.length > 0) && is(BaseTypeTuple!T[0] == Message))), 46 "The function of RPC call return type is incorrect, function: " ~ member); 47 48 static if (Package != string.init) 49 { 50 mixin("import " ~ Package ~ ";"); 51 } 52 53 static if (isBuiltinType!T) 54 { 55 mixin(` 56 if (method == "` ~ member ~ `") 57 { 58 if (params.length < ` ~ ParameterTypes.length.to!string ~ `) 59 { 60 import std.stdio; 61 writeln("Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 62 assert(0, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` lengthString!(ParameterTypes.length)."); 63 } 64 65 T ret = business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 66 67 return Message.serialize_without_msginfo(method, ret); 68 } 69 `); 70 } 71 else 72 { 73 mixin(` 74 if (method == "` ~ member ~ `") 75 { 76 if (params.length < ` ~ ParameterTypes.length.to!string ~ `) 77 { 78 import std.stdio; 79 writeln("Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 80 assert(0, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 81 } 82 83 T ret = business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 84 85 if (ret is null) 86 { 87 return null; 88 } 89 90 return ret.serialize(); 91 } 92 `); 93 } 94 } 95 } 96 97 assert(0, "The server does not implement client call method: " ~ method); 98 } 99 100 private static string combineParams(ParameterTypes...)() 101 { 102 string s; 103 104 foreach (i, type; ParameterTypes) 105 { 106 if (i > 0) s ~= ", "; 107 108 s ~= ("params[" ~ i.to!string ~ "].get!" ~ type.stringof); 109 } 110 111 return s; 112 } 113 }