inline std::pair execute()

in include/ylt/coro_rpc/impl/rpc_execute.hpp [54:158]


inline std::pair<coro_rpc::err_code, std::string> execute(
    std::string_view data, rpc_context<rpc_protocol> &context_info,
    Self *self = nullptr) {
  using namespace std::string_literals;
  using T = decltype(func);
  using param_type = util::function_parameters_t<T>;
  using return_type = util::function_return_type_t<T>;

  if constexpr (!std::is_void_v<param_type>) {
    using First = std::tuple_element_t<0, param_type>;
    constexpr bool is_conn = requires { typename First::return_type; };
    if constexpr (is_conn) {
      static_assert(std::is_void_v<return_type>,
                    "The return_type must be void");
    }

    using conn_return_type = decltype(get_return_type<is_conn, First>());
    constexpr bool has_coro_conn_v =
        std::is_convertible_v<context_base<conn_return_type, rpc_protocol>,
                              First>;
    auto args = util::get_args<has_coro_conn_v, param_type>();

    bool is_ok = true;
    constexpr size_t size = std::tuple_size_v<decltype(args)>;
    if constexpr (size > 0) {
      is_ok = serialize_proto::deserialize_to(args, data);
    }

    if (!is_ok)
      AS_UNLIKELY {
        return std::pair{err_code{errc::invalid_rpc_arguments},
                         "invalid rpc arg"s};
      }

    if constexpr (std::is_void_v<return_type>) {
      if constexpr (std::is_void_v<Self>) {
        if constexpr (has_coro_conn_v) {
          // call void func(coro_conn, args...)
          std::apply(func, std::tuple_cat(
                               std::forward_as_tuple(
                                   context_base<conn_return_type, rpc_protocol>(
                                       context_info)),
                               std::move(args)));
        }
        else {
          // call void func(args...)
          std::apply(func, std::move(args));
        }
      }
      else {
        if constexpr (has_coro_conn_v) {
          // call void self->func(coro_conn, args...)
          std::apply(
              func, std::tuple_cat(
                        std::forward_as_tuple(
                            *self, context_base<conn_return_type, rpc_protocol>(
                                       context_info)),
                        std::move(args)));
        }
        else {
          // call void self->func(args...)
          std::apply(func, std::tuple_cat(std::forward_as_tuple(*self),
                                          std::move(args)));
        }
      }
      return std::pair{err_code{}, serialize_proto::serialize()};
    }
    else {
      if constexpr (std::is_void_v<Self>) {
        // call return_type func(args...)

        return std::pair{err_code{}, serialize_proto::serialize(
                                         std::apply(func, std::move(args)))};
      }
      else {
        // call return_type self->func(args...)

        return std::pair{err_code{},
                         serialize_proto::serialize(std::apply(
                             func, std::tuple_cat(std::forward_as_tuple(*self),
                                                  std::move(args))))};
      }
    }
  }
  else {
    if constexpr (std::is_void_v<return_type>) {
      if constexpr (std::is_void_v<Self>) {
        func();
      }
      else {
        (self->*func)();
      }
      return std::pair{err_code{}, serialize_proto::serialize()};
    }
    else {
      if constexpr (std::is_void_v<Self>) {
        return std::pair{err_code{}, serialize_proto::serialize(func())};
      }
      else {
        return std::pair{err_code{},
                         serialize_proto::serialize((self->*func)())};
      }
    }
  }
}