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 }