init repo.

This commit is contained in:
tqcq
2024-02-23 18:07:37 +08:00
commit 1a9e41d167
512 changed files with 191774 additions and 0 deletions

View File

@ -0,0 +1,10 @@
#pragma once
// first include
#include "rpc_core/serialize.hpp"
// other include
#include "rpc_core/connection.hpp"
#include "rpc_core/dispose.hpp"
#include "rpc_core/request.hpp"
#include "rpc_core/rpc.hpp"

View File

@ -0,0 +1,3 @@
#pragma once
#include "version.hpp"

View File

@ -0,0 +1,86 @@
#pragma once
#include <functional>
#include <string>
#include <utility>
// config
#include "config.hpp"
// include
#include "detail/data_packer.hpp"
#include "detail/noncopyable.hpp"
namespace rpc_core {
/**
* Defines interfaces for sending and receiving messages
* Usage:
* 1. Both sending and receiving should ensure that a complete package of data is sent/received.
* 2. Call on_recv_package when a package of data is actually received.
* 3. Provide the implementation of sending data, send_package_impl.
*/
struct connection : detail::noncopyable {
std::function<void(std::string)> send_package_impl;
std::function<void(std::string)> on_recv_package;
};
/**
* Default connection avoid crash
*/
struct default_connection : connection {
default_connection() {
send_package_impl = [](const std::string &payload) {
RPC_CORE_LOGE("need send_package_impl: %zu", payload.size());
};
on_recv_package = [](const std::string &payload) {
RPC_CORE_LOGE("need on_recv_package: %zu", payload.size());
};
}
};
/**
* Loopback connection for testing
*/
struct loopback_connection : public connection {
loopback_connection() {
send_package_impl = [this](std::string payload) {
on_recv_package(std::move(payload));
};
}
};
/**
* Stream connection
* for bytes stream: tcp socket, serial port, etc.
*/
struct stream_connection : public connection {
explicit stream_connection(uint32_t max_body_size = UINT32_MAX) : data_packer_(max_body_size) {
send_package_impl = [this](const std::string &package) {
auto payload = data_packer_.pack(package);
send_bytes_impl(std::move(payload));
};
data_packer_.on_data = [this](std::string payload) {
on_recv_package(std::move(payload));
};
on_recv_bytes = [this](const void *data, size_t size) {
data_packer_.feed(data, size);
};
}
/**
* should call on connected or disconnected
*/
void reset() {
data_packer_.reset();
}
public:
std::function<void(std::string)> send_bytes_impl;
std::function<void(const void *data, size_t size)> on_recv_bytes;
private:
detail::data_packer data_packer_;
};
} // namespace rpc_core

View File

@ -0,0 +1,58 @@
#pragma once
#include <cstddef>
#include <functional>
#include "function.hpp"
#include "functor.hpp"
#include "helpers.hpp"
#include "member_function.hpp"
namespace rpc_core {
// There are three basic kinds of callable types
// function types
struct function_tag {};
// function pointer types
struct function_ptr_tag {};
// classes with operator()
struct functor_tag {};
namespace detail {
/** Define traits for a operator() member function pointer type */
// classes with operator()
template <typename Callable>
struct callable_traits : functor_traits<Callable> {
typedef functor_tag callable_category;
};
// functions
template <typename Ret, typename... Args>
struct callable_traits<Ret(Args...)> : function_traits<Ret(Args...)> {
typedef function_tag callable_category;
};
// function pointers
template <typename Ret, typename... Args>
struct callable_traits<Ret (*)(Args...)> : function_traits<Ret(Args...)> {
typedef function_ptr_tag callable_category;
};
} // namespace detail
// Main template
/** Traits for a callable (function/functor/lambda/...) */
template <typename Callable>
struct callable_traits : detail::callable_traits<detail::remove_cvref_t<Callable>> {};
/** Convert a callable to a std::function<> */
template <typename Callable>
std::function<typename callable_traits<Callable>::function_type> to_stdfunction(Callable fun) {
std::function<typename callable_traits<Callable>::function_type> stdfun(std::forward<Callable>(fun));
return stdfun;
}
} // namespace rpc_core

View File

@ -0,0 +1,40 @@
#pragma once
#include <cstddef>
#include "helpers.hpp"
namespace rpc_core {
namespace detail {
namespace {
/** Define traits for a function type */
template <typename Fun>
struct function_traits;
template <typename Ret, typename... Args>
struct function_traits<Ret(Args...)> {
typedef Ret function_type(Args...);
typedef Ret return_type;
static constexpr std::size_t argc = types_count<Args...>::value;
template <std::size_t N>
using argument_type = typename types_n<N, Args...>::type;
};
template <typename Ret, typename... Args>
const std::size_t function_traits<Ret(Args...)>::argc;
} // namespace
} // namespace detail
template <typename Func>
struct function_traits : detail::function_traits<detail::remove_cvref_t<Func>> {};
template <typename Func>
struct function_traits<Func*> : detail::function_traits<detail::remove_cvref_t<Func>> {};
} // namespace rpc_core

View File

@ -0,0 +1,25 @@
#pragma once
#include "function.hpp"
#include "helpers.hpp"
#include "member_function.hpp"
namespace rpc_core {
namespace detail {
template <typename Class>
using call_operator_traits = member_function_traits<decltype(&Class::operator())>;
// classes with operator()
template <typename Class>
struct functor_traits : function_traits<typename call_operator_traits<Class>::function_type> {
typedef call_operator_traits<Class> call_operator;
};
} // namespace detail
template <typename Class>
struct functor_traits : detail::functor_traits<detail::remove_cvref_t<Class>> {};
} // namespace rpc_core

View File

@ -0,0 +1,58 @@
#pragma once
#include <cstddef>
namespace rpc_core {
namespace detail {
/** Remove reference and cv qualification */
template <typename T>
using remove_cvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
/** Count the number of types given to the template */
template <typename... Types>
struct types_count;
template <>
struct types_count<> {
static constexpr std::size_t value = 0;
};
template <typename Type, typename... Types>
struct types_count<Type, Types...> {
static constexpr std::size_t value = types_count<Types...>::value + 1;
};
/** Get the nth type given to the template */
template <std::size_t n, typename... Types>
struct types_n;
template <std::size_t N, typename Type, typename... Types>
struct types_n<N, Type, Types...> : types_n<N - 1, Types...> {};
template <typename Type, typename... Types>
struct types_n<0, Type, Types...> {
typedef Type type;
};
/** Test if a type is in a list given types */
template <typename Q, typename... Ts>
struct types_has;
template <typename Q>
struct types_has<Q> {
static constexpr bool value = false;
};
template <typename Q, typename... Ts>
struct types_has<Q, Q, Ts...> {
static constexpr bool value = true;
};
template <typename Q, typename T, typename... Ts>
struct types_has<Q, T, Ts...> : types_has<Q, Ts...> {};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,139 @@
#pragma once
#include "helpers.hpp"
namespace rpc_core {
namespace detail {
// Tags for member function qualifiers
struct const_tag {};
struct volatile_tag {};
struct lref_tag {};
struct rref_tag {};
struct noexcept_tag {};
namespace {
template <typename Class, typename Func, typename... Qual>
struct member_function_traits_q : function_traits<Func> {
typedef Class class_type;
static constexpr bool is_const = types_has<const_tag, Qual...>::value;
static constexpr bool is_volatile = types_has<volatile_tag, Qual...>::value;
static constexpr bool is_lref = types_has<lref_tag, Qual...>::value;
static constexpr bool is_rref = types_has<rref_tag, Qual...>::value;
#if __cpp_noexcept_function_type
static constexpr bool is_noexcept = types_has<noexcept_tag, Qual...>::value;
#endif
};
// We need these until C++17 in case someone takes the address of one
// of those static variables or passses it by reference to a function
template <typename Class, typename Func, typename... Qual>
const bool member_function_traits_q<Class, Func, Qual...>::is_const;
template <typename Class, typename Func, typename... Qual>
const bool member_function_traits_q<Class, Func, Qual...>::is_volatile;
template <typename Class, typename Func, typename... Qual>
const bool member_function_traits_q<Class, Func, Qual...>::is_lref;
template <typename Class, typename Func, typename... Qual>
const bool member_function_traits_q<Class, Func, Qual...>::is_rref;
#if __cpp_noexcept_function_type
template <typename Class, typename Func, typename... Qual>
const bool member_function_traits_q<Class, Func, Qual...>::is_noexcept;
#endif
} // namespace
template <typename MemFun>
struct member_function_traits;
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...)> : member_function_traits_q<Class, Ret(Args...)> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const> : member_function_traits_q<Class, Ret(Args...), const_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) volatile> : member_function_traits_q<Class, Ret(Args...), volatile_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const volatile> : member_function_traits_q<Class, Ret(Args...), const_tag, volatile_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) &> : member_function_traits_q<Class, Ret(Args...), lref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const &> : member_function_traits_q<Class, Ret(Args...), const_tag, lref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) volatile &> : member_function_traits_q<Class, Ret(Args...), volatile_tag, lref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const volatile &>
: member_function_traits_q<Class, Ret(Args...), const_tag, volatile_tag, lref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) &&> : member_function_traits_q<Class, Ret(Args...), rref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const &&> : member_function_traits_q<Class, Ret(Args...), const_tag, rref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) volatile &&> : member_function_traits_q<Class, Ret(Args...), volatile_tag, rref_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const volatile &&>
: member_function_traits_q<Class, Ret(Args...), const_tag, volatile_tag, rref_tag> {};
#if __cpp_noexcept_function_type
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) noexcept> : member_function_traits_q<Class, Ret(Args...), noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const noexcept> : member_function_traits_q<Class, Ret(Args...), const_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) volatile noexcept> : member_function_traits_q<Class, Ret(Args...), volatile_tag, noexcept_tag> {
};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const volatile noexcept>
: member_function_traits_q<Class, Ret(Args...), const_tag, volatile_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) & noexcept> : member_function_traits_q<Class, Ret(Args...), lref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const & noexcept>
: member_function_traits_q<Class, Ret(Args...), const_tag, lref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) volatile & noexcept>
: member_function_traits_q<Class, Ret(Args...), volatile_tag, lref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const volatile & noexcept>
: member_function_traits_q<Class, Ret(Args...), const_tag, volatile_tag, lref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) && noexcept> : member_function_traits_q<Class, Ret(Args...), rref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const && noexcept>
: member_function_traits_q<Class, Ret(Args...), const_tag, rref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) volatile && noexcept>
: member_function_traits_q<Class, Ret(Args...), volatile_tag, rref_tag, noexcept_tag> {};
template <typename Class, typename Ret, typename... Args>
struct member_function_traits<Ret (Class::*)(Args...) const volatile && noexcept>
: member_function_traits_q<Class, Ret(Args...), const_tag, volatile_tag, rref_tag, noexcept_tag> {};
#endif // __cpp_noexcept_function_type
} // namespace detail
template <typename MemFunPtr>
struct member_function_traits : detail::member_function_traits<detail::remove_cvref_t<MemFunPtr>> {};
} // namespace rpc_core

View File

@ -0,0 +1,56 @@
#pragma once
#include "msg_wrapper.hpp"
namespace rpc_core {
namespace detail {
class coder {
public:
static std::string serialize(const msg_wrapper& msg) {
std::string payload;
payload.reserve(PayloadMinLen + msg.cmd.size() + msg.data.size());
payload.append((char*)&msg.seq, 4);
uint16_t cmdLen = msg.cmd.length();
payload.append((char*)&cmdLen, 2);
payload.append((char*)msg.cmd.data(), cmdLen);
payload.append((char*)&msg.type, 1);
if (msg.request_payload) {
payload.append(*msg.request_payload);
} else {
payload.append(msg.data);
}
return payload;
}
static msg_wrapper deserialize(const std::string& payload, bool& ok) {
msg_wrapper msg;
if (payload.size() < PayloadMinLen) {
ok = false;
return msg;
}
char* p = (char*)payload.data();
const char* pend = payload.data() + payload.size();
msg.seq = *(seq_type*)p;
p += 4;
uint16_t cmdLen = *(uint16_t*)p;
p += 2;
if (p + cmdLen + 1 > pend) {
ok = false;
return msg;
}
msg.cmd.append(p, cmdLen);
p += cmdLen;
msg.type = *(msg_wrapper::msg_type*)(p);
p += 1;
msg.data.append(p, pend - p);
ok = true;
return msg;
}
private:
static const uint8_t PayloadMinLen = 4 /*seq*/ + 2 /*cmdLen*/ + 1 /*type*/;
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,17 @@
#pragma once
namespace rpc_core {
namespace detail {
class copyable {
public:
copyable(const copyable&) = default;
copyable& operator=(const copyable&) = default;
protected:
copyable() = default;
~copyable() = default;
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,120 @@
#pragma once
#include <cstdint>
#include <functional>
#include <string>
// #define RPC_CORE_LOG_SHOW_VERBOSE
#include "log.h"
#include "noncopyable.hpp"
namespace rpc_core {
namespace detail {
class data_packer : detail::noncopyable {
public:
explicit data_packer(uint32_t max_body_size = UINT32_MAX) : max_body_size_(max_body_size) {}
public:
bool pack(const void *data, size_t size, const std::function<bool(const void *data, size_t size)> &cb) const {
if (size > max_body_size_) {
return false;
}
auto ret = cb(&size, 4);
if (!ret) return false;
ret = cb(data, size);
if (!ret) return false;
return true;
}
std::string pack(const void *data, size_t size) const {
std::string payload;
if (size > max_body_size_) {
RPC_CORE_LOGW("size > max_body_size: %zu > %u", size, max_body_size_);
return payload;
}
payload.insert(0, (char *)&size, 4);
payload.insert(payload.size(), (char *)data, size);
return payload;
}
std::string pack(const std::string &data) const {
return pack(data.data(), data.size());
}
public:
bool feed(const void *data, size_t size) { // NOLINT(misc-no-recursion)
if (body_size_ != 0) {
feed_body(data, size);
return true;
}
/// wait header(4 bytes)
if (header_len_now_ + size < 4) {
buffer_.insert(buffer_.size(), (char *)data, size);
header_len_now_ += size;
return true;
}
/// herder data ready, start read body
// 1. read header, aka: body size
uint8_t header_len = 4 - header_len_now_;
size_t body_len = size - header_len;
for (int i = 0; i < header_len; ++i) {
buffer_.push_back(((char *)data)[i]);
}
body_size_ = *(uint32_t *)(buffer_.data());
buffer_.clear();
RPC_CORE_LOGV("feed: wait body_size: %u", body_size_);
if (body_size_ > max_body_size_) {
RPC_CORE_LOGW("body_size > max_body_size: %u > %u", body_size_, max_body_size_);
reset();
return false;
}
// 2. feed body
if (body_len != 0) {
feed_body((char *)data + header_len, body_len);
}
return true;
}
void reset() {
buffer_.clear();
buffer_.shrink_to_fit();
header_len_now_ = 0;
body_size_ = 0;
}
private:
void feed_body(const void *data, size_t size) { // NOLINT(misc-no-recursion)
if (buffer_.size() + size < body_size_) {
buffer_.insert(buffer_.size(), (char *)data, size);
} else {
size_t body_need = body_size_ - buffer_.size();
size_t body_left = size - body_need;
buffer_.insert(buffer_.size(), (char *)data, body_need);
if (on_data) on_data(std::move(buffer_));
reset();
if (body_left != 0) {
feed((char *)data + body_need, body_left);
}
}
}
public:
std::function<void(std::string)> on_data;
private:
uint32_t max_body_size_;
std::string buffer_;
uint32_t header_len_now_ = 0;
uint32_t body_size_ = 0;
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,272 @@
// 1. 全局控制
// L_O_G_NDEBUG 关闭DEBUG日志默认依据NDEBUG自动判断
// L_O_G_SHOW_DEBUG 强制开启DEBUG日志
// L_O_G_DISABLE_ALL 关闭所有日志
// L_O_G_DISABLE_COLOR 禁用颜色显示
// L_O_G_LINE_END_CRLF 默认是\n结尾 添加此宏将以\r\n结尾
// L_O_G_FOR_MCU 更适用于MCU环境
// L_O_G_NOT_EXIT_ON_FATAL FATAL默认退出程序 添加此宏将不退出
// L_O_G_SHOW_FULL_PATH 显示文件绝对路径
//
// c++11环境默认打开以下内容
// L_O_G_ENABLE_THREAD_SAFE 线程安全
// L_O_G_ENABLE_THREAD_ID 显示线程ID
// L_O_G_ENABLE_DATE_TIME 显示日期
// 分别可通过下列禁用
// L_O_G_DISABLE_THREAD_SAFE
// L_O_G_DISABLE_THREAD_ID
// L_O_G_DISABLE_DATE_TIME
// 可通过`L_O_G_GET_TID_CUSTOM`自定义获取线程ID的实现
//
// 2. 自定义实现
// L_O_G_PRINTF_CUSTOM 自定义输出实现
// 并添加实现`int L_O_G_PRINTF_CUSTOM(const char *fmt, ...)`
//
// 3. 在库中使用时
// 3.1. 替换`RPC_CORE_LOG`为库名
// 3.2. 定义`RPC_CORE_LOG_IN_LIB`
// 3.3. 可配置项
// RPC_CORE_LOG_SHOW_DEBUG 开启RPC_CORE_LOGD的输出
// RPC_CORE_LOG_SHOW_VERBOSE 显示RPC_CORE_LOGV的输出
// RPC_CORE_LOG_DISABLE_ALL 关闭所有日志
#pragma once
// clang-format off
#define RPC_CORE_LOG_IN_LIB
#if defined(RPC_CORE_LOG_DISABLE_ALL) || defined(L_O_G_DISABLE_ALL)
#define RPC_CORE_LOG(fmt, ...) ((void)0)
#define RPC_CORE_LOGT(tag, fmt, ...) ((void)0)
#define RPC_CORE_LOGI(fmt, ...) ((void)0)
#define RPC_CORE_LOGW(fmt, ...) ((void)0)
#define RPC_CORE_LOGE(fmt, ...) ((void)0)
#define RPC_CORE_LOGF(fmt, ...) ((void)0)
#define RPC_CORE_LOGD(fmt, ...) ((void)0)
#define RPC_CORE_LOGV(fmt, ...) ((void)0)
#else
#ifdef __cplusplus
#include <cstring>
#include <cstdlib>
#if __cplusplus >= 201103L
#if !defined(L_O_G_DISABLE_THREAD_SAFE) && !defined(L_O_G_ENABLE_THREAD_SAFE)
#define L_O_G_ENABLE_THREAD_SAFE
#endif
#if !defined(L_O_G_DISABLE_THREAD_ID) && !defined(L_O_G_ENABLE_THREAD_ID)
#define L_O_G_ENABLE_THREAD_ID
#endif
#if !defined(L_O_G_DISABLE_DATE_TIME) && !defined(L_O_G_ENABLE_DATE_TIME)
#define L_O_G_ENABLE_DATE_TIME
#endif
#endif
#else
#include <string.h>
#include <stdlib.h>
#endif
#ifdef L_O_G_LINE_END_CRLF
#define RPC_CORE_LOG_LINE_END "\r\n"
#else
#define RPC_CORE_LOG_LINE_END "\n"
#endif
#ifdef L_O_G_NOT_EXIT_ON_FATAL
#define RPC_CORE_LOG_EXIT_PROGRAM()
#else
#ifdef L_O_G_FOR_MCU
#define RPC_CORE_LOG_EXIT_PROGRAM() do{ for(;;); } while(0)
#else
#define RPC_CORE_LOG_EXIT_PROGRAM() exit(EXIT_FAILURE)
#endif
#endif
#ifdef L_O_G_SHOW_FULL_PATH
#define RPC_CORE_LOG_BASE_FILENAME (__FILE__)
#else
#ifdef __FILE_NAME__
#define RPC_CORE_LOG_BASE_FILENAME (__FILE_NAME__)
#else
#define RPC_CORE_LOG_BASE_FILENAME (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#endif
#endif
#define RPC_CORE_LOG_WITH_COLOR
#if defined(_WIN32) || (defined(__ANDROID__) && !defined(ANDROID_STANDALONE)) || defined(L_O_G_FOR_MCU)
#undef RPC_CORE_LOG_WITH_COLOR
#endif
#ifdef L_O_G_DISABLE_COLOR
#undef RPC_CORE_LOG_WITH_COLOR
#endif
#ifdef RPC_CORE_LOG_WITH_COLOR
#define RPC_CORE_LOG_COLOR_RED "\033[31m"
#define RPC_CORE_LOG_COLOR_GREEN "\033[32m"
#define RPC_CORE_LOG_COLOR_YELLOW "\033[33m"
#define RPC_CORE_LOG_COLOR_BLUE "\033[34m"
#define RPC_CORE_LOG_COLOR_CARMINE "\033[35m"
#define RPC_CORE_LOG_COLOR_CYAN "\033[36m"
#define RPC_CORE_LOG_COLOR_DEFAULT
#define RPC_CORE_LOG_COLOR_END "\033[m"
#else
#define RPC_CORE_LOG_COLOR_RED
#define RPC_CORE_LOG_COLOR_GREEN
#define RPC_CORE_LOG_COLOR_YELLOW
#define RPC_CORE_LOG_COLOR_BLUE
#define RPC_CORE_LOG_COLOR_CARMINE
#define RPC_CORE_LOG_COLOR_CYAN
#define RPC_CORE_LOG_COLOR_DEFAULT
#define RPC_CORE_LOG_COLOR_END
#endif
#define RPC_CORE_LOG_END RPC_CORE_LOG_COLOR_END RPC_CORE_LOG_LINE_END
#ifndef L_O_G_PRINTF
#ifndef RPC_CORE_LOG_PRINTF_DEFAULT
#if defined(__ANDROID__) && !defined(ANDROID_STANDALONE)
#include <android/log.h>
#define RPC_CORE_LOG_PRINTF_DEFAULT(...) __android_log_print(ANDROID_L##OG_DEBUG, "RPC_CORE_LOG", __VA_ARGS__)
#else
#define RPC_CORE_LOG_PRINTF_DEFAULT(...) printf(__VA_ARGS__)
#endif
#endif
#ifndef L_O_G_PRINTF_CUSTOM
#ifdef __cplusplus
#include <cstdio>
#else
#include <stdio.h>
#endif
#ifdef L_O_G_ENABLE_THREAD_SAFE
#ifndef L_O_G_NS_MUTEX
#define L_O_G_NS_MUTEX L_O_G_NS_MUTEX
#include <mutex>
// 1. struct instead of namespace, ensure single instance
struct L_O_G_NS_MUTEX {
static std::mutex& mutex() {
// 2. never delete, avoid destroy before user log
// 3. static memory, avoid memory fragmentation
static char memory[sizeof(std::mutex)];
static std::mutex& mutex = *(new (memory) std::mutex());
return mutex;
}
};
#endif
#define L_O_G_PRINTF(...) { \
std::lock_guard<std::mutex> lock(L_O_G_NS_MUTEX::mutex()); \
RPC_CORE_LOG_PRINTF_DEFAULT(__VA_ARGS__); \
}
#else
#define L_O_G_PRINTF(...) RPC_CORE_LOG_PRINTF_DEFAULT(__VA_ARGS__)
#endif
#else
extern int L_O_G_PRINTF_CUSTOM(const char *fmt, ...);
#define L_O_G_PRINTF(...) L_O_G_PRINTF_CUSTOM(__VA_ARGS__)
#endif
#endif
#ifdef L_O_G_ENABLE_THREAD_ID
#ifndef L_O_G_NS_GET_TID
#define L_O_G_NS_GET_TID L_O_G_NS_GET_TID
#include <cstdint>
#ifdef L_O_G_GET_TID_CUSTOM
extern uint32_t L_O_G_GET_TID_CUSTOM();
#elif defined(_WIN32)
#include <processthreadsapi.h>
struct L_O_G_NS_GET_TID {
static inline uint32_t get_tid() {
return GetCurrentThreadId();
}
};
#elif defined(__linux__)
#include <sys/syscall.h>
#include <unistd.h>
struct L_O_G_NS_GET_TID {
static inline uint32_t get_tid() {
return syscall(SYS_gettid);
}
};
#else /* for mac, bsd.. */
#include <pthread.h>
struct L_O_G_NS_GET_TID {
static inline uint32_t get_tid() {
uint64_t x;
pthread_threadid_np(nullptr, &x);
return (uint32_t)x;
}
};
#endif
#endif
#ifdef L_O_G_GET_TID_CUSTOM
#define RPC_CORE_LOG_THREAD_LABEL "%u "
#define RPC_CORE_LOG_THREAD_VALUE ,L_O_G_GET_TID_CUSTOM()
#else
#define RPC_CORE_LOG_THREAD_LABEL "%u "
#define RPC_CORE_LOG_THREAD_VALUE ,L_O_G_NS_GET_TID::get_tid()
#endif
#else
#define RPC_CORE_LOG_THREAD_LABEL
#define RPC_CORE_LOG_THREAD_VALUE
#endif
#ifdef L_O_G_ENABLE_DATE_TIME
#include <chrono>
#include <sstream>
#include <iomanip> // std::put_time
#ifndef L_O_G_NS_GET_TIME
#define L_O_G_NS_GET_TIME L_O_G_NS_GET_TIME
struct L_O_G_NS_GET_TIME {
static inline std::string get_time() {
auto now = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(now);
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
std::stringstream ss;
ss << std::put_time(std::localtime(&time), "%Y-%m-%d %H:%M:%S") << '.' << std::setw(3) << std::setfill('0') << ms.count();
return ss.str();
}
};
#endif
#define RPC_CORE_LOG_TIME_LABEL "%s "
#define RPC_CORE_LOG_TIME_VALUE ,L_O_G_NS_GET_TIME::get_time().c_str()
#else
#define RPC_CORE_LOG_TIME_LABEL
#define RPC_CORE_LOG_TIME_VALUE
#endif
#define RPC_CORE_LOG(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_GREEN RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[*]: %s:%d " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, ##__VA_ARGS__); } while(0)
#define RPC_CORE_LOGT(tag, fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_BLUE RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[" tag "]: %s:%d " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, ##__VA_ARGS__); } while(0)
#define RPC_CORE_LOGI(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_YELLOW RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[I]: %s:%d " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, ##__VA_ARGS__); } while(0)
#define RPC_CORE_LOGW(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_CARMINE RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[W]: %s:%d [%s] " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, __func__, ##__VA_ARGS__); } while(0) // NOLINT(bugprone-lambda-function-name)
#define RPC_CORE_LOGE(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_RED RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[E]: %s:%d [%s] " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, __func__, ##__VA_ARGS__); } while(0) // NOLINT(bugprone-lambda-function-name)
#define RPC_CORE_LOGF(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_CYAN RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[!]: %s:%d [%s] " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, __func__, ##__VA_ARGS__); RPC_CORE_LOG_EXIT_PROGRAM(); } while(0) // NOLINT(bugprone-lambda-function-name)
#if defined(RPC_CORE_LOG_IN_LIB) && !defined(RPC_CORE_LOG_SHOW_DEBUG) && !defined(L_O_G_NDEBUG)
#define RPC_CORE_LOG_NDEBUG
#endif
#if defined(L_O_G_NDEBUG) && !defined(RPC_CORE_LOG_NDEBUG)
#define RPC_CORE_LOG_NDEBUG
#endif
#if (defined(NDEBUG) || defined(RPC_CORE_LOG_NDEBUG)) && !defined(L_O_G_SHOW_DEBUG)
#define RPC_CORE_LOGD(fmt, ...) ((void)0)
#else
#define RPC_CORE_LOGD(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_DEFAULT RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[D]: %s:%d " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, ##__VA_ARGS__); } while(0)
#endif
#if defined(RPC_CORE_LOG_SHOW_VERBOSE)
#define RPC_CORE_LOGV(fmt, ...) do{ L_O_G_PRINTF(RPC_CORE_LOG_COLOR_DEFAULT RPC_CORE_LOG_TIME_LABEL RPC_CORE_LOG_THREAD_LABEL "[V]: %s:%d " fmt RPC_CORE_LOG_END RPC_CORE_LOG_TIME_VALUE RPC_CORE_LOG_THREAD_VALUE, RPC_CORE_LOG_BASE_FILENAME, __LINE__, ##__VA_ARGS__); } while(0)
#else
#define RPC_CORE_LOGV(fmt, ...) ((void)0)
#endif
#endif

View File

@ -0,0 +1,168 @@
#pragma once
#include <map>
#include <memory>
#include <utility>
#include "../connection.hpp"
#include "coder.hpp"
#include "log.h"
#include "noncopyable.hpp"
namespace rpc_core {
namespace detail {
class msg_dispatcher : noncopyable {
public:
using cmd_handle = std::function<std::pair<bool, msg_wrapper>(msg_wrapper)>;
using rsp_handle = std::function<bool(msg_wrapper)>;
using timeout_cb = std::function<void()>;
using timer_impl = std::function<void(uint32_t ms, timeout_cb)>;
public:
explicit msg_dispatcher(std::shared_ptr<connection> conn) : conn_(std::move(conn)) {
auto alive = std::weak_ptr<void>(is_alive_);
conn_->on_recv_package = ([this, RPC_CORE_MOVE_LAMBDA(alive)](const std::string& payload) {
if (alive.expired()) {
RPC_CORE_LOGD("msg_dispatcher expired");
return;
}
bool success;
auto msg = coder::deserialize(payload, success);
if (success) {
this->dispatch(std::move(msg));
} else {
RPC_CORE_LOGE("payload deserialize error");
}
});
}
private:
void dispatch(msg_wrapper msg) {
switch (msg.type & (msg_wrapper::command | msg_wrapper::response)) {
case msg_wrapper::command: {
// ping
const bool is_ping = msg.type & msg_wrapper::ping;
if (is_ping) {
RPC_CORE_LOGD("<= seq:%u type:ping", msg.seq);
msg.type = static_cast<msg_wrapper::msg_type>(msg_wrapper::response | msg_wrapper::pong);
RPC_CORE_LOGD("=> seq:%u type:pong", msg.seq);
conn_->send_package_impl(coder::serialize(msg));
return;
}
// command
RPC_CORE_LOGD("<= seq:%u cmd:%s", msg.seq, msg.cmd.c_str());
const auto& cmd = msg.cmd;
auto it = cmd_handle_map_.find(cmd);
if (it == cmd_handle_map_.cend()) {
RPC_CORE_LOGD("not subscribe cmd for: %s", cmd.c_str());
const bool need_rsp = msg.type & msg_wrapper::need_rsp;
if (need_rsp) {
RPC_CORE_LOGD("=> seq:%u type:rsp", msg.seq);
msg_wrapper rsp;
rsp.seq = msg.seq;
rsp.type = static_cast<msg_wrapper::msg_type>(msg_wrapper::msg_type::response | msg_wrapper::msg_type::no_such_cmd);
conn_->send_package_impl(coder::serialize(rsp));
}
return;
}
const auto& fn = it->second;
const bool need_rsp = msg.type & msg_wrapper::need_rsp;
auto resp = fn(msg);
if (need_rsp && resp.first) {
RPC_CORE_LOGD("=> seq:%u type:rsp", msg.seq);
conn_->send_package_impl(coder::serialize(resp.second));
}
} break;
case msg_wrapper::response: {
// pong or response
const bool isPong = msg.type & msg_wrapper::pong;
const auto handleMap = isPong ? &pong_handle_map_ : &rsp_handle_map_;
RPC_CORE_LOGD("<= seq:%u type:%s", msg.seq, (msg.type & detail::msg_wrapper::msg_type::pong) ? "pong" : "rsp");
auto it = handleMap->find(msg.seq);
if (it == handleMap->cend()) {
RPC_CORE_LOGD("no rsp for seq:%u", msg.seq);
break;
}
const auto& cb = it->second;
if (not cb) {
RPC_CORE_LOGE("rsp can not be null");
return;
}
if (cb(std::move(msg))) {
handleMap->erase(it);
RPC_CORE_LOGV("handleMap->size=%zu", handleMap->size());
} else {
RPC_CORE_LOGE("may deserialize error");
}
} break;
default:
RPC_CORE_LOGE("unknown type");
}
}
public:
inline void subscribe_cmd(const cmd_type& cmd, cmd_handle handle) {
RPC_CORE_LOGD("subscribe cmd:%s", cmd.c_str());
cmd_handle_map_[cmd] = std::move(handle);
}
void unsubscribe_cmd(const cmd_type& cmd) {
auto it = cmd_handle_map_.find(cmd);
if (it != cmd_handle_map_.cend()) {
RPC_CORE_LOGD("erase cmd:%s", cmd.c_str());
cmd_handle_map_.erase(it);
} else {
RPC_CORE_LOGD("not subscribe cmd for: %s", cmd.c_str());
}
}
void subscribe_rsp(seq_type seq, rsp_handle handle, RPC_CORE_MOVE_PARAM(timeout_cb) timeout_cb, uint32_t timeout_ms, bool is_ping) {
RPC_CORE_LOGD("subscribe_rsp seq:%u", seq);
if (handle == nullptr) return;
const auto handleMap = is_ping ? &pong_handle_map_ : &rsp_handle_map_;
(*handleMap)[seq] = std::move(handle);
if (timer_impl_ == nullptr) {
RPC_CORE_LOGW("no timeout will cause memory leak!");
return;
}
auto alive = std::weak_ptr<void>(is_alive_);
timer_impl_(timeout_ms, [handleMap, seq, RPC_CORE_MOVE_LAMBDA(timeout_cb), RPC_CORE_MOVE_LAMBDA(alive)] {
if (alive.expired()) {
RPC_CORE_LOGD("seq:%u timeout after destroy", seq);
return;
}
auto it = handleMap->find(seq);
if (it != handleMap->cend()) {
if (timeout_cb) {
timeout_cb();
}
handleMap->erase(seq);
RPC_CORE_LOGV("Timeout seq=%d, handleMap.size=%zu", seq, handleMap->size());
}
});
}
inline void set_timer_impl(timer_impl timer_impl) {
timer_impl_ = std::move(timer_impl);
}
private:
std::shared_ptr<connection> conn_;
std::map<cmd_type, cmd_handle> cmd_handle_map_;
std::map<seq_type, rsp_handle> rsp_handle_map_;
std::map<seq_type, rsp_handle> pong_handle_map_;
timer_impl timer_impl_;
std::shared_ptr<void> is_alive_ = std::make_shared<uint8_t>();
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,59 @@
#pragma once
#include <string>
#include <utility>
#include "../type.hpp"
#include "copyable.hpp"
#include "log.h"
#include "msg_wrapper.hpp"
namespace rpc_core {
namespace detail {
struct msg_wrapper : copyable { // NOLINT
enum msg_type : uint8_t {
command = 1 << 0,
response = 1 << 1,
need_rsp = 1 << 2,
ping = 1 << 3,
pong = 1 << 4,
no_such_cmd = 1 << 5,
};
seq_type seq;
cmd_type cmd;
msg_type type;
std::string data;
std::string* request_payload = nullptr;
std::string dump() const {
char tmp[100];
snprintf(tmp, 100, "seq:%u, type:%u, cmd:%s", seq, type, cmd.c_str());
return tmp;
}
template <typename T>
std::pair<bool, T> unpack_as() const {
T message;
bool ok = deserialize(data, message);
if (not ok) {
RPC_CORE_LOGE("deserialize error, msg info:%s", dump().c_str());
}
return std::make_pair(ok, std::move(message));
}
template <typename T>
static std::pair<bool, msg_wrapper> make_rsp(seq_type seq, T* t = nullptr, bool success = true) {
msg_wrapper msg;
msg.type = msg_wrapper::response;
msg.seq = seq;
if (success && t != nullptr) {
msg.data = serialize(*t);
}
return std::make_pair(success, std::move(msg));
}
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,17 @@
#pragma once
namespace rpc_core {
namespace detail {
class noncopyable {
public:
noncopyable(const noncopyable&) = delete;
noncopyable& operator=(const noncopyable&) = delete;
protected:
noncopyable() = default;
~noncopyable() = default;
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,26 @@
#pragma once
#include <cstddef>
#include <string>
namespace rpc_core {
namespace detail {
class string_view {
public:
string_view(const char* data, size_t size) : data_(data), size_(size) {}
string_view(const std::string& data) : data_(data.data()), size_(data.size()) {} // NOLINT
const char* data() const {
return data_;
}
size_t size() const {
return size_;
}
private:
const char* data_;
size_t size_;
};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,24 @@
#pragma once
#include <type_traits>
namespace rpc_core {
namespace detail {
template <typename Base, typename T, typename... Args>
struct all_base_of {
static constexpr bool value = std::is_base_of<Base, T>::value && all_base_of<Base, Args...>::value;
};
template <typename Base, typename T>
struct all_base_of<Base, T> {
static constexpr bool value = std::is_base_of<Base, T>::value;
};
template <typename T>
constexpr const T& min(const T& a, const T& b) {
return a < b ? a : b;
}
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,61 @@
#pragma once
#include <algorithm>
#include <memory>
#include <vector>
// #define RPC_CORE_LOG_SHOW_VERBOSE
// config
#include "config.hpp"
// include
#include "detail/noncopyable.hpp"
#include "request.hpp"
namespace rpc_core {
class dispose : detail::noncopyable, public request::dispose_proto {
public:
static std::shared_ptr<dispose> create() {
return std::make_shared<dispose>();
}
public:
void add(const request_s& request) override {
RPC_CORE_LOGV("add: ptr:%p", request.get());
requests_.push_back(request_w{request});
}
void remove(const request_s& request) override {
RPC_CORE_LOGV("remove: ptr:%p", request.get());
auto iter = std::remove_if(requests_.begin(), requests_.end(), [&](request_w& param) {
auto r = param.lock();
if (!r) return true;
return r == request;
});
requests_.erase(iter);
}
void dismiss() {
for (const auto& item : requests_) {
auto r = item.lock();
if (r) {
r->cancel();
}
}
requests_.clear();
}
~dispose() override {
RPC_CORE_LOGD("~dispose: size:%zu", requests_.size());
dismiss();
}
private:
std::vector<request_w> requests_;
};
using dispose_s = std::shared_ptr<dispose>;
} // namespace rpc_core

View File

@ -0,0 +1,35 @@
#pragma once
#include "flatbuffers/flatbuffers.h"
#include "rpc_core/serialize.hpp"
namespace rpc_core {
template <typename T, typename std::enable_if<std::is_base_of<::flatbuffers::NativeTable, T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
using TableType = typename T::TableType;
flatbuffers::FlatBufferBuilder fbb(1024);
auto offset = TableType::Pack(fbb, &t);
fbb.Finish(offset);
auto data = fbb.GetBufferPointer();
auto size = fbb.GetSize();
oa.data.append((char*)data, size);
return oa;
}
template <typename T, typename std::enable_if<std::is_base_of<::flatbuffers::NativeTable, T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
using TableType = typename T::TableType;
flatbuffers::Verifier verifier((uint8_t*)ia.data, ia.size);
bool ok = verifier.VerifyBuffer<TableType>();
if (!ok) {
ia.error = true;
return ia;
}
flatbuffers::GetRoot<TableType>(ia.data)->UnPackTo(&t);
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,26 @@
#pragma once
#include "nlohmann/json.hpp"
#include "rpc_core/detail/log.h"
#include "rpc_core/serialize.hpp"
namespace rpc_core {
template <typename T, typename std::enable_if<std::is_same<nlohmann::json, T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
t.dump() >> oa;
return oa;
}
template <typename T, typename std::enable_if<std::is_same<nlohmann::json, T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
try {
nlohmann::json::parse(ia.data, ia.data + ia.size).swap(t);
} catch (std::exception& e) {
RPC_CORE_LOGE("deserialize: %s", e.what());
ia.error = true;
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,26 @@
#pragma once
#include "nlohmann/json.hpp"
#include "rpc_core/detail/log.h"
#include "rpc_core/serialize.hpp"
#define RPC_CORE_DEFINE_TYPE_NLOHMANN_JSON(CLASS) \
template <typename T, typename std::enable_if<std::is_same<CLASS, T>::value, int>::type = 0> \
::rpc_core::serialize_oarchive& operator>>(const T& t, ::rpc_core::serialize_oarchive& oa) { \
oa.data.append(nlohmann::json(t).dump(-1)); \
return oa; \
} \
template <typename T, typename std::enable_if<std::is_same<CLASS, T>::value, int>::type = 0> \
::rpc_core::serialize_iarchive& operator<<(T& t, ::rpc_core::serialize_iarchive& ia) { \
try { \
t = nlohmann::json::parse(ia.data, ia.data + ia.size).get<T>(); \
} catch (std::exception & e) { \
RPC_CORE_LOGE("deserialize: %s", e.what()); \
ia.error = true; \
} \
return ia; \
}
#define RPC_CORE_DEFINE_TYPE_JSON(Type, ...) \
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, __VA_ARGS__) \
RPC_CORE_DEFINE_TYPE_NLOHMANN_JSON(Type);

View File

@ -0,0 +1,384 @@
#pragma once
#include <cassert>
#include <memory>
#include <utility>
#ifndef RPC_CORE_FEATURE_DISABLE_FUTURE
#include <future>
#endif
// config
#include "config.hpp"
// include
#include "detail/callable/callable.hpp"
#include "detail/msg_wrapper.hpp"
#include "detail/noncopyable.hpp"
#include "serialize.hpp"
namespace rpc_core {
class request : detail::noncopyable, public std::enable_shared_from_this<request> {
friend class rpc;
public:
using request_s = std::shared_ptr<request>;
using request_w = std::weak_ptr<request>;
struct rpc_proto {
virtual ~rpc_proto() = default;
virtual seq_type make_seq() = 0;
virtual void send_request(const request_s&) = 0;
virtual bool is_ready() const = 0;
};
using send_proto_s = std::shared_ptr<rpc_proto>;
using send_proto_w = std::weak_ptr<rpc_proto>;
struct dispose_proto {
virtual ~dispose_proto() = default;
virtual void add(const request_s& request) = 0;
virtual void remove(const request_s& request) = 0;
};
enum class finally_t : int {
normal = 0,
no_need_rsp = 1,
timeout = 2,
canceled = 3,
rpc_expired = 4,
rpc_not_ready = 5,
rsp_serialize_error = 6,
no_such_cmd = 7,
};
static inline const char* finally_t_str(finally_t t) {
switch (t) {
case finally_t::normal:
return "normal";
case finally_t::no_need_rsp:
return "no_need_rsp";
case finally_t::timeout:
return "timeout";
case finally_t::canceled:
return "canceled";
case finally_t::rpc_expired:
return "rpc_expired";
case finally_t::rpc_not_ready:
return "rpc_not_ready";
case finally_t::rsp_serialize_error:
return "rsp_serialize_error";
case finally_t::no_such_cmd:
return "no_such_cmd";
default:
return "unknown";
}
}
public:
template <typename... Args>
static request_s create(Args&&... args) {
auto r = std::shared_ptr<request>(new request(std::forward<Args>(args)...), [](request* p) {
delete p;
});
r->init();
return r;
}
public:
std::shared_ptr<request> cmd(cmd_type cmd) {
cmd_ = std::move(cmd);
return shared_from_this();
}
template <typename T>
request_s msg(T&& message) {
this->payload_ = serialize(std::forward<T>(message));
return shared_from_this();
}
template <typename F, typename std::enable_if<callable_traits<F>::argc, int>::type = 0>
request_s rsp(RPC_CORE_MOVE_PARAM(F) cb) {
using T = detail::remove_cvref_t<typename callable_traits<F>::template argument_type<0>>;
need_rsp_ = true;
auto self = shared_from_this();
this->rsp_handle_ = [this, RPC_CORE_MOVE_LAMBDA(cb)](detail::msg_wrapper msg) {
if (canceled_) {
on_finish(finally_t::canceled);
return true;
}
if (msg.type & detail::msg_wrapper::msg_type::no_such_cmd) {
on_finish(finally_t::no_such_cmd);
return true;
}
auto rsp = msg.unpack_as<T>();
if (rsp.first) {
cb(std::move(rsp.second));
on_finish(finally_t::normal);
return true;
} else {
on_finish(finally_t::rsp_serialize_error);
return false;
}
};
return self;
}
template <typename F, typename std::enable_if<!callable_traits<F>::argc, int>::type = 0>
request_s rsp(RPC_CORE_MOVE_PARAM(F) cb) {
need_rsp_ = true;
auto self = shared_from_this();
this->rsp_handle_ = [this, RPC_CORE_MOVE_LAMBDA(cb)](const detail::msg_wrapper& msg) {
RPC_CORE_UNUSED(msg);
if (canceled_) {
on_finish(finally_t::canceled);
return true;
}
if (msg.type & detail::msg_wrapper::msg_type::no_such_cmd) {
on_finish(finally_t::no_such_cmd);
return true;
}
cb();
on_finish(finally_t::normal);
return true;
};
return self;
}
/**
* one call, one finally
* @param finally
* @return
*/
std::shared_ptr<request> finally(std::function<void(finally_t)> finally) {
finally_ = std::move(finally);
return shared_from_this();
}
std::shared_ptr<request> finally(RPC_CORE_MOVE_PARAM(std::function<void()>) finally) {
finally_ = [RPC_CORE_MOVE_LAMBDA(finally)](finally_t t) {
RPC_CORE_UNUSED(t);
finally();
};
return shared_from_this();
}
void call(const send_proto_s& rpc = nullptr) {
waiting_rsp_ = true;
if (canceled_) {
on_finish(finally_t::canceled);
return;
}
self_keeper_ = shared_from_this();
if (rpc) {
rpc_ = rpc;
} else if (rpc_.expired()) {
on_finish(finally_t::rpc_expired);
return;
}
auto r = rpc_.lock();
if (!r->is_ready()) {
on_finish(finally_t::rpc_not_ready);
return;
}
seq_ = r->make_seq();
r->send_request(self_keeper_);
if (!need_rsp_) {
on_finish(finally_t::no_need_rsp);
}
}
request_s ping() {
is_ping_ = true;
return shared_from_this();
}
std::shared_ptr<request> timeout_ms(uint32_t timeout_ms) {
timeout_ms_ = timeout_ms;
return shared_from_this();
}
/**
* timeout callback for wait `rsp`
*/
std::shared_ptr<request> timeout(RPC_CORE_MOVE_PARAM(std::function<void()>) timeout_cb) {
timeout_cb_ = [this, RPC_CORE_MOVE_LAMBDA(timeout_cb)] {
if (timeout_cb) {
timeout_cb();
}
if (retry_count_ == -1) {
call();
} else if (retry_count_ > 0) {
retry_count_--;
call();
} else {
on_finish(finally_t::timeout);
}
};
return shared_from_this();
}
request_s add_to(dispose_proto& dispose) {
auto self = shared_from_this();
dispose.add(self);
return self;
}
request_s cancel() {
canceled(true);
on_finish(finally_t::canceled);
return shared_from_this();
}
request_s reset_cancel() {
canceled(false);
return shared_from_this();
}
/**
* Automatic retry times after timeout
* -1 means retry indefinitely, 0 means no retry, >0 means the number of retries.
*/
request_s retry(int count) {
retry_count_ = count;
return shared_from_this();
}
/**
* Force to ignore `rsp` callback.
*/
request_s disable_rsp() {
need_rsp_ = false;
return shared_from_this();
}
std::shared_ptr<request> rpc(send_proto_w rpc) {
rpc_ = std::move(rpc);
return shared_from_this();
}
send_proto_w rpc() {
return rpc_;
}
bool canceled() const {
return canceled_;
}
std::shared_ptr<request> canceled(bool canceled) {
canceled_ = canceled;
return shared_from_this();
}
#ifndef RPC_CORE_FEATURE_DISABLE_FUTURE
/**
* Future pattern
* It is not recommended to use blocking interfaces unless you are very clear about what you are doing, as it is easy to cause deadlock.
*/
template <typename T>
struct future_ret;
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type = 0>
std::future<future_ret<R>> future(const send_proto_s& rpc = nullptr);
template <typename R, typename std::enable_if<std::is_same<R, void>::value, int>::type = 0>
std::future<future_ret<void>> future(const send_proto_s& rpc = nullptr);
#endif
private:
explicit request(const send_proto_s& rpc = nullptr) : rpc_(rpc) {
RPC_CORE_LOGD("request: %p", this);
}
~request() {
RPC_CORE_LOGD("~request: %p", this);
}
private:
void init() {
timeout(nullptr);
}
void on_finish(finally_t type) {
if (!waiting_rsp_) return;
waiting_rsp_ = false;
RPC_CORE_LOGD("on_finish: cmd:%s type:%s", cmd_.c_str(), finally_t_str(type));
finally_type_ = type;
if (finally_) {
finally_(finally_type_);
}
self_keeper_ = nullptr;
}
private:
send_proto_w rpc_;
request_s self_keeper_;
seq_type seq_{};
cmd_type cmd_;
std::string payload_;
bool need_rsp_ = false;
bool canceled_ = false;
std::function<bool(detail::msg_wrapper)> rsp_handle_;
uint32_t timeout_ms_ = 3000;
std::function<void()> timeout_cb_;
finally_t finally_type_ = finally_t::no_need_rsp;
std::function<void(finally_t)> finally_;
int retry_count_ = 0;
bool waiting_rsp_ = false;
bool is_ping_ = false;
};
#ifndef RPC_CORE_FEATURE_DISABLE_FUTURE
template <typename T>
struct request::future_ret {
finally_t type;
T data;
};
template <>
struct request::future_ret<void> {
finally_t type;
};
template <typename R, typename std::enable_if<!std::is_same<R, void>::value, int>::type>
std::future<request::future_ret<R>> request::future(const request::send_proto_s& rpc) {
auto promise = std::make_shared<std::promise<future_ret<R>>>();
rsp([promise](R r) {
promise->set_value({finally_t::normal, std::move(r)});
});
finally([promise](finally_t type) {
if (type != finally_t::normal) {
promise->set_value({type, {}});
}
});
call(rpc);
return promise->get_future();
}
template <typename R, typename std::enable_if<std::is_same<R, void>::value, int>::type>
std::future<request::future_ret<void>> request::future(const request::send_proto_s& rpc) {
auto promise = std::make_shared<std::promise<request::future_ret<void>>>();
rsp([promise] {
promise->set_value({request::finally_t::normal});
});
finally([promise](request::finally_t type) {
if (type != request::finally_t::normal) {
promise->set_value({type});
}
});
call(rpc);
return promise->get_future();
}
#endif
using request_s = request::request_s;
using request_w = request::request_w;
using finally_t = request::finally_t;
} // namespace rpc_core

View File

@ -0,0 +1,165 @@
#pragma once
#include <memory>
#include <utility>
// config
#include "config.hpp"
// include
#include "connection.hpp"
#include "detail/callable/callable.hpp"
#include "detail/msg_dispatcher.hpp"
#include "detail/noncopyable.hpp"
#include "request.hpp"
namespace rpc_core {
class rpc : detail::noncopyable, public std::enable_shared_from_this<rpc>, public request::rpc_proto {
public:
using timeout_cb = detail::msg_dispatcher::timeout_cb;
public:
template <typename... Args>
static std::shared_ptr<rpc> create(Args&&... args) {
return std::shared_ptr<rpc>(new rpc(std::forward<Args>(args)...), [](rpc* p) {
delete p;
});
}
private:
explicit rpc(std::shared_ptr<connection> conn = std::make_shared<default_connection>()) : conn_(conn), dispatcher_(std::move(conn)) {
RPC_CORE_LOGD("rpc: %p", this);
}
~rpc() override {
RPC_CORE_LOGD("~rpc: %p", this);
};
public:
inline std::shared_ptr<connection> get_connection() const {
return conn_;
}
inline void set_timer(detail::msg_dispatcher::timer_impl timer_impl) {
dispatcher_.set_timer_impl(std::move(timer_impl));
}
inline void set_ready(bool ready) {
is_ready_ = ready;
}
public:
template <typename F>
void subscribe(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle) {
constexpr bool F_ReturnIsEmpty = std::is_void<typename detail::callable_traits<F>::return_type>::value;
constexpr bool F_ParamIsEmpty = detail::callable_traits<F>::argc == 0;
subscribe_helper<F, F_ReturnIsEmpty, F_ParamIsEmpty>()(cmd, std::move(handle), &dispatcher_);
}
inline void unsubscribe(const cmd_type& cmd) {
dispatcher_.unsubscribe_cmd(cmd);
}
public:
inline request_s create_request() {
return request::create(shared_from_this());
}
inline request_s cmd(cmd_type cmd) {
return create_request()->cmd(std::move(cmd));
}
inline request_s ping(std::string payload = {}) { // NOLINT
return create_request()->ping()->msg(std::move(payload));
}
public:
seq_type make_seq() override {
return seq_++;
}
void send_request(const request_s& request) override {
if (request->need_rsp_) {
dispatcher_.subscribe_rsp(request->seq_, request->rsp_handle_, request->timeout_cb_, request->timeout_ms_, request->is_ping_);
}
detail::msg_wrapper msg;
msg.type = static_cast<detail::msg_wrapper::msg_type>(detail::msg_wrapper::command | (request->is_ping_ ? detail::msg_wrapper::ping : 0) |
(request->need_rsp_ ? detail::msg_wrapper::need_rsp : 0));
msg.cmd = request->cmd_;
msg.seq = request->seq_;
msg.request_payload = &request->payload_;
RPC_CORE_LOGD("=> seq:%u type:%s %s", msg.seq, (msg.type & detail::msg_wrapper::msg_type::ping) ? "ping" : "cmd", msg.cmd.c_str());
conn_->send_package_impl(detail::coder::serialize(msg));
}
inline bool is_ready() const override {
return is_ready_;
}
private:
template <typename F, bool F_ReturnIsEmpty, bool F_ParamIsEmpty>
struct subscribe_helper;
template <typename F>
struct subscribe_helper<F, false, false> {
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
using F_Param = detail::remove_cvref_t<typename detail::callable_traits<F>::template argument_type<0>>;
using F_Return = detail::remove_cvref_t<typename detail::callable_traits<F>::return_type>;
auto r = msg.unpack_as<F_Param>();
F_Return ret;
if (r.first) {
ret = handle(std::move(r.second));
}
return detail::msg_wrapper::make_rsp(msg.seq, &ret, r.first);
});
}
};
template <typename F>
struct subscribe_helper<F, true, false> {
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
using F_Param = detail::remove_cvref_t<typename detail::callable_traits<F>::template argument_type<0>>;
auto r = msg.unpack_as<F_Param>();
if (r.first) {
handle(std::move(r.second));
}
return detail::msg_wrapper::make_rsp<uint8_t>(msg.seq, nullptr, r.first);
});
}
};
template <typename F>
struct subscribe_helper<F, false, true> {
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
using F_Return = typename detail::callable_traits<F>::return_type;
F_Return ret = handle();
return detail::msg_wrapper::make_rsp(msg.seq, &ret, true);
});
}
};
template <typename F>
struct subscribe_helper<F, true, true> {
void operator()(const cmd_type& cmd, RPC_CORE_MOVE_PARAM(F) handle, detail::msg_dispatcher* dispatcher) {
dispatcher->subscribe_cmd(cmd, [RPC_CORE_MOVE_LAMBDA(handle)](const detail::msg_wrapper& msg) {
handle();
return detail::msg_wrapper::make_rsp<uint8_t>(msg.seq, nullptr, true);
});
}
};
private:
std::shared_ptr<connection> conn_;
detail::msg_dispatcher dispatcher_;
seq_type seq_{0};
bool is_ready_ = false;
};
} // namespace rpc_core

View File

@ -0,0 +1,34 @@
#pragma once
// config
#include "config.hpp"
// type traits
#include "detail/type_traits.hpp"
// serialize type
#include "serialize_type.hpp"
// raw type
#include "serialize/type_raw.hpp"
// other types
#include "serialize/binary_wrap.hpp"
#include "serialize/std_array.hpp"
#include "serialize/std_basic_string.hpp"
#include "serialize/std_bitset.hpp"
#include "serialize/std_chrono.hpp"
#include "serialize/std_complex.hpp"
#include "serialize/std_container_adaptors.hpp"
#include "serialize/std_forward_list.hpp"
#include "serialize/std_list_like.hpp"
#include "serialize/std_map.hpp"
#include "serialize/std_pair.hpp"
#include "serialize/std_set.hpp"
#include "serialize/std_shared_ptr.hpp"
#include "serialize/std_tuple.hpp"
#include "serialize/std_unique_ptr.hpp"
#include "serialize/type_enum.hpp"
#include "serialize/type_ptr.hpp"
#include "serialize/type_struct.hpp"
#include "serialize/type_void.hpp"

View File

@ -0,0 +1,38 @@
#pragma once
#include <cstdint>
#include <memory>
namespace rpc_core {
struct binary_wrap {
binary_wrap() = default;
binary_wrap(void* data, size_t size) : data(data), size(size) {}
void* data = nullptr;
size_t size = 0;
// private:
std::shared_ptr<uint8_t> _data_;
};
template <typename T, typename std::enable_if<std::is_same<T, binary_wrap>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
t.size >> oa;
oa.data.append((char*)t.data, t.size);
return oa;
}
template <typename T, typename std::enable_if<std::is_same<T, binary_wrap>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
t.size << ia;
t._data_ = std::shared_ptr<uint8_t>(new uint8_t[t.size], [](const uint8_t* p) {
delete[] p;
});
t.data = t._data_.get();
memcpy(t.data, ia.data, t.size);
ia.data += t.size;
ia.size -= t.size;
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,73 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <string>
namespace rpc_core {
namespace detail {
template <typename int_impl_t>
struct auto_size_type {
explicit auto_size_type(int_impl_t value = 0) : value(value) {}
std::string serialize() const {
if (value == 0) {
return {(char*)&value, 1};
}
uint8_t effective_bytes = sizeof(int_impl_t);
auto value_tmp = value;
if (value_tmp < 0) {
value_tmp = -value_tmp;
}
for (int i = sizeof(int_impl_t) - 1; i >= 0; --i) {
if ((value_tmp >> (i * 8)) & 0xff) {
break;
} else {
--effective_bytes;
}
}
std::string ret;
ret.resize(1 + effective_bytes);
auto data = (uint8_t*)ret.data();
data[0] = effective_bytes;
memcpy(data + 1, &value_tmp, effective_bytes);
if (value < 0) {
data[0] |= 0x80;
}
return ret;
}
int deserialize(const void* data) {
auto p = (uint8_t*)data;
uint8_t size_bytes = p[0];
bool negative = false;
if (size_bytes & 0x80) {
negative = true;
size_bytes &= 0x7f;
}
memcpy(&value, p + 1, size_bytes);
if (negative) {
value = -value;
}
return size_bytes + 1;
}
int_impl_t value;
};
using auto_size = auto_size_type<size_t>;
using auto_intmax = auto_size_type<intmax_t>;
using auto_uintmax = auto_size_type<uintmax_t>;
template <typename T>
struct is_auto_size_type : std::false_type {};
template <typename T>
struct is_auto_size_type<auto_size_type<T>> : std::true_type {};
} // namespace detail
} // namespace rpc_core

View File

@ -0,0 +1,57 @@
#pragma once
#include <array>
#include "../detail/callable/helpers.hpp"
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_array : std::false_type {};
template <typename T, size_t Size>
struct is_std_array<std::array<T, Size>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_array<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_size size(t.size());
size >> oa;
for (auto& item : t) {
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item >> oa;
} else {
serialize_oarchive tmp;
item >> tmp;
tmp >> oa;
}
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_array<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_size size;
size << ia;
for (size_t i = 0; i < size.value; ++i) {
typename T::value_type item;
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item << ia;
} else {
serialize_iarchive tmp;
tmp << ia;
item << tmp;
if (tmp.error) {
ia.error = true;
break;
}
}
t[i] = std::move(item);
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,42 @@
#pragma once
#include <string>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_basic_string : std::false_type {};
template <typename... Args>
struct is_std_basic_string<std::basic_string<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_basic_string<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
using VT = typename T::value_type;
oa.data.append((char*)t.data(), t.size() * sizeof(VT));
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_basic_string<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(T&& t, serialize_oarchive& oa) {
using VT = typename T::value_type;
if (oa.data.empty()) {
oa.data = std::forward<T>(t);
} else {
oa.data.append((char*)t.data(), t.size() * sizeof(VT));
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_basic_string<T>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
using VT = typename T::value_type;
t = T((VT*)(ia.data), ia.size / sizeof(VT));
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,33 @@
#pragma once
#include <bitset>
#include <string>
#include <type_traits>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_bitset : std::false_type {};
template <std::size_t N>
struct is_std_bitset<std::bitset<N>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_bitset<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
oa.data.append(t.to_string());
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_bitset<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
std::string tmp;
tmp << ia;
t = T(std::move(tmp));
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,53 @@
#pragma once
#include <chrono>
#include <type_traits>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_chrono_duration : std::false_type {};
template <typename... Args>
struct is_std_chrono_duration<std::chrono::duration<Args...>> : std::true_type {};
template <typename T>
struct is_std_chrono_time_point : std::false_type {};
template <typename... Args>
struct is_std_chrono_time_point<std::chrono::time_point<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_chrono_duration<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_intmax count(t.count());
count >> oa;
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_chrono_duration<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_intmax rep;
rep << ia;
t = T(rep.value);
return ia;
}
template <typename T, typename std::enable_if<detail::is_std_chrono_time_point<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
t.time_since_epoch() >> oa;
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_chrono_time_point<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
typename T::duration duration;
duration << ia;
t = T(duration);
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,52 @@
#pragma once
#include <complex>
#include <type_traits>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_complex : std::false_type {};
template <typename T>
struct is_std_complex<std::complex<T>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_complex<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
using VT = typename T::value_type;
if (std::is_fundamental<VT>::value) {
t.real() >> oa;
t.imag() >> oa;
} else {
oa & t.real();
oa & t.imag();
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_complex<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
using VT = typename T::value_type;
if (std::is_fundamental<VT>::value) {
VT real;
real << ia;
t.real(real);
VT imag;
imag << ia;
t.imag(imag);
} else {
VT real;
ia & real;
t.real(std::move(real));
VT imag;
ia & imag;
t.imag(std::move(imag));
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,36 @@
#pragma once
#include <queue>
#include <stack>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_stack : std::false_type {};
template <typename... Args>
struct is_std_stack<std::stack<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_stack<std::queue<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_stack<std::priority_queue<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_stack<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
(typename T::container_type&)t >> oa;
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_stack<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
(typename T::container_type&)t << ia;
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,58 @@
#pragma once
#include <forward_list>
#include "../detail/callable/helpers.hpp"
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_forward_list : std::false_type {};
template <typename... Args>
struct is_std_forward_list<std::forward_list<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_forward_list<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_size size(std::distance(t.cbegin(), t.cend()));
size >> oa;
for (auto& item : t) {
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item >> oa;
} else {
serialize_oarchive tmp;
item >> tmp;
tmp >> oa;
}
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_forward_list<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_size size;
size << ia;
for (size_t i = 0; i < size.value; ++i) {
typename T::value_type item;
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item << ia;
} else {
serialize_iarchive tmp;
tmp << ia;
item << tmp;
if (tmp.error) {
ia.error = true;
break;
}
}
t.emplace_front(std::move(item));
}
t.reverse();
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,63 @@
#pragma once
#include <deque>
#include <list>
#include <vector>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_list_like : std::false_type {};
template <typename... Args>
struct is_std_list_like<std::vector<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_list_like<std::list<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_list_like<std::deque<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_list_like<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_size size(t.size());
size >> oa;
for (auto& item : t) {
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item >> oa;
} else {
serialize_oarchive tmp;
item >> tmp;
tmp >> oa;
}
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_list_like<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_size size;
size << ia;
for (size_t i = 0; i < size.value; ++i) {
typename T::value_type item;
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item << ia;
} else {
serialize_iarchive tmp;
tmp << ia;
item << tmp;
if (tmp.error) {
ia.error = true;
break;
}
}
t.emplace_back(std::move(item));
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,57 @@
#pragma once
#include <map>
#include <unordered_map>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_map_like : std::false_type {};
template <typename... Args>
struct is_std_map_like<std::map<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_map_like<std::unordered_map<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_map_like<std::multimap<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_map_like<std::unordered_multimap<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_map_like<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_size size(t.size());
size >> oa;
for (auto& item : t) {
serialize_oarchive tmp;
item >> tmp;
tmp >> oa;
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_map_like<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_size size;
size << ia;
for (size_t i = 0; i < size.value; ++i) {
typename T::value_type item;
serialize_iarchive tmp;
tmp << ia;
item << tmp;
if (tmp.error) {
ia.error = true;
break;
}
t.emplace(std::move(item));
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,34 @@
#pragma once
#include <tuple>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_pair : std::false_type {};
template <typename... Args>
struct is_std_pair<std::pair<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_pair<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
std::tie(t.first, t.second) >> oa;
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_pair<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
using first_type = detail::remove_cvref_t<decltype(t.first)>;
using second_type = detail::remove_cvref_t<decltype(t.second)>;
auto& tt = (std::pair<first_type, second_type>&)t;
std::tuple<first_type, second_type> tup;
tup << ia;
std::tie(tt.first, tt.second) = std::move(tup);
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,65 @@
#pragma once
#include <set>
#include <unordered_set>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_set_like : std::false_type {};
template <typename... Args>
struct is_std_set_like<std::set<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_set_like<std::unordered_set<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_set_like<std::multiset<Args...>> : std::true_type {};
template <typename... Args>
struct is_std_set_like<std::unordered_multiset<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_set_like<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_size size(t.size());
size >> oa;
for (auto& item : t) {
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item >> oa;
} else {
serialize_oarchive tmp;
item >> tmp;
tmp >> oa;
}
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_set_like<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_size size;
size << ia;
for (size_t i = 0; i < size.value; ++i) {
typename T::value_type item;
if (std::is_fundamental<detail::remove_cvref_t<decltype(item)>>::value) {
item << ia;
} else {
serialize_iarchive tmp;
tmp << ia;
item << tmp;
if (tmp.error) {
ia.error = true;
break;
}
}
t.emplace(std::move(item));
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,40 @@
#pragma once
#include <memory>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_shared_ptr : std::false_type {};
template <typename... Args>
struct is_std_shared_ptr<std::shared_ptr<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_shared_ptr<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
if (t != nullptr) {
true >> oa;
*t >> oa;
} else {
false >> oa;
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_shared_ptr<T>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
bool notnull;
notnull << ia;
if (notnull) {
using Type = typename T::element_type;
t = std::make_shared<Type>();
*t << ia;
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,147 @@
#pragma once
#include <tuple>
#include "../detail/callable/helpers.hpp"
namespace rpc_core {
namespace detail {
template <std::size_t I, typename T>
using tuple_element_t = detail::remove_cvref_t<typename std::tuple_element<I, detail::remove_cvref_t<T>>::type>;
template <typename T>
struct is_tuple : std::false_type {};
template <typename... Args>
struct is_tuple<std::tuple<Args...>> : std::true_type {};
template <typename T>
struct is_std_ignore {
static const bool value = std::is_same<detail::remove_cvref_t<decltype(std::ignore)>, T>::value;
};
enum class tuple_serialize_type {
Ignore,
RawType,
Normal,
};
template <typename T>
struct tuple_serialize_type_check {
static constexpr tuple_serialize_type value = std::is_fundamental<T>::value ? tuple_serialize_type::RawType
: is_std_ignore<T>::value ? tuple_serialize_type::Ignore
: tuple_serialize_type::Normal;
};
template <typename Tuple, std::size_t I, tuple_serialize_type type>
struct tuple_serialize_helper_impl;
template <typename Tuple, std::size_t I>
struct tuple_serialize_helper_impl<Tuple, I, tuple_serialize_type::Normal> {
static void serialize(const Tuple& t, serialize_oarchive& oa) {
serialize_oarchive tmp;
std::get<I>(t) >> tmp;
tmp >> oa;
}
};
template <typename Tuple, std::size_t I>
struct tuple_serialize_helper_impl<Tuple, I, tuple_serialize_type::RawType> {
static void serialize(const Tuple& t, serialize_oarchive& oa) {
std::get<I>(t) >> oa;
}
};
template <typename Tuple, std::size_t I>
struct tuple_serialize_helper_impl<Tuple, I, tuple_serialize_type::Ignore> {
static void serialize(const Tuple& t, serialize_oarchive& oa) {
RPC_CORE_UNUSED(t);
RPC_CORE_UNUSED(oa);
}
};
template <typename Tuple, std::size_t N>
struct tuple_serialize_helper {
static void serialize(const Tuple& t, serialize_oarchive& oa) {
tuple_serialize_helper<Tuple, N - 1>::serialize(t, oa);
tuple_serialize_helper_impl<Tuple, N - 1, tuple_serialize_type_check<tuple_element_t<N - 1, Tuple>>::value>::serialize(t, oa);
}
};
template <typename Tuple>
struct tuple_serialize_helper<Tuple, 1> {
static void serialize(const Tuple& t, serialize_oarchive& oa) {
tuple_serialize_helper_impl<Tuple, 0, tuple_serialize_type_check<tuple_element_t<0, Tuple>>::value>::serialize(t, oa);
}
};
template <typename... Args>
void tuple_serialize(const std::tuple<Args...>& t, serialize_oarchive& oa) {
tuple_serialize_helper<decltype(t), sizeof...(Args)>::serialize(t, oa);
}
template <typename Tuple, std::size_t I, tuple_serialize_type type>
struct tuple_de_serialize_helper_impl;
template <typename Tuple, std::size_t I>
struct tuple_de_serialize_helper_impl<Tuple, I, tuple_serialize_type::Normal> {
static void de_serialize(Tuple& t, serialize_iarchive& ia) {
serialize_iarchive tmp;
tmp << ia;
std::get<I>(t) << tmp;
}
};
template <typename Tuple, std::size_t I>
struct tuple_de_serialize_helper_impl<Tuple, I, tuple_serialize_type::RawType> {
static void de_serialize(Tuple& t, serialize_iarchive& ia) {
std::get<I>(t) << ia;
}
};
template <typename Tuple, std::size_t I>
struct tuple_de_serialize_helper_impl<Tuple, I, tuple_serialize_type::Ignore> {
static void de_serialize(Tuple& t, serialize_iarchive& ia) {
RPC_CORE_UNUSED(t);
RPC_CORE_UNUSED(ia);
}
};
template <typename Tuple, std::size_t N>
struct tuple_de_serialize_helper {
static void de_serialize(Tuple& t, serialize_iarchive& ia) {
tuple_de_serialize_helper<Tuple, N - 1>::de_serialize(t, ia);
if (ia.error) return;
tuple_de_serialize_helper_impl<Tuple, N - 1, tuple_serialize_type_check<tuple_element_t<N - 1, Tuple>>::value>::de_serialize(t, ia);
}
};
template <typename Tuple>
struct tuple_de_serialize_helper<Tuple, 1> {
static void de_serialize(Tuple& t, serialize_iarchive& ia) {
tuple_de_serialize_helper_impl<Tuple, 0, tuple_serialize_type_check<tuple_element_t<0, Tuple>>::value>::de_serialize(t, ia);
}
};
template <typename... Args>
void tuple_de_serialize(std::tuple<Args...>& t, serialize_iarchive& ia) {
tuple_de_serialize_helper<decltype(t), sizeof...(Args)>::de_serialize(t, ia);
}
} // namespace detail
template <typename T, typename std::enable_if<detail::is_tuple<T>::value, int>::type = 0>
serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::tuple_serialize(t, oa);
return oa;
}
template <typename T, typename std::enable_if<detail::is_tuple<T>::value, int>::type = 0>
serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::tuple_de_serialize(t, ia);
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,40 @@
#pragma once
#include <memory>
namespace rpc_core {
namespace detail {
template <typename T>
struct is_std_unique_ptr : std::false_type {};
template <typename... Args>
struct is_std_unique_ptr<std::unique_ptr<Args...>> : std::true_type {};
} // namespace detail
template <typename T, typename std::enable_if<detail::is_std_unique_ptr<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
if (t != nullptr) {
true >> oa;
*t >> oa;
} else {
false >> oa;
}
return oa;
}
template <typename T, typename std::enable_if<detail::is_std_unique_ptr<T>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
bool notnull;
notnull << ia;
if (notnull) {
using Type = typename T::element_type;
t = std::unique_ptr<Type>(new Type);
*t << ia;
}
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,20 @@
#pragma once
namespace rpc_core {
template <typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
detail::auto_uintmax impl((uintmax_t)t);
impl >> oa;
return oa;
}
template <typename T, typename std::enable_if<std::is_enum<T>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
detail::auto_uintmax impl;
impl << ia;
t = (T)impl.value;
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,22 @@
#pragma once
#include <cstdint>
namespace rpc_core {
template <typename T, typename std::enable_if<std::is_pointer<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
auto ptr = (intptr_t)t;
ptr >> oa;
return oa;
}
template <typename T, typename std::enable_if<std::is_pointer<T>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
intptr_t ptr;
ptr << ia;
t = (T)ptr;
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,54 @@
#pragma once
#include <cstring>
#include <type_traits>
#include "detail/auto_size.hpp"
#define RPC_CORE_DETAIL_DEFINE_RAW_TYPE(type_raw, type_size) \
static_assert(sizeof(type_raw) <= type_size, ""); \
inline serialize_oarchive& operator>>(const type_raw& t, serialize_oarchive& oa) { \
oa.data.append((char*)&t, type_size); \
return oa; \
} \
inline serialize_iarchive& operator<<(type_raw& t, serialize_iarchive& ia) { \
t = {}; \
memcpy(&t, ia.data, detail::min<size_t>(sizeof(t), type_size)); \
ia.data += type_size; \
ia.size -= type_size; \
return ia; \
}
#define RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(type_raw, type_auto) \
inline serialize_oarchive& operator>>(const type_raw& t, serialize_oarchive& oa) { \
type_auto impl(t); \
impl >> oa; \
return oa; \
} \
inline serialize_iarchive& operator<<(type_raw& t, serialize_iarchive& ia) { \
type_auto impl; \
impl << ia; \
t = impl.value; \
return ia; \
}
namespace rpc_core {
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(bool, 1);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(char, 1);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(signed char, 1);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(unsigned char, 1);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(short, 2);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(unsigned short, 2);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(int, detail::auto_intmax);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(unsigned int, detail::auto_uintmax);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(long, detail::auto_intmax);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(unsigned long, detail::auto_uintmax);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(long long, detail::auto_intmax);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE_AUTO_SIZE(unsigned long long, detail::auto_uintmax);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(float, 4);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(double, 8);
RPC_CORE_DETAIL_DEFINE_RAW_TYPE(long double, 16);
} // namespace rpc_core

View File

@ -0,0 +1,200 @@
#pragma once
// clang-format off
#define RPC_CORE_DETAIL_SERIALIZE_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
#define RPC_CORE_DETAIL_SERIALIZE_PASTE(...) RPC_CORE_DETAIL_SERIALIZE_GET_MACRO(__VA_ARGS__, \
RPC_CORE_DETAIL_SERIALIZE_PASTE64, \
RPC_CORE_DETAIL_SERIALIZE_PASTE63, \
RPC_CORE_DETAIL_SERIALIZE_PASTE62, \
RPC_CORE_DETAIL_SERIALIZE_PASTE61, \
RPC_CORE_DETAIL_SERIALIZE_PASTE60, \
RPC_CORE_DETAIL_SERIALIZE_PASTE59, \
RPC_CORE_DETAIL_SERIALIZE_PASTE58, \
RPC_CORE_DETAIL_SERIALIZE_PASTE57, \
RPC_CORE_DETAIL_SERIALIZE_PASTE56, \
RPC_CORE_DETAIL_SERIALIZE_PASTE55, \
RPC_CORE_DETAIL_SERIALIZE_PASTE54, \
RPC_CORE_DETAIL_SERIALIZE_PASTE53, \
RPC_CORE_DETAIL_SERIALIZE_PASTE52, \
RPC_CORE_DETAIL_SERIALIZE_PASTE51, \
RPC_CORE_DETAIL_SERIALIZE_PASTE50, \
RPC_CORE_DETAIL_SERIALIZE_PASTE49, \
RPC_CORE_DETAIL_SERIALIZE_PASTE48, \
RPC_CORE_DETAIL_SERIALIZE_PASTE47, \
RPC_CORE_DETAIL_SERIALIZE_PASTE46, \
RPC_CORE_DETAIL_SERIALIZE_PASTE45, \
RPC_CORE_DETAIL_SERIALIZE_PASTE44, \
RPC_CORE_DETAIL_SERIALIZE_PASTE43, \
RPC_CORE_DETAIL_SERIALIZE_PASTE42, \
RPC_CORE_DETAIL_SERIALIZE_PASTE41, \
RPC_CORE_DETAIL_SERIALIZE_PASTE40, \
RPC_CORE_DETAIL_SERIALIZE_PASTE39, \
RPC_CORE_DETAIL_SERIALIZE_PASTE38, \
RPC_CORE_DETAIL_SERIALIZE_PASTE37, \
RPC_CORE_DETAIL_SERIALIZE_PASTE36, \
RPC_CORE_DETAIL_SERIALIZE_PASTE35, \
RPC_CORE_DETAIL_SERIALIZE_PASTE34, \
RPC_CORE_DETAIL_SERIALIZE_PASTE33, \
RPC_CORE_DETAIL_SERIALIZE_PASTE32, \
RPC_CORE_DETAIL_SERIALIZE_PASTE31, \
RPC_CORE_DETAIL_SERIALIZE_PASTE30, \
RPC_CORE_DETAIL_SERIALIZE_PASTE29, \
RPC_CORE_DETAIL_SERIALIZE_PASTE28, \
RPC_CORE_DETAIL_SERIALIZE_PASTE27, \
RPC_CORE_DETAIL_SERIALIZE_PASTE26, \
RPC_CORE_DETAIL_SERIALIZE_PASTE25, \
RPC_CORE_DETAIL_SERIALIZE_PASTE24, \
RPC_CORE_DETAIL_SERIALIZE_PASTE23, \
RPC_CORE_DETAIL_SERIALIZE_PASTE22, \
RPC_CORE_DETAIL_SERIALIZE_PASTE21, \
RPC_CORE_DETAIL_SERIALIZE_PASTE20, \
RPC_CORE_DETAIL_SERIALIZE_PASTE19, \
RPC_CORE_DETAIL_SERIALIZE_PASTE18, \
RPC_CORE_DETAIL_SERIALIZE_PASTE17, \
RPC_CORE_DETAIL_SERIALIZE_PASTE16, \
RPC_CORE_DETAIL_SERIALIZE_PASTE15, \
RPC_CORE_DETAIL_SERIALIZE_PASTE14, \
RPC_CORE_DETAIL_SERIALIZE_PASTE13, \
RPC_CORE_DETAIL_SERIALIZE_PASTE12, \
RPC_CORE_DETAIL_SERIALIZE_PASTE11, \
RPC_CORE_DETAIL_SERIALIZE_PASTE10, \
RPC_CORE_DETAIL_SERIALIZE_PASTE9, \
RPC_CORE_DETAIL_SERIALIZE_PASTE8, \
RPC_CORE_DETAIL_SERIALIZE_PASTE7, \
RPC_CORE_DETAIL_SERIALIZE_PASTE6, \
RPC_CORE_DETAIL_SERIALIZE_PASTE5, \
RPC_CORE_DETAIL_SERIALIZE_PASTE4, \
RPC_CORE_DETAIL_SERIALIZE_PASTE3, \
RPC_CORE_DETAIL_SERIALIZE_PASTE2, \
RPC_CORE_DETAIL_SERIALIZE_PASTE1)(__VA_ARGS__)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) func(v1)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE3(func, v1, v2) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v2)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE4(func, v1, v2, v3) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE3(func, v2, v3)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE5(func, v1, v2, v3, v4) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE4(func, v2, v3, v4)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE6(func, v1, v2, v3, v4, v5) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE5(func, v2, v3, v4, v5)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE7(func, v1, v2, v3, v4, v5, v6) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE6(func, v2, v3, v4, v5, v6)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE7(func, v2, v3, v4, v5, v6, v7)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
#define RPC_CORE_DETAIL_SERIALIZE_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) RPC_CORE_DETAIL_SERIALIZE_PASTE2(func, v1) RPC_CORE_DETAIL_SERIALIZE_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
#define RPC_CORE_DETAIL_SERIALIZE_FIELD(v1) ar & t.v1;
#define RPC_CORE_DETAIL_SERIALIZE_FIELD_INNER(v1) ar & this->v1;
// clang-format on
#include <string>
#include <type_traits>
#include "../detail/noncopyable.hpp"
#include "../detail/string_view.hpp"
namespace rpc_core {
template <typename T, typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
inline serialize_oarchive& operator&(serialize_oarchive& oa, const T& t) {
t >> oa;
return oa;
}
template <typename T, typename std::enable_if<!std::is_fundamental<T>::value, int>::type = 0>
inline serialize_oarchive& operator&(serialize_oarchive& oa, const T& t) {
serialize_oarchive tmp;
t >> tmp;
tmp >> oa;
return oa;
}
template <typename T, typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0>
inline serialize_iarchive& operator&(serialize_iarchive& ia, T& t) {
if (ia.error) return ia;
t << ia;
return ia;
}
template <typename T, typename std::enable_if<!std::is_fundamental<T>::value, int>::type = 0>
serialize_iarchive& operator&(serialize_iarchive& ia, T& t) {
if (ia.error) return ia;
detail::auto_size auto_size;
int cost = auto_size.deserialize(ia.data);
uint32_t size = auto_size.value;
ia.data += cost;
serialize_iarchive tmp(detail::string_view(ia.data, size));
t << tmp;
ia.error = tmp.error;
ia.data += size;
return ia;
}
} // namespace rpc_core
#define RPC_CORE_DEFINE_TYPE(Type, ...) \
inline void operator>>(const Type& t, ::rpc_core::serialize_oarchive& ar) { \
RPC_CORE_DETAIL_SERIALIZE_PASTE(RPC_CORE_DETAIL_SERIALIZE_FIELD, __VA_ARGS__) \
} \
inline void operator<<(Type& t, ::rpc_core::serialize_iarchive& ar) { \
RPC_CORE_DETAIL_SERIALIZE_PASTE(RPC_CORE_DETAIL_SERIALIZE_FIELD, __VA_ARGS__) \
}
#define RPC_CORE_DEFINE_TYPE_INNER(...) \
public: \
void operator>>(::rpc_core::serialize_oarchive& ar) const { \
RPC_CORE_DETAIL_SERIALIZE_PASTE(RPC_CORE_DETAIL_SERIALIZE_FIELD_INNER, __VA_ARGS__) \
} \
void operator<<(::rpc_core::serialize_iarchive& ar) { \
RPC_CORE_DETAIL_SERIALIZE_PASTE(RPC_CORE_DETAIL_SERIALIZE_FIELD_INNER, __VA_ARGS__) \
}

View File

@ -0,0 +1,17 @@
#pragma once
namespace rpc_core {
template <typename T, typename std::enable_if<std::is_same<T, void>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
RPC_CORE_UNUSED(t);
return oa;
}
template <typename T, typename std::enable_if<std::is_same<T, void>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
RPC_CORE_UNUSED(t);
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,82 @@
#pragma once
// config
#include "config.hpp"
// include
#include "detail/noncopyable.hpp"
#include "detail/string_view.hpp"
#include "serialize/detail/auto_size.hpp"
#include "type.hpp"
namespace rpc_core {
struct serialize_oarchive : detail::noncopyable {
std::string data;
};
inline serialize_oarchive& operator>>(const serialize_oarchive& t, serialize_oarchive& oa) {
oa.data.append(detail::auto_size(t.data.size()).serialize());
oa.data.append(t.data);
return oa;
}
inline serialize_oarchive& operator>>(serialize_oarchive&& t, serialize_oarchive& oa) {
if (oa.data.empty()) {
oa.data = std::move(t.data);
return oa;
}
oa.data.append(detail::auto_size(t.data.size()).serialize());
oa.data.append(t.data);
return oa;
}
struct serialize_iarchive : detail::noncopyable {
serialize_iarchive() = default;
serialize_iarchive(detail::string_view sv) : data((char*)sv.data()), size(sv.size()) {} // NOLINT(google-explicit-constructor)
serialize_iarchive(const char* data, size_t size) : data((char*)data), size(size) {}
char* data = nullptr;
size_t size = 0;
bool error = false;
};
inline serialize_iarchive& operator<<(serialize_iarchive& t, serialize_iarchive& ia) {
detail::auto_size size;
int cost = size.deserialize(ia.data);
ia.data += cost;
t.data = ia.data;
t.size = size.value;
ia.data += size.value;
ia.size -= cost + size.value;
return ia;
}
template <typename T>
inline std::string serialize(T&& t) {
serialize_oarchive ar;
std::forward<T>(t) >> ar;
return std::move(ar.data);
}
template <typename T>
inline bool deserialize(const detail::string_view& data, T& t) {
serialize_iarchive ar(data);
t << ar;
return !ar.error;
}
template <typename T, typename std::enable_if<detail::is_auto_size_type<T>::value, int>::type = 0>
inline serialize_oarchive& operator>>(const T& t, serialize_oarchive& oa) {
oa.data.append(t.serialize());
return oa;
}
template <typename T, typename std::enable_if<detail::is_auto_size_type<T>::value, int>::type = 0>
inline serialize_iarchive& operator<<(T& t, serialize_iarchive& ia) {
int cost = t.deserialize((uint8_t*)ia.data);
ia.data += cost;
ia.size -= cost;
return ia;
}
} // namespace rpc_core

View File

@ -0,0 +1,25 @@
#pragma once
#include <cstdint>
#include <string>
// config
#include "config.hpp"
namespace rpc_core {
#if __cplusplus >= 201402L
#define RPC_CORE_MOVE_LAMBDA(arg) arg = std::move(arg)
#define RPC_CORE_MOVE_PARAM(arg) arg
#else
#define RPC_CORE_MOVE_LAMBDA(arg) arg
#define RPC_CORE_MOVE_PARAM(arg) const arg&
#endif
#define RPC_CORE_UNUSED(x) (void)x
using cmd_type = std::string;
using seq_type = uint32_t;
} // namespace rpc_core

View File

@ -0,0 +1,8 @@
#pragma once
#define RPC_CORE_VER_MAJOR 2
#define RPC_CORE_VER_MINOR 0
#define RPC_CORE_VER_PATCH 1
#define RPC_CORE_TO_VERSION(major, minor, patch) (major * 10000 + minor * 100 + patch)
#define RPC_CORE_VERSION RPC_CORE_TO_VERSION(RPC_CORE_VER_MAJOR, RPC_CORE_VER_MINOR, RPC_CORE_VER_PATCH)