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 == bool) || is(T == char) 23 || 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 ushort messageId; 30 TypeInfo_Class messageName; 31 string res_method; 32 Variant[] res_params = Message.deserialize(response, messageId, messageName, res_method); 33 34 //assert(method == res_method); 35 36 static if (isBuiltinType!T) 37 { 38 assert(res_params.length == 1, "The number of response parameters from the server is incorrect."); 39 40 return res_params[0].get!T; 41 } 42 else 43 { 44 alias FieldTypes = FieldTypeTuple!T; 45 static assert(FieldTypes.length == params.length, "Incorrect number of parameters, " ~ T.stringof ~ " requires " ~ FieldTypes.length.to!string ~ " parameters."); 46 47 T message = new T(); 48 49 foreach (i, type; FieldTypes) 50 { 51 mixin(` 52 message.` ~ FieldNameTuple!T[i] ~ ` = res_params[` ~ i.to!string ~ `].get!` ~ type.stringof ~ `; 53 `); 54 } 55 56 return message; 57 } 58 } 59 }