TEMPLATE MAGIC FOR GREAT JUSTICE
[invirt/third/libt4.git] / rpc / marshall.h
index 27cebbb..448240b 100644 (file)
@@ -219,13 +219,11 @@ class unmarshall {
                        _ind = RPC_HEADER_SZ;
                }
 
-        template <class OutputIterator>
-        void iterate(OutputIterator i, int n) {
-            while (n--) {
-                typename OutputIterator::value_type t;
-                *this >> t;
-                *i++ = t;
-            }
+        template <class A>
+        inline A grab() {
+            A a;
+            *this >> a;
+            return a;
         }
 };
 
@@ -285,4 +283,89 @@ operator>>(unmarshall &u, std::pair<A,B> &d) {
     return u >> d.first >> d.second;
 }
 
+template <size_t...> struct tuple_indices {};
+template <size_t S, class IntTuple, size_t E> struct make_indices_imp;
+template <size_t S, size_t ...Indices, size_t E> struct make_indices_imp<S, tuple_indices<Indices...>, E> {
+    typedef typename make_indices_imp<S+1, tuple_indices<Indices..., S>, E>::type type;
+};
+template <size_t E, size_t ...Indices> struct make_indices_imp<E, tuple_indices<Indices...>, E> {
+    typedef tuple_indices<Indices...> type;
+};
+template <size_t E, size_t S = 0> struct make_tuple_indices {
+    typedef typename make_indices_imp<S, tuple_indices<>, E>::type type;
+};
+
+struct VerifyOnFailure {
+    static inline int unmarshall_args_failure() {
+        VERIFY(0);
+        return 0;
+    }
+};
+
+typedef std::function<int(unmarshall &, marshall &)> handler;
+
+using std::move;
+using std::get;
+using std::tuple;
+using std::decay;
+
+#include <iostream>
+
+template <class F, class R, class args_type, size_t ...Indices>
+typename std::enable_if<!std::is_member_function_pointer<F>::value, int>::type
+invoke(F f, void *, R & r, args_type & t, tuple_indices<Indices...>) {
+    return f(r, move(get<Indices>(t))...);
+}
+
+template <class F, class C, class R, class args_type, size_t ...Indices>
+typename std::enable_if<std::is_member_function_pointer<F>::value, int>::type
+invoke(F f, C *c, R & r, args_type & t, tuple_indices<Indices...>) {
+    return (c->*f)(r, move(get<Indices>(t))...);
+}
+
+template <class Functor,
+          class Instance,
+          class Signature,
+          class ErrorHandler=VerifyOnFailure> struct marshalled_func_imp;
+
+template <class F, class C, class ErrorHandler, class R, class... Args>
+struct marshalled_func_imp<F, C, int(R&, Args...), ErrorHandler> {
+    using result_type = R;
+    using args_type = tuple<typename decay<Args>::type...>;
+    using index_type = typename make_tuple_indices<sizeof...(Args)>::type;
+
+    static inline int call(F f, C *c, unmarshall &u, marshall &m) {
+        args_type t{std::move(std::tuple<Args...>{u.grab<Args>()...})};
+        if (!u.okdone())
+            return ErrorHandler::unmarshall_args_failure();
+        R r;
+        int b = invoke(f, c, r, t, index_type());
+        m << r;
+        return b;
+    }
+
+    static inline handler *wrap(F f, C *c=nullptr) {
+        typename decay<F>::type f_ = f;
+        return new handler([f_, c](unmarshall &u, marshall &m) -> int {
+            return call(f_, c, u, m);
+        });
+    }
+};
+
+template <class Functor,
+          class Signature,
+          class ErrorHandler=VerifyOnFailure> struct marshalled_func;
+
+template <class F, class ErrorHandler, class... Args>
+struct marshalled_func<F, int(*)(Args...), ErrorHandler> :
+    public marshalled_func_imp<F, void, int(Args...), ErrorHandler> {};
+
+template <class F, class ErrorHandler, class C, class... Args>
+struct marshalled_func<F, int(C::*)(Args...), ErrorHandler> :
+    public marshalled_func_imp<F, C, int(Args...), ErrorHandler> {};
+
+template <class F, class ErrorHandler, class Signature>
+struct marshalled_func<F, std::function<Signature>, ErrorHandler> :
+    public marshalled_func_imp<F, void, Signature, ErrorHandler> {};
+
 #endif