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)())};
}
}
}
}