1 module buffer.rpc.client; 2 3 import std.traits; 4 import std.conv : to; 5 import std.variant; 6 7 import buffer.message; 8 9 alias TcpRequestHandler = ubyte[] delegate(ubyte[] data); 10 11 class Client 12 { 13 static TcpRequestHandler handler = null; 14 15 static void bindTcpRequestHandler(TcpRequestHandler handler) 16 { 17 Client.handler = handler; 18 } 19 20 static T call(T, Params...)(string method, Params params) if ( 21 is(T == byte) || is(T == ubyte) || is(T == short) || is(T == ushort) || is(T == int) || is(T == uint) 22 || is(T == long) || is(T == ulong) || is(T == float) || is(T == double) || is(T == real) || is(T == bool) 23 || is(T == char) || is(T == string)|| (BaseTypeTuple!T.length > 0 && is(BaseTypeTuple!T[0] == Message))) 24 { 25 assert(handler != null, "TcpRequestHandler must be bound."); 26 assert(method.length > 0, "Paramter method must be set."); 27 28 ubyte[] response = handler(Message.serialize_without_msginfo(method, params)); 29 string name; 30 string res_method; 31 Variant[] res_params = Message.deserialize(response, name, res_method); 32 33 //assert(method == res_method); 34 35 static if (isBuiltinType!T) 36 { 37 assert(res_params.length == 1, "The number of response parameters from the server is incorrect."); 38 39 return res_params[0].get!T; 40 } 41 else 42 { 43 alias FieldTypes = FieldTypeTuple!T; 44 static assert(FieldTypes.length == params.length, "Incorrect number of parameters, " ~ T.stringof ~ " requires " ~ FieldTypes.length.to!string ~ " parameters."); 45 46 T message = new T(); 47 48 foreach (i, type; FieldTypes) 49 { 50 mixin(` 51 message.` ~ FieldNameTuple!T[i] ~ ` = res_params[` ~ i.to!string ~ `].get!` ~ type.stringof ~ `; 52 `); 53 } 54 55 return message; 56 } 57 } 58 }