1#ifndef HandleMessage_h
2#define HandleMessage_h
3
4#include "Arguments.h"
5#include "MessageDecoder.h"
6#include "MessageEncoder.h"
7#include <wtf/StdLibExtras.h>
8
9namespace IPC {
10
11// Dispatch functions with no reply arguments.
12
13template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
14void callMemberFunctionImpl(C* object, MF function, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
15{
16    (object->*function)(std::get<ArgsIndex>(args)...);
17}
18
19template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
20void callMemberFunction(ArgsTuple&& args, C* object, MF function)
21{
22    callMemberFunctionImpl(object, function, std::forward<ArgsTuple>(args), ArgsIndicies());
23}
24
25// Dispatch functions with reply arguments.
26
27template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex, typename ReplyArgsTuple, size_t... ReplyArgsIndex>
28void callMemberFunctionImpl(C* object, MF function, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence<ArgsIndex...>, std::index_sequence<ReplyArgsIndex...>)
29{
30    (object->*function)(std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., std::get<ReplyArgsIndex>(replyArgs)...);
31}
32
33template <typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence<std::tuple_size<ReplyArgsTuple>::value>>
34void callMemberFunction(ArgsTuple&& args, ReplyArgsTuple& replyArgs, C* object, MF function)
35{
36    callMemberFunctionImpl(object, function, std::forward<ArgsTuple>(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies());
37}
38
39// Dispatch functions with delayed reply arguments.
40
41template <typename C, typename MF, typename R, typename ArgsTuple, size_t... ArgsIndex>
42void callMemberFunctionImpl(C* object, MF function, PassRefPtr<R> delayedReply, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
43{
44    (object->*function)(std::get<ArgsIndex>(args)..., delayedReply);
45}
46
47template<typename C, typename MF, typename R, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
48void callMemberFunction(ArgsTuple&& args, PassRefPtr<R> delayedReply, C* object, MF function)
49{
50    callMemberFunctionImpl(object, function, delayedReply, std::forward<ArgsTuple>(args), ArgsIndicies());
51}
52
53// Dispatch functions with connection parameter with no reply arguments.
54
55template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
56void callMemberFunctionImpl(C* object, MF function, Connection* connection, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
57{
58    (object->*function)(connection, std::get<ArgsIndex>(args)...);
59}
60
61template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
62void callMemberFunction(Connection* connection, ArgsTuple&& args, C* object, MF function)
63{
64    callMemberFunctionImpl(object, function, connection, std::forward<ArgsTuple>(args), ArgsIndicies());
65}
66
67// Dispatch functions with connection parameter with reply arguments.
68
69template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex, typename ReplyArgsTuple, size_t... ReplyArgsIndex>
70void callMemberFunctionImpl(C* object, MF function, Connection* connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence<ArgsIndex...>, std::index_sequence<ReplyArgsIndex...>)
71{
72    (object->*function)(connection, std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., std::get<ReplyArgsIndex>(replyArgs)...);
73}
74
75template <typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence<std::tuple_size<ReplyArgsTuple>::value>>
76void callMemberFunction(Connection* connection, ArgsTuple&& args, ReplyArgsTuple& replyArgs, C* object, MF function)
77{
78    callMemberFunctionImpl(object, function, connection, std::forward<ArgsTuple>(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies());
79}
80
81// Variadic dispatch functions.
82
83template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex>
84void callMemberFunctionImpl(C* object, MF function, MessageDecoder& decoder, ArgsTuple&& args, std::index_sequence<ArgsIndex...>)
85{
86    (object->*function)(std::get<ArgsIndex>(args)..., decoder);
87}
88
89template<typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>>
90void callMemberFunction(ArgsTuple&& args, MessageDecoder& decoder, C* object, MF function)
91{
92    callMemberFunctionImpl(object, function, decoder, std::forward<ArgsTuple>(args), ArgsIndicies());
93}
94
95// Variadic dispatch functions with non-variadic reply arguments.
96
97template <typename C, typename MF, typename ArgsTuple, size_t... ArgsIndex, typename ReplyArgsTuple, size_t... ReplyArgsIndex>
98void callMemberFunctionImpl(C* object, MF function, MessageDecoder& decoder, ArgsTuple&& args, ReplyArgsTuple& replyArgs, std::index_sequence<ArgsIndex...>, std::index_sequence<ReplyArgsIndex...>)
99{
100    (object->*function)(std::get<ArgsIndex>(std::forward<ArgsTuple>(args))..., decoder, std::get<ReplyArgsIndex>(replyArgs)...);
101}
102
103template <typename C, typename MF, typename ArgsTuple, typename ArgsIndicies = std::make_index_sequence<std::tuple_size<ArgsTuple>::value>, typename ReplyArgsTuple, typename ReplyArgsIndicies = std::make_index_sequence<std::tuple_size<ReplyArgsTuple>::value>>
104void callMemberFunction(ArgsTuple&& args, MessageDecoder& decoder, ReplyArgsTuple& replyArgs, C* object, MF function)
105{
106    callMemberFunctionImpl(object, function, decoder, std::forward<ArgsTuple>(args), replyArgs, ArgsIndicies(), ReplyArgsIndicies());
107}
108
109// Main dispatch functions
110
111template<typename T, typename C, typename MF>
112void handleMessage(MessageDecoder& decoder, C* object, MF function)
113{
114    typename T::DecodeType arguments;
115    if (!decoder.decode(arguments)) {
116        ASSERT(decoder.isInvalid());
117        return;
118    }
119
120    callMemberFunction(WTF::move(arguments), object, function);
121}
122
123template<typename T, typename C, typename MF>
124void handleMessage(MessageDecoder& decoder, MessageEncoder& replyEncoder, C* object, MF function)
125{
126    typename T::DecodeType arguments;
127    if (!decoder.decode(arguments)) {
128        ASSERT(decoder.isInvalid());
129        return;
130    }
131
132    typename T::Reply::ValueType replyArguments;
133    callMemberFunction(WTF::move(arguments), replyArguments, object, function);
134    replyEncoder << replyArguments;
135}
136
137template<typename T, typename C, typename MF>
138void handleMessage(Connection* connection, MessageDecoder& decoder, MessageEncoder& replyEncoder, C* object, MF function)
139{
140    typename T::DecodeType arguments;
141    if (!decoder.decode(arguments)) {
142        ASSERT(decoder.isInvalid());
143        return;
144    }
145
146    typename T::Reply::ValueType replyArguments;
147    callMemberFunction(connection, WTF::move(arguments), replyArguments, object, function);
148    replyEncoder << replyArguments;
149}
150
151template<typename T, typename C, typename MF>
152void handleMessage(Connection* connection, MessageDecoder& decoder, C* object, MF function)
153{
154    typename T::DecodeType arguments;
155    if (!decoder.decode(arguments)) {
156        ASSERT(decoder.isInvalid());
157        return;
158    }
159    callMemberFunction(connection, WTF::move(arguments), object, function);
160}
161
162template<typename T, typename C, typename MF>
163void handleMessageVariadic(MessageDecoder& decoder, C* object, MF function)
164{
165    typename T::DecodeType arguments;
166    if (!decoder.decode(arguments)) {
167        ASSERT(decoder.isInvalid());
168        return;
169    }
170    callMemberFunction(WTF::move(arguments), decoder, object, function);
171}
172
173template<typename T, typename C, typename MF>
174void handleMessageVariadic(MessageDecoder& decoder, MessageEncoder& replyEncoder, C* object, MF function)
175{
176    typename T::DecodeType arguments;
177    if (!decoder.decode(arguments)) {
178        ASSERT(decoder.isInvalid());
179        return;
180    }
181
182    typename T::Reply::ValueType replyArguments;
183    callMemberFunction(WTF::move(arguments), decoder, replyArguments, object, function);
184    replyEncoder << replyArguments;
185}
186
187template<typename T, typename C, typename MF>
188void handleMessageDelayed(Connection* connection, MessageDecoder& decoder, std::unique_ptr<MessageEncoder>& replyEncoder, C* object, MF function)
189{
190    typename T::DecodeType arguments;
191    if (!decoder.decode(arguments)) {
192        ASSERT(decoder.isInvalid());
193        return;
194    }
195
196    RefPtr<typename T::DelayedReply> delayedReply = adoptRef(new typename T::DelayedReply(connection, WTF::move(replyEncoder)));
197    callMemberFunction(WTF::move(arguments), delayedReply.release(), object, function);
198}
199
200} // namespace IPC
201
202#endif // HandleMessage_h
203