1 module buffer.rpc.server; 2 3 import std.meta : staticIndexOf; 4 import std.traits; 5 import std.algorithm.searching; 6 import std.conv : to; 7 import std.variant; 8 9 import buffer.message; 10 11 class Server(Business) 12 { 13 static immutable string[] builtinFunctions = [ "__ctor", "__dtor", "opEquals", "opCmp", "toHash", "toString", "Monitor", "factory" ]; 14 private Business business = new Business(); 15 16 this() 17 { 18 business = new Business(); 19 } 20 21 ubyte[] Handler(string Package = string.init, Stuff...)(const ubyte[] data, Stuff stuff) 22 { 23 string name; 24 string method; 25 Variant[] params = Message.deserialize(data, name, method); 26 foreach (s; stuff) 27 { 28 params ~= Variant(s); 29 } 30 31 foreach (member; __traits(allMembers, Business)) 32 { 33 alias funcs = MemberFunctionsTuple!(Business, member); 34 35 static if (funcs.length > 0 && !canFind(builtinFunctions, member)) 36 { 37 static assert(funcs.length == 1, "The function of RPC call doesn't allow the overloads, function: " ~ member); 38 39 alias func = typeof(funcs[0]); 40 alias ParameterTypes = ParameterTypeTuple!func; 41 alias T = ReturnType!func; 42 43 static assert(is(T == void) || (staticIndexOf!(T, supportedBuiltinTypes) != -1) || ((BaseTypeTuple!T.length > 0) && is(BaseTypeTuple!T[0] == Message)), 44 "The function of RPC call return type is incorrect, function: " ~ member); 45 46 static if (Package != string.init) 47 { 48 mixin("import " ~ Package ~ ";"); 49 } 50 51 static if (is(T == void)) 52 { 53 mixin(` 54 if (method == "` ~ member ~ `") 55 { 56 if (params.length < ` ~ ParameterTypes.length.to!string ~ `) 57 { 58 import std.stdio : writeln; 59 writeln("Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 60 assert(0, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 61 } 62 63 business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 64 return null; 65 } 66 `); 67 } 68 else static if (isBuiltinType!T) 69 { 70 mixin(` 71 if (method == "` ~ member ~ `") 72 { 73 if (params.length < ` ~ ParameterTypes.length.to!string ~ `) 74 { 75 import std.stdio : writeln; 76 writeln("Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 77 assert(0, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 78 } 79 80 T ret = business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 81 return Message.serialize_without_msginfo(method, ret); 82 } 83 `); 84 } 85 else 86 { 87 mixin(` 88 if (method == "` ~ member ~ `") 89 { 90 if (params.length < ` ~ ParameterTypes.length.to!string ~ `) 91 { 92 import std.stdio : writeln; 93 writeln("Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 94 assert(0, "Incorrect number of parameters, ` ~ member ~ ` requires ` ~ ParameterTypes.length.to!string ~ ` parameters."); 95 } 96 97 T ret = business.` ~ member ~ `(` ~ combineParams!ParameterTypes ~ `); 98 return ((ret is null) ? null : ret.serialize()); 99 } 100 `); 101 } 102 } 103 } 104 105 // Server does not implement client call method. 106 return null; 107 } 108 109 private static string combineParams(ParameterTypes...)() 110 { 111 string s; 112 113 foreach (i, type; ParameterTypes) 114 { 115 if (i > 0) s ~= ", "; 116 117 s ~= ("params[" ~ i.to!string ~ "].get!" ~ type.stringof); 118 } 119 120 return s; 121 } 122 }