feat add rpc_core
All checks were successful
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Successful in 1m6s
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Successful in 1m9s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Successful in 1m17s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Successful in 1m22s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Successful in 1m39s
linux-mips64-gcc / linux-gcc-mips64el (push) Successful in 1m48s
linux-x64-gcc / linux-gcc (push) Successful in 2m3s
All checks were successful
rpcrypto-build / build (Debug, hisiv510.toolchain.cmake) (push) Successful in 1m6s
rpcrypto-build / build (Debug, himix200.toolchain.cmake) (push) Successful in 1m9s
rpcrypto-build / build (Release, himix200.toolchain.cmake) (push) Successful in 1m17s
rpcrypto-build / build (Release, hisiv510.toolchain.cmake) (push) Successful in 1m22s
linux-hisiv500-gcc / linux-gcc-hisiv500 (push) Successful in 1m39s
linux-mips64-gcc / linux-gcc-mips64el (push) Successful in 1m48s
linux-x64-gcc / linux-gcc (push) Successful in 2m3s
This commit is contained in:
parent
6e1491fd41
commit
c3b5a29da2
5
3party/rpc_core/.clang-format
Normal file
5
3party/rpc_core/.clang-format
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
ColumnLimit: 150
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortLambdasOnASingleLine: Empty
|
29
3party/rpc_core/.github/workflows/build.yml
vendored
Normal file
29
3party/rpc_core/.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
name: build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
pull_request:
|
||||||
|
paths-ignore:
|
||||||
|
- '**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
Linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: CMake
|
||||||
|
run: |
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Debug -DRPC_CORE_TEST_PLUGIN=ON ..
|
||||||
|
|
||||||
|
- name: Init thirdparty
|
||||||
|
run: cd build && make rpc_core_test_init
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cd build && make -j2
|
||||||
|
|
||||||
|
- name: Run
|
||||||
|
run: cd build && ./rpc_core_test
|
14
3party/rpc_core/.gitignore
vendored
Normal file
14
3party/rpc_core/.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
build/
|
||||||
|
|
||||||
|
# clion
|
||||||
|
.idea/
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# qt creator
|
||||||
|
CMakeLists.txt.user
|
||||||
|
|
||||||
|
# vscode
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
# thirdparty
|
||||||
|
/thirdparty/
|
54
3party/rpc_core/CMakeLists.txt
Normal file
54
3party/rpc_core/CMakeLists.txt
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
project(rpc_core CXX)
|
||||||
|
|
||||||
|
option(RPC_CORE_BUILD_TEST "" OFF)
|
||||||
|
option(RPC_CORE_TEST_PLUGIN "" OFF)
|
||||||
|
option(RPC_CORE_TEST_LINK_PTHREAD "" OFF)
|
||||||
|
|
||||||
|
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||||
|
set(RPC_CORE_BUILD_TEST ON)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
add_compile_options(-Wall -Wunused-parameter)
|
||||||
|
|
||||||
|
add_library(${PROJECT_NAME} INTERFACE)
|
||||||
|
target_include_directories(${PROJECT_NAME} INTERFACE include)
|
||||||
|
|
||||||
|
if (RPC_CORE_BUILD_TEST)
|
||||||
|
set(EXAMPLE_COMPILE_DEFINE
|
||||||
|
ANDROID_STANDALONE
|
||||||
|
RPC_CORE_LOG_SHOW_DEBUG
|
||||||
|
# RPC_CORE_LOG_SHOW_VERBOSE
|
||||||
|
)
|
||||||
|
|
||||||
|
set(TARGET_NAME ${PROJECT_NAME}_test)
|
||||||
|
file(GLOB SRCS test/main.cpp test/test_rpc.cpp test/test_serialize.cpp test/test_data_packer.cpp)
|
||||||
|
add_executable(${TARGET_NAME})
|
||||||
|
if (RPC_CORE_TEST_LINK_PTHREAD)
|
||||||
|
# some linux platform need link -pthread for std::future api
|
||||||
|
set(LIBRARIES -pthread)
|
||||||
|
endif ()
|
||||||
|
target_link_libraries(${TARGET_NAME} ${PROJECT_NAME} ${LIBRARIES})
|
||||||
|
target_compile_definitions(${TARGET_NAME} PRIVATE ${EXAMPLE_COMPILE_DEFINE})
|
||||||
|
|
||||||
|
if (RPC_CORE_TEST_PLUGIN)
|
||||||
|
list(APPEND SRCS test/test_plugin.cpp)
|
||||||
|
target_compile_definitions(${TARGET_NAME} PRIVATE "RPC_CORE_TEST_PLUGIN")
|
||||||
|
add_custom_target(${TARGET_NAME}_init
|
||||||
|
# clear dir
|
||||||
|
COMMAND rm -rf ${CMAKE_CURRENT_LIST_DIR}/thirdparty
|
||||||
|
# json
|
||||||
|
COMMAND mkdir -p ${CMAKE_CURRENT_LIST_DIR}/thirdparty/nlohmann
|
||||||
|
COMMAND curl -L -o ${CMAKE_CURRENT_LIST_DIR}/thirdparty/nlohmann/json.hpp https://github.com/nlohmann/json/releases/download/v3.11.2/json.hpp
|
||||||
|
# flatbuffers
|
||||||
|
COMMAND git clone https://github.com/google/flatbuffers.git --depth=1 --branch=v23.1.21 ${CMAKE_CURRENT_LIST_DIR}/thirdparty/flatbuffers
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE thirdparty)
|
||||||
|
target_include_directories(${TARGET_NAME} PRIVATE thirdparty/flatbuffers/include)
|
||||||
|
endif ()
|
||||||
|
target_sources(${TARGET_NAME} PRIVATE ${SRCS})
|
||||||
|
endif ()
|
148
3party/rpc_core/README.md
Normal file
148
3party/rpc_core/README.md
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
# rpc_core
|
||||||
|
|
||||||
|
[![Build Status](https://github.com/shuai132/rpc_core/workflows/build/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=build)
|
||||||
|
|
||||||
|
a tiny c++11 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips (
|
||||||
|
Arduino, STM32, ESP32/ESP8266, etc.)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The complete rpc frameworks (such as `gRPC` and `brpc`) have complex functions
|
||||||
|
and are not practical on embedded platforms.
|
||||||
|
|
||||||
|
This project offers a lightweight and user-friendly rpc library that is better suited for one-to-one rpc calls.
|
||||||
|
It supports all platforms and a wide range of microchips, including Arduino, STM32, ESP32/ESP8266, and more.
|
||||||
|
|
||||||
|
Note:
|
||||||
|
This project solely offers the protocol layer and API,
|
||||||
|
and `does not include the implementation of the transport layer`.
|
||||||
|
For TCP-based implementations: [asio_net](https://github.com/shuai132/asio_net)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
* Header-Only
|
||||||
|
* No-Schema
|
||||||
|
* Support performance-limited platforms including microchips
|
||||||
|
* Support any connection type (`tcp socket`, `serial port`, etc.)
|
||||||
|
* High Performance Serialization, support most STL containers and user type
|
||||||
|
* Serialization plugins implementations for `flatbuffers` and `nlohmann::json`
|
||||||
|
* RAII-based `dispose` for automatic cancel request
|
||||||
|
* Timeout and Retry API
|
||||||
|
* Support `std::future` interface
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* C++11
|
||||||
|
* Provide your connection implementation: [connection](include/rpc_core/connection.hpp)
|
||||||
|
NOTICE: complete data packets are required for data transmission, such as `websocket`.
|
||||||
|
If using `tcp socket`, `serial port`, etc., message pack and unpack need to be implemented.
|
||||||
|
Or you can use [stream_connection](include/rpc_core/connection.hpp).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```c++
|
||||||
|
// The Receiver
|
||||||
|
rpc->subscribe("cmd", [](const std::string& msg) -> std::string {
|
||||||
|
assert(msg == "hello");
|
||||||
|
return "world";
|
||||||
|
});
|
||||||
|
|
||||||
|
// The Sender
|
||||||
|
rpc->cmd("cmd")
|
||||||
|
->msg(std::string("hello"))
|
||||||
|
->rsp([](const std::string& rsp) {
|
||||||
|
assert(rsp == "world");
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
```
|
||||||
|
|
||||||
|
`msg` and `rsp` support any serializable type, see [Serialization](#Serialization).
|
||||||
|
|
||||||
|
Detailed usages and unittests can be found here: [rpc_test.cpp](test/test_rpc.cpp)
|
||||||
|
|
||||||
|
## Serialization
|
||||||
|
|
||||||
|
High-performance and memory-saving binary serialization.
|
||||||
|
|
||||||
|
For example, user data:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct Type {
|
||||||
|
uint8_t id = 1;
|
||||||
|
uint8_t age = 18;
|
||||||
|
std::string name = "test";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
json: `{"id":1,"age":18,"name":"test"}`
|
||||||
|
|
||||||
|
| library | bytes |
|
||||||
|
|-------------|:-----:|
|
||||||
|
| json | 31 |
|
||||||
|
| flatbuffers | 44 |
|
||||||
|
| protobuf | 10 |
|
||||||
|
| msgpack | 8 |
|
||||||
|
| rpc_core | 8 |
|
||||||
|
|
||||||
|
- [x] [std::string](https://en.cppreference.com/w/cpp/string/basic_string)
|
||||||
|
- [x] [std::wstring](https://en.cppreference.com/w/cpp/string/basic_string)
|
||||||
|
- [x] [std::array](https://en.cppreference.com/w/cpp/container/array)
|
||||||
|
- [x] [std::vector](https://en.cppreference.com/w/cpp/container/vector)
|
||||||
|
- [x] [std::list](https://en.cppreference.com/w/cpp/container/list)
|
||||||
|
- [x] [std::forward_list](https://en.cppreference.com/w/cpp/container/forward_list)
|
||||||
|
- [x] [std::deque](https://en.cppreference.com/w/cpp/container/deque)
|
||||||
|
- [x] [std::pair](https://en.cppreference.com/w/cpp/utility/pair)
|
||||||
|
- [x] [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple)
|
||||||
|
- [x] [std::map](https://en.cppreference.com/w/cpp/container/map)
|
||||||
|
- [x] [std::unordered_map](https://en.cppreference.com/w/cpp/container/unordered_map)
|
||||||
|
- [x] [std::multimap](https://en.cppreference.com/w/cpp/container/multimap)
|
||||||
|
- [x] [std::unordered_multimap](https://en.cppreference.com/w/cpp/container/unordered_multimap)
|
||||||
|
- [x] [std::set](https://en.cppreference.com/w/cpp/container/set)
|
||||||
|
- [x] [std::unordered_set](https://en.cppreference.com/w/cpp/container/unordered_set)
|
||||||
|
- [x] [std::multiset](https://en.cppreference.com/w/cpp/container/multiset)
|
||||||
|
- [x] [std::unordered_multiset](https://en.cppreference.com/w/cpp/container/unordered_multiset)
|
||||||
|
- [x] [std::stack](https://en.cppreference.com/w/cpp/container/stack)
|
||||||
|
- [x] [std::queue](https://en.cppreference.com/w/cpp/container/queue)
|
||||||
|
- [x] [std::priority_queue](https://en.cppreference.com/w/cpp/container/priority_queue)
|
||||||
|
- [x] [std::bitset](https://en.cppreference.com/w/cpp/utility/bitset)
|
||||||
|
- [x] [std::complex](https://en.cppreference.com/w/cpp/numeric/complex)
|
||||||
|
- [x] [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration)
|
||||||
|
- [x] [std::chrono::time_point](https://en.cppreference.com/w/cpp/chrono/time_point)
|
||||||
|
- [x] [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr)
|
||||||
|
- [x] [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr)
|
||||||
|
- [x] [rpc_core::binary_wrap](include/rpc_core/serialize/binary_wrap.hpp)
|
||||||
|
- [x] [custom struct/class](test/serialize/CustomType.h)
|
||||||
|
```c++
|
||||||
|
#include "rpc_core/serialize.hpp"
|
||||||
|
struct TestStruct {
|
||||||
|
uint8_t a;
|
||||||
|
std::string b;
|
||||||
|
OtherType c
|
||||||
|
// RPC_CORE_DEFINE_TYPE_INNER(a, b, c);
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE(TestStruct, a, b, c);
|
||||||
|
```
|
||||||
|
choose `RPC_CORE_DEFINE_TYPE` or `RPC_CORE_DEFINE_TYPE_INNER` for private member variable.
|
||||||
|
|
||||||
|
## Serialization Plugins
|
||||||
|
|
||||||
|
* [flatbuffers.hpp](include/rpc_core/plugin/flatbuffers.hpp)
|
||||||
|
Supports using types generated by `flatbuffers` directly as message
|
||||||
|
(add the option `--gen-object-api` when using `flatc`)
|
||||||
|
|
||||||
|
|
||||||
|
* [json_msg.hpp](include/rpc_core/plugin/json_msg.hpp)
|
||||||
|
Supports using types supported by [nlohmann/json](https://github.com/nlohmann/json) directly as message
|
||||||
|
(the `to_json/from_json` rules in `nlohmann/json` need to be satisfied, and use `DEFINE_JSON_CLASS`).
|
||||||
|
|
||||||
|
|
||||||
|
* [json.hpp](include/rpc_core/plugin/json.hpp)
|
||||||
|
A flexible way to use `nlohmann/json`
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
* Implementation based on asio: [asio_net](https://github.com/shuai132/asio_net)
|
||||||
|
support macOS, Linux, Windows, iOS, Android, etc. and can be used on MCUs that support asio, such as ESP32.
|
||||||
|
|
||||||
|
|
||||||
|
* Implementation suitable for ESP8266: [esp_rpc](https://github.com/shuai132/esp_rpc)
|
10
3party/rpc_core/include/rpc_core.hpp
Normal file
10
3party/rpc_core/include/rpc_core.hpp
Normal 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"
|
3
3party/rpc_core/include/rpc_core/config.hpp
Normal file
3
3party/rpc_core/include/rpc_core/config.hpp
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "version.hpp"
|
86
3party/rpc_core/include/rpc_core/connection.hpp
Normal file
86
3party/rpc_core/include/rpc_core/connection.hpp
Normal 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
|
@ -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
|
@ -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
|
25
3party/rpc_core/include/rpc_core/detail/callable/functor.hpp
Normal file
25
3party/rpc_core/include/rpc_core/detail/callable/functor.hpp
Normal 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
|
58
3party/rpc_core/include/rpc_core/detail/callable/helpers.hpp
Normal file
58
3party/rpc_core/include/rpc_core/detail/callable/helpers.hpp
Normal 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
|
@ -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
|
56
3party/rpc_core/include/rpc_core/detail/coder.hpp
Normal file
56
3party/rpc_core/include/rpc_core/detail/coder.hpp
Normal 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
|
17
3party/rpc_core/include/rpc_core/detail/copyable.hpp
Normal file
17
3party/rpc_core/include/rpc_core/detail/copyable.hpp
Normal 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
|
120
3party/rpc_core/include/rpc_core/detail/data_packer.hpp
Normal file
120
3party/rpc_core/include/rpc_core/detail/data_packer.hpp
Normal 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
|
272
3party/rpc_core/include/rpc_core/detail/log.h
Normal file
272
3party/rpc_core/include/rpc_core/detail/log.h
Normal 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
|
168
3party/rpc_core/include/rpc_core/detail/msg_dispatcher.hpp
Normal file
168
3party/rpc_core/include/rpc_core/detail/msg_dispatcher.hpp
Normal 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
|
59
3party/rpc_core/include/rpc_core/detail/msg_wrapper.hpp
Normal file
59
3party/rpc_core/include/rpc_core/detail/msg_wrapper.hpp
Normal 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
|
17
3party/rpc_core/include/rpc_core/detail/noncopyable.hpp
Normal file
17
3party/rpc_core/include/rpc_core/detail/noncopyable.hpp
Normal 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
|
26
3party/rpc_core/include/rpc_core/detail/string_view.hpp
Normal file
26
3party/rpc_core/include/rpc_core/detail/string_view.hpp
Normal 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
|
24
3party/rpc_core/include/rpc_core/detail/type_traits.hpp
Normal file
24
3party/rpc_core/include/rpc_core/detail/type_traits.hpp
Normal 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
|
61
3party/rpc_core/include/rpc_core/dispose.hpp
Normal file
61
3party/rpc_core/include/rpc_core/dispose.hpp
Normal 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
|
35
3party/rpc_core/include/rpc_core/plugin/flatbuffers.hpp
Normal file
35
3party/rpc_core/include/rpc_core/plugin/flatbuffers.hpp
Normal 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
|
26
3party/rpc_core/include/rpc_core/plugin/json.hpp
Normal file
26
3party/rpc_core/include/rpc_core/plugin/json.hpp
Normal 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
|
26
3party/rpc_core/include/rpc_core/plugin/json_msg.hpp
Normal file
26
3party/rpc_core/include/rpc_core/plugin/json_msg.hpp
Normal 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);
|
384
3party/rpc_core/include/rpc_core/request.hpp
Normal file
384
3party/rpc_core/include/rpc_core/request.hpp
Normal 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
|
165
3party/rpc_core/include/rpc_core/rpc.hpp
Normal file
165
3party/rpc_core/include/rpc_core/rpc.hpp
Normal 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
|
34
3party/rpc_core/include/rpc_core/serialize.hpp
Normal file
34
3party/rpc_core/include/rpc_core/serialize.hpp
Normal 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"
|
38
3party/rpc_core/include/rpc_core/serialize/binary_wrap.hpp
Normal file
38
3party/rpc_core/include/rpc_core/serialize/binary_wrap.hpp
Normal 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
|
@ -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
|
57
3party/rpc_core/include/rpc_core/serialize/std_array.hpp
Normal file
57
3party/rpc_core/include/rpc_core/serialize/std_array.hpp
Normal 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
|
@ -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
|
33
3party/rpc_core/include/rpc_core/serialize/std_bitset.hpp
Normal file
33
3party/rpc_core/include/rpc_core/serialize/std_bitset.hpp
Normal 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
|
53
3party/rpc_core/include/rpc_core/serialize/std_chrono.hpp
Normal file
53
3party/rpc_core/include/rpc_core/serialize/std_chrono.hpp
Normal 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
|
52
3party/rpc_core/include/rpc_core/serialize/std_complex.hpp
Normal file
52
3party/rpc_core/include/rpc_core/serialize/std_complex.hpp
Normal 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
|
@ -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
|
@ -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
|
63
3party/rpc_core/include/rpc_core/serialize/std_list_like.hpp
Normal file
63
3party/rpc_core/include/rpc_core/serialize/std_list_like.hpp
Normal 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
|
57
3party/rpc_core/include/rpc_core/serialize/std_map.hpp
Normal file
57
3party/rpc_core/include/rpc_core/serialize/std_map.hpp
Normal 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
|
34
3party/rpc_core/include/rpc_core/serialize/std_pair.hpp
Normal file
34
3party/rpc_core/include/rpc_core/serialize/std_pair.hpp
Normal 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
|
65
3party/rpc_core/include/rpc_core/serialize/std_set.hpp
Normal file
65
3party/rpc_core/include/rpc_core/serialize/std_set.hpp
Normal 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
|
@ -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
|
147
3party/rpc_core/include/rpc_core/serialize/std_tuple.hpp
Normal file
147
3party/rpc_core/include/rpc_core/serialize/std_tuple.hpp
Normal 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
|
@ -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
|
20
3party/rpc_core/include/rpc_core/serialize/type_enum.hpp
Normal file
20
3party/rpc_core/include/rpc_core/serialize/type_enum.hpp
Normal 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
|
22
3party/rpc_core/include/rpc_core/serialize/type_ptr.hpp
Normal file
22
3party/rpc_core/include/rpc_core/serialize/type_ptr.hpp
Normal 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
|
54
3party/rpc_core/include/rpc_core/serialize/type_raw.hpp
Normal file
54
3party/rpc_core/include/rpc_core/serialize/type_raw.hpp
Normal 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
|
200
3party/rpc_core/include/rpc_core/serialize/type_struct.hpp
Normal file
200
3party/rpc_core/include/rpc_core/serialize/type_struct.hpp
Normal 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__) \
|
||||||
|
}
|
17
3party/rpc_core/include/rpc_core/serialize/type_void.hpp
Normal file
17
3party/rpc_core/include/rpc_core/serialize/type_void.hpp
Normal 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
|
82
3party/rpc_core/include/rpc_core/serialize_type.hpp
Normal file
82
3party/rpc_core/include/rpc_core/serialize_type.hpp
Normal 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
|
25
3party/rpc_core/include/rpc_core/type.hpp
Normal file
25
3party/rpc_core/include/rpc_core/type.hpp
Normal 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
|
8
3party/rpc_core/include/rpc_core/version.hpp
Normal file
8
3party/rpc_core/include/rpc_core/version.hpp
Normal 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)
|
20
3party/rpc_core/library.json
Normal file
20
3party/rpc_core/library.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "rpc_core",
|
||||||
|
"description": "a tiny c++11 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips (Arduino, STM32, ESP32/ESP8266, etc.)",
|
||||||
|
"keywords": "rpc",
|
||||||
|
"authors": {
|
||||||
|
"name": "shuai132",
|
||||||
|
"maintainer": true
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/shuai132/rpc_core.git"
|
||||||
|
},
|
||||||
|
"version": "2.0.1",
|
||||||
|
"build": {
|
||||||
|
"srcDir": "_",
|
||||||
|
"flags": [
|
||||||
|
"-I include"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
12
3party/rpc_core/test/assert_def.h
Normal file
12
3party/rpc_core/test/assert_def.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#define __ASSERT(e, file, line) \
|
||||||
|
((void)printf ("%s:%d: failed assertion `%s'\n", file, line, e), abort())
|
||||||
|
|
||||||
|
#define ASSERT(e) \
|
||||||
|
((void) ((e) ? ((void)0) : __ASSERT (#e, __FILE__, __LINE__)))
|
31
3party/rpc_core/test/main.cpp
Normal file
31
3party/rpc_core/test/main.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include "rpc_core.hpp"
|
||||||
|
#include "rpc_core/detail/log.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
using namespace rpc_core_test;
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
RPC_CORE_LOG("version: %d", RPC_CORE_VERSION);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
RPC_CORE_LOG("test_serialize...");
|
||||||
|
test_serialize();
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
RPC_CORE_LOG("test_data_packer...");
|
||||||
|
test_data_packer();
|
||||||
|
|
||||||
|
#ifdef RPC_CORE_TEST_PLUGIN
|
||||||
|
printf("\n");
|
||||||
|
RPC_CORE_LOG("test_plugin...");
|
||||||
|
test_plugin();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
RPC_CORE_LOG("test_rpc...");
|
||||||
|
test_rpc();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
11
3party/rpc_core/test/plugin/JsonType.h
Normal file
11
3party/rpc_core/test/plugin/JsonType.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nlohmann/json.hpp"
|
||||||
|
#include "rpc_core/plugin/json_msg.hpp"
|
||||||
|
|
||||||
|
struct JsonType {
|
||||||
|
int id = 0;
|
||||||
|
std::string name;
|
||||||
|
uint8_t age = 0;
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE_JSON(JsonType, id, name, age);
|
10
3party/rpc_core/test/plugin/RawType.h
Normal file
10
3party/rpc_core/test/plugin/RawType.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rpc_core/serialize.hpp"
|
||||||
|
|
||||||
|
struct RawType {
|
||||||
|
uint8_t id = 0;
|
||||||
|
std::string name;
|
||||||
|
uint8_t age = 0;
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE(RawType, id, name, age);
|
1
3party/rpc_core/test/plugin/fb/.clang-format
Normal file
1
3party/rpc_core/test/plugin/fb/.clang-format
Normal file
@ -0,0 +1 @@
|
|||||||
|
DisableFormat: true
|
9
3party/rpc_core/test/plugin/fb/FbMsg.fbs
Normal file
9
3party/rpc_core/test/plugin/fb/FbMsg.fbs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace msg;
|
||||||
|
|
||||||
|
table FbMsg {
|
||||||
|
id: int;
|
||||||
|
age: uint8;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type FbMsg;
|
186
3party/rpc_core/test/plugin/fb/FbMsg_generated.h
Normal file
186
3party/rpc_core/test/plugin/fb/FbMsg_generated.h
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_GENERATED_FBMSG_MSG_H_
|
||||||
|
#define FLATBUFFERS_GENERATED_FBMSG_MSG_H_
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
|
||||||
|
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||||
|
// generated, otherwise it may not be compatible.
|
||||||
|
static_assert(FLATBUFFERS_VERSION_MAJOR == 23 &&
|
||||||
|
FLATBUFFERS_VERSION_MINOR == 1 &&
|
||||||
|
FLATBUFFERS_VERSION_REVISION == 21,
|
||||||
|
"Non-compatible flatbuffers version included");
|
||||||
|
|
||||||
|
namespace msg {
|
||||||
|
|
||||||
|
struct FbMsg;
|
||||||
|
struct FbMsgBuilder;
|
||||||
|
struct FbMsgT;
|
||||||
|
|
||||||
|
struct FbMsgT : public ::flatbuffers::NativeTable {
|
||||||
|
typedef FbMsg TableType;
|
||||||
|
int32_t id = 0;
|
||||||
|
uint8_t age = 0;
|
||||||
|
std::string name{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FbMsg FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||||
|
typedef FbMsgT NativeTableType;
|
||||||
|
typedef FbMsgBuilder Builder;
|
||||||
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
|
VT_ID = 4,
|
||||||
|
VT_AGE = 6,
|
||||||
|
VT_NAME = 8
|
||||||
|
};
|
||||||
|
int32_t id() const {
|
||||||
|
return GetField<int32_t>(VT_ID, 0);
|
||||||
|
}
|
||||||
|
uint8_t age() const {
|
||||||
|
return GetField<uint8_t>(VT_AGE, 0);
|
||||||
|
}
|
||||||
|
const ::flatbuffers::String *name() const {
|
||||||
|
return GetPointer<const ::flatbuffers::String *>(VT_NAME);
|
||||||
|
}
|
||||||
|
bool Verify(::flatbuffers::Verifier &verifier) const {
|
||||||
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyField<int32_t>(verifier, VT_ID, 4) &&
|
||||||
|
VerifyField<uint8_t>(verifier, VT_AGE, 1) &&
|
||||||
|
VerifyOffset(verifier, VT_NAME) &&
|
||||||
|
verifier.VerifyString(name()) &&
|
||||||
|
verifier.EndTable();
|
||||||
|
}
|
||||||
|
FbMsgT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||||
|
void UnPackTo(FbMsgT *_o, const ::flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||||
|
static ::flatbuffers::Offset<FbMsg> Pack(::flatbuffers::FlatBufferBuilder &_fbb, const FbMsgT* _o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FbMsgBuilder {
|
||||||
|
typedef FbMsg Table;
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
|
::flatbuffers::uoffset_t start_;
|
||||||
|
void add_id(int32_t id) {
|
||||||
|
fbb_.AddElement<int32_t>(FbMsg::VT_ID, id, 0);
|
||||||
|
}
|
||||||
|
void add_age(uint8_t age) {
|
||||||
|
fbb_.AddElement<uint8_t>(FbMsg::VT_AGE, age, 0);
|
||||||
|
}
|
||||||
|
void add_name(::flatbuffers::Offset<::flatbuffers::String> name) {
|
||||||
|
fbb_.AddOffset(FbMsg::VT_NAME, name);
|
||||||
|
}
|
||||||
|
explicit FbMsgBuilder(::flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
|
: fbb_(_fbb) {
|
||||||
|
start_ = fbb_.StartTable();
|
||||||
|
}
|
||||||
|
::flatbuffers::Offset<FbMsg> Finish() {
|
||||||
|
const auto end = fbb_.EndTable(start_);
|
||||||
|
auto o = ::flatbuffers::Offset<FbMsg>(end);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<FbMsg> CreateFbMsg(
|
||||||
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
int32_t id = 0,
|
||||||
|
uint8_t age = 0,
|
||||||
|
::flatbuffers::Offset<::flatbuffers::String> name = 0) {
|
||||||
|
FbMsgBuilder builder_(_fbb);
|
||||||
|
builder_.add_name(name);
|
||||||
|
builder_.add_id(id);
|
||||||
|
builder_.add_age(age);
|
||||||
|
return builder_.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<FbMsg> CreateFbMsgDirect(
|
||||||
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
int32_t id = 0,
|
||||||
|
uint8_t age = 0,
|
||||||
|
const char *name = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
return msg::CreateFbMsg(
|
||||||
|
_fbb,
|
||||||
|
id,
|
||||||
|
age,
|
||||||
|
name__);
|
||||||
|
}
|
||||||
|
|
||||||
|
::flatbuffers::Offset<FbMsg> CreateFbMsg(::flatbuffers::FlatBufferBuilder &_fbb, const FbMsgT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|
||||||
|
inline FbMsgT *FbMsg::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||||
|
auto _o = std::unique_ptr<FbMsgT>(new FbMsgT());
|
||||||
|
UnPackTo(_o.get(), _resolver);
|
||||||
|
return _o.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FbMsg::UnPackTo(FbMsgT *_o, const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||||
|
(void)_o;
|
||||||
|
(void)_resolver;
|
||||||
|
{ auto _e = id(); _o->id = _e; }
|
||||||
|
{ auto _e = age(); _o->age = _e; }
|
||||||
|
{ auto _e = name(); if (_e) _o->name = _e->str(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<FbMsg> FbMsg::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const FbMsgT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||||
|
return CreateFbMsg(_fbb, _o, _rehasher);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ::flatbuffers::Offset<FbMsg> CreateFbMsg(::flatbuffers::FlatBufferBuilder &_fbb, const FbMsgT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) {
|
||||||
|
(void)_rehasher;
|
||||||
|
(void)_o;
|
||||||
|
struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const FbMsgT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||||
|
auto _id = _o->id;
|
||||||
|
auto _age = _o->age;
|
||||||
|
auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
|
||||||
|
return msg::CreateFbMsg(
|
||||||
|
_fbb,
|
||||||
|
_id,
|
||||||
|
_age,
|
||||||
|
_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const msg::FbMsg *GetFbMsg(const void *buf) {
|
||||||
|
return ::flatbuffers::GetRoot<msg::FbMsg>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const msg::FbMsg *GetSizePrefixedFbMsg(const void *buf) {
|
||||||
|
return ::flatbuffers::GetSizePrefixedRoot<msg::FbMsg>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool VerifyFbMsgBuffer(
|
||||||
|
::flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifyBuffer<msg::FbMsg>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool VerifySizePrefixedFbMsgBuffer(
|
||||||
|
::flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifySizePrefixedBuffer<msg::FbMsg>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FinishFbMsgBuffer(
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
::flatbuffers::Offset<msg::FbMsg> root) {
|
||||||
|
fbb.Finish(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FinishSizePrefixedFbMsgBuffer(
|
||||||
|
::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
::flatbuffers::Offset<msg::FbMsg> root) {
|
||||||
|
fbb.FinishSizePrefixed(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unique_ptr<msg::FbMsgT> UnPackFbMsg(
|
||||||
|
const void *buf,
|
||||||
|
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||||
|
return std::unique_ptr<msg::FbMsgT>(GetFbMsg(buf)->UnPack(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::unique_ptr<msg::FbMsgT> UnPackSizePrefixedFbMsg(
|
||||||
|
const void *buf,
|
||||||
|
const ::flatbuffers::resolver_function_t *res = nullptr) {
|
||||||
|
return std::unique_ptr<msg::FbMsgT>(GetSizePrefixedFbMsg(buf)->UnPack(res));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace msg
|
||||||
|
|
||||||
|
#endif // FLATBUFFERS_GENERATED_FBMSG_MSG_H_
|
65
3party/rpc_core/test/serialize/CustomType.h
Normal file
65
3party/rpc_core/test/serialize/CustomType.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rpc_core/serialize.hpp"
|
||||||
|
|
||||||
|
struct CustomType {
|
||||||
|
uint32_t id = 0;
|
||||||
|
std::vector<uint32_t> ids;
|
||||||
|
std::string name;
|
||||||
|
bool operator==(const CustomType& t) const {
|
||||||
|
return std::tie(id, ids, name) == std::tie(t.id, t.ids, t.name);
|
||||||
|
}
|
||||||
|
bool operator<(const CustomType& t) const {
|
||||||
|
return std::tie(id, ids, name) < std::tie(t.id, t.ids, t.name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE(CustomType, id, ids, name);
|
||||||
|
|
||||||
|
// 指针
|
||||||
|
struct CustomTypePtr {
|
||||||
|
int32_t* int_n;
|
||||||
|
int32_t* int_v;
|
||||||
|
std::unique_ptr<int32_t> unique_ptr_n;
|
||||||
|
std::unique_ptr<int32_t> unique_ptr_v;
|
||||||
|
std::shared_ptr<int32_t> shared_ptr_n;
|
||||||
|
std::shared_ptr<int32_t> shared_ptr_v;
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE(CustomTypePtr, int_n, int_v, unique_ptr_n, unique_ptr_v, shared_ptr_n, shared_ptr_v);
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct CustomType2 {
|
||||||
|
uint8_t id1{};
|
||||||
|
uint8_t id2{};
|
||||||
|
uint32_t id3{};
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
RPC_CORE_DEFINE_TYPE(CustomType2, id1, id2, id3);
|
||||||
|
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
struct CustomType3 {
|
||||||
|
uint8_t id1{};
|
||||||
|
uint8_t id2{};
|
||||||
|
uint32_t id3{};
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
RPC_CORE_DEFINE_TYPE(CustomType3, id1, id2, id3);
|
||||||
|
|
||||||
|
namespace test {
|
||||||
|
// 嵌套定义
|
||||||
|
struct CustomTypeNest {
|
||||||
|
CustomType2 c2{};
|
||||||
|
CustomType3 c3{};
|
||||||
|
CustomTypeNest* ptr{};
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE(test::CustomTypeNest, c2, c3, ptr);
|
||||||
|
|
||||||
|
// 内部定义
|
||||||
|
struct CustomTypeNest2 {
|
||||||
|
// can be private
|
||||||
|
CustomType2 c2{};
|
||||||
|
CustomType3 c3{};
|
||||||
|
CustomTypeNest* ptr{};
|
||||||
|
RPC_CORE_DEFINE_TYPE_INNER(c2, c3, ptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace test
|
10
3party/rpc_core/test/serialize/TestStruct.h
Normal file
10
3party/rpc_core/test/serialize/TestStruct.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rpc_core/serialize.hpp"
|
||||||
|
|
||||||
|
struct TestStruct {
|
||||||
|
uint8_t a;
|
||||||
|
uint16_t b;
|
||||||
|
uint32_t c;
|
||||||
|
};
|
||||||
|
RPC_CORE_DEFINE_TYPE(TestStruct, a, b, c);
|
13
3party/rpc_core/test/test.h
Normal file
13
3party/rpc_core/test/test.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace rpc_core_test {
|
||||||
|
|
||||||
|
void test_serialize();
|
||||||
|
|
||||||
|
void test_data_packer();
|
||||||
|
|
||||||
|
void test_rpc();
|
||||||
|
|
||||||
|
void test_plugin();
|
||||||
|
|
||||||
|
} // namespace rpc_core_test
|
95
3party/rpc_core/test/test_data_packer.cpp
Normal file
95
3party/rpc_core/test/test_data_packer.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
#include <ctime>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include "assert_def.h"
|
||||||
|
#include "rpc_core.hpp"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
static void test_simple() {
|
||||||
|
RPC_CORE_LOGI();
|
||||||
|
RPC_CORE_LOGI("test_simple...");
|
||||||
|
rpc_core::detail::data_packer packer;
|
||||||
|
std::string testData = "hello world";
|
||||||
|
std::string packedData;
|
||||||
|
|
||||||
|
packer.pack(testData.data(), testData.size(), [&](const void *data, size_t size) {
|
||||||
|
packedData.insert(packedData.size(), (char *)data, size);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
ASSERT(packedData.size() == testData.size() + 4);
|
||||||
|
|
||||||
|
std::string feedRecData;
|
||||||
|
packer.on_data = [&](std::string data) {
|
||||||
|
feedRecData = std::move(data);
|
||||||
|
};
|
||||||
|
packer.feed(packedData.data(), packedData.size());
|
||||||
|
ASSERT(testData == feedRecData);
|
||||||
|
RPC_CORE_LOGI("packedData PASS");
|
||||||
|
|
||||||
|
std::string packedData2 = packer.pack(testData);
|
||||||
|
ASSERT(packedData2 == packedData);
|
||||||
|
RPC_CORE_LOGI("packedData2 PASS");
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("feed again...");
|
||||||
|
feedRecData.clear();
|
||||||
|
ASSERT(testData != feedRecData);
|
||||||
|
packer.feed(packedData.data(), packedData.size());
|
||||||
|
ASSERT(testData == feedRecData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_random() {
|
||||||
|
RPC_CORE_LOGI();
|
||||||
|
RPC_CORE_LOGI("test_random...");
|
||||||
|
RPC_CORE_LOGI("generate big data...");
|
||||||
|
bool pass = false;
|
||||||
|
std::string TEST_PAYLOAD;
|
||||||
|
size_t TestAddCount = 1000;
|
||||||
|
for (size_t i = 0; i < TestAddCount; i++) {
|
||||||
|
TEST_PAYLOAD += "helloworld"; // 10bytes
|
||||||
|
}
|
||||||
|
RPC_CORE_LOGI("data generated, size:%zu", TEST_PAYLOAD.size());
|
||||||
|
ASSERT(TEST_PAYLOAD.size() == TestAddCount * 10);
|
||||||
|
|
||||||
|
rpc_core::detail::data_packer packer;
|
||||||
|
packer.on_data = [&](const std::string &data) {
|
||||||
|
size_t size = data.size();
|
||||||
|
RPC_CORE_LOGI("get payload size:%zu", size);
|
||||||
|
if (data == TEST_PAYLOAD) {
|
||||||
|
pass = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("packing...");
|
||||||
|
auto payload = packer.pack(TEST_PAYLOAD);
|
||||||
|
const uint32_t payloadSize = payload.size();
|
||||||
|
RPC_CORE_LOGI("payloadSize:%u", payloadSize);
|
||||||
|
ASSERT(payloadSize == TestAddCount * 10 + 4);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("******test normal******");
|
||||||
|
packer.feed(payload.data(), payloadSize);
|
||||||
|
ASSERT(pass);
|
||||||
|
pass = false;
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("******test random******");
|
||||||
|
uint32_t sendLeft = payloadSize;
|
||||||
|
std::default_random_engine generator(time(nullptr)); // NOLINT
|
||||||
|
std::uniform_int_distribution<int> dis(1, 10);
|
||||||
|
auto random = std::bind(dis, generator); // NOLINT
|
||||||
|
while (sendLeft > 0) {
|
||||||
|
uint32_t randomSize = random();
|
||||||
|
// RPC_CORE_LOGI("random: %u, %u", randomSize, sendLeft);
|
||||||
|
size_t needSend = std::min(randomSize, sendLeft);
|
||||||
|
packer.feed(payload.data() + (payloadSize - sendLeft), needSend);
|
||||||
|
sendLeft -= needSend;
|
||||||
|
}
|
||||||
|
ASSERT(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace rpc_core_test {
|
||||||
|
|
||||||
|
void test_data_packer() {
|
||||||
|
test_simple();
|
||||||
|
test_random();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rpc_core_test
|
86
3party/rpc_core/test/test_plugin.cpp
Normal file
86
3party/rpc_core/test/test_plugin.cpp
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "assert_def.h"
|
||||||
|
#include "plugin/JsonType.h"
|
||||||
|
#include "plugin/RawType.h"
|
||||||
|
#include "plugin/fb/FbMsg_generated.h"
|
||||||
|
#include "rpc_core/plugin/flatbuffers.hpp"
|
||||||
|
#include "rpc_core/plugin/json.hpp"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
namespace rpc_core_test {
|
||||||
|
|
||||||
|
void test_plugin() {
|
||||||
|
using namespace rpc_core;
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("RawType...");
|
||||||
|
RawType a;
|
||||||
|
a.id = 1;
|
||||||
|
a.name = "test";
|
||||||
|
a.age = 18;
|
||||||
|
|
||||||
|
auto payload = serialize(a);
|
||||||
|
// payload is not readable
|
||||||
|
RPC_CORE_LOGI("RawType: size: %zu", payload.size());
|
||||||
|
|
||||||
|
RawType b;
|
||||||
|
deserialize(payload, b);
|
||||||
|
ASSERT(a.id == b.id);
|
||||||
|
ASSERT(a.name == b.name);
|
||||||
|
ASSERT(a.age == b.age);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("json...");
|
||||||
|
nlohmann::json a;
|
||||||
|
a["id"] = 1;
|
||||||
|
a["name"] = "test";
|
||||||
|
a["age"] = 18;
|
||||||
|
|
||||||
|
auto payload = serialize(a);
|
||||||
|
RPC_CORE_LOGI("json: %s", payload.c_str());
|
||||||
|
RPC_CORE_LOGI("json: size: %zu", payload.size());
|
||||||
|
|
||||||
|
nlohmann::json b;
|
||||||
|
deserialize(payload, b);
|
||||||
|
ASSERT(b["id"] == a["id"]);
|
||||||
|
ASSERT(b["name"] == a["name"]);
|
||||||
|
ASSERT(b["age"] == a["age"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("JsonType...");
|
||||||
|
JsonType a;
|
||||||
|
a.id = 1;
|
||||||
|
a.name = "test";
|
||||||
|
a.age = 18;
|
||||||
|
|
||||||
|
auto payload = serialize(a);
|
||||||
|
RPC_CORE_LOGI("JsonType: %s", payload.c_str());
|
||||||
|
RPC_CORE_LOGI("JsonType: size: %zu", payload.size());
|
||||||
|
|
||||||
|
JsonType b;
|
||||||
|
deserialize(payload, b);
|
||||||
|
ASSERT(b.id == a.id);
|
||||||
|
ASSERT(b.name == a.name);
|
||||||
|
ASSERT(b.age == a.age);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("flatbuffers...");
|
||||||
|
msg::FbMsgT a;
|
||||||
|
a.id = 1;
|
||||||
|
a.name = "test";
|
||||||
|
a.age = 18;
|
||||||
|
|
||||||
|
auto payload = serialize(a);
|
||||||
|
// flatbuffers payload is not readable
|
||||||
|
RPC_CORE_LOGI("flatbuffers: size: %zu", payload.size());
|
||||||
|
|
||||||
|
msg::FbMsgT b;
|
||||||
|
deserialize(payload, b);
|
||||||
|
ASSERT(b.id == a.id);
|
||||||
|
ASSERT(b.name == a.name);
|
||||||
|
ASSERT(b.age == a.age);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rpc_core_test
|
318
3party/rpc_core/test/test_rpc.cpp
Normal file
318
3party/rpc_core/test/test_rpc.cpp
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
#include "assert_def.h"
|
||||||
|
#include "rpc_core.hpp"
|
||||||
|
#include "serialize/CustomType.h"
|
||||||
|
#include "test.h"
|
||||||
|
|
||||||
|
namespace rpc_core_test {
|
||||||
|
|
||||||
|
void test_rpc() {
|
||||||
|
using namespace rpc_core;
|
||||||
|
|
||||||
|
// 此示例使用回环连接 实际使用时需自定义连接
|
||||||
|
auto connection = std::make_shared<loopback_connection>();
|
||||||
|
|
||||||
|
// 创建rpc 收发消息
|
||||||
|
auto rpc = rpc::create(connection);
|
||||||
|
|
||||||
|
// 定时器实现 应配合当前应用的事件循环 以确保消息收发和超时回调在同一个线程
|
||||||
|
// 此示例使用回环连接 不做超时测试
|
||||||
|
rpc->set_timer([](uint32_t ms, const rpc::timeout_cb& cb) {
|
||||||
|
RPC_CORE_UNUSED(ms);
|
||||||
|
RPC_CORE_UNUSED(cb);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 已连接时设置ready
|
||||||
|
rpc->set_ready(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 简单示例
|
||||||
|
* 以收发`std::string`为例,支持结构体和绝大多数STL容器(见序列化章节)。
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
// The Receiver
|
||||||
|
rpc->subscribe("cmd", [](const std::string& msg) -> std::string {
|
||||||
|
assert(msg == "hello");
|
||||||
|
return "world";
|
||||||
|
});
|
||||||
|
|
||||||
|
// The Sender
|
||||||
|
rpc->cmd("cmd")
|
||||||
|
->msg(std::string("hello"))
|
||||||
|
->rsp([](const std::string& rsp) {
|
||||||
|
assert(rsp == "world");
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 详细测试
|
||||||
|
* 根据使用场景不同 提供以下几种方式
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
RPC_CORE_LOG("1. 收发消息完整测试");
|
||||||
|
// 注册监听
|
||||||
|
rpc->subscribe("cmd1", [&](const std::string& msg) -> std::string {
|
||||||
|
RPC_CORE_LOGI("get cmd1: %s", msg.c_str());
|
||||||
|
ASSERT(msg == "test");
|
||||||
|
return "ok";
|
||||||
|
});
|
||||||
|
|
||||||
|
// 请求支持很多方法 可根据需求使用所需部分
|
||||||
|
bool pass = false;
|
||||||
|
auto request = rpc->cmd("cmd1")
|
||||||
|
->msg(std::string("test"))
|
||||||
|
->rsp([&](const std::string& rsp) {
|
||||||
|
RPC_CORE_LOGI("get rsp from cmd1: %s", rsp.c_str());
|
||||||
|
ASSERT(rsp == "ok");
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->timeout([] {
|
||||||
|
RPC_CORE_LOGI("timeout");
|
||||||
|
})
|
||||||
|
->finally([](finally_t type) {
|
||||||
|
RPC_CORE_LOGI("finally: type:%s", rpc_core::request::finally_t_str(type));
|
||||||
|
});
|
||||||
|
RPC_CORE_LOGI("执行请求");
|
||||||
|
ASSERT(!pass);
|
||||||
|
request->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
|
||||||
|
/// 其他功能测试
|
||||||
|
RPC_CORE_LOGI("多次调用");
|
||||||
|
pass = false;
|
||||||
|
request->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("测试取消");
|
||||||
|
pass = false;
|
||||||
|
request->cancel();
|
||||||
|
request->call();
|
||||||
|
ASSERT(!pass);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("恢复取消");
|
||||||
|
request->reset_cancel();
|
||||||
|
request->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("添加到dispose");
|
||||||
|
pass = false;
|
||||||
|
{ // RAII dispose
|
||||||
|
dispose dispose;
|
||||||
|
request->add_to(dispose);
|
||||||
|
}
|
||||||
|
request->call();
|
||||||
|
ASSERT(!pass);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("先创建request");
|
||||||
|
pass = false;
|
||||||
|
request::create()
|
||||||
|
->cmd("cmd1")
|
||||||
|
->msg(std::string("test"))
|
||||||
|
->rsp([&](const std::string& rsp) {
|
||||||
|
ASSERT(rsp == "ok");
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->call(rpc);
|
||||||
|
ASSERT(pass);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("no_such_cmd");
|
||||||
|
pass = false;
|
||||||
|
request::create()
|
||||||
|
->cmd("cmd_xx")
|
||||||
|
->msg(std::string("test"))
|
||||||
|
->rsp([] {
|
||||||
|
ASSERT(false);
|
||||||
|
})
|
||||||
|
->finally([&](finally_t type) {
|
||||||
|
ASSERT(type == finally_t::no_such_cmd);
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->call(rpc);
|
||||||
|
ASSERT(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("2. 复杂结构体类型测试(包含STL容器)");
|
||||||
|
{
|
||||||
|
bool pass = false;
|
||||||
|
CustomType customType;
|
||||||
|
customType.id = 1;
|
||||||
|
customType.ids = {1, 2, 3};
|
||||||
|
customType.name = "test";
|
||||||
|
|
||||||
|
rpc->subscribe("cmd2", [&](const CustomType& msg) -> CustomType {
|
||||||
|
RPC_CORE_LOGI("get cmd2");
|
||||||
|
ASSERT(msg == customType);
|
||||||
|
return customType;
|
||||||
|
});
|
||||||
|
rpc->cmd("cmd2")
|
||||||
|
->msg(customType)
|
||||||
|
->rsp([&](const CustomType& rsp) {
|
||||||
|
RPC_CORE_LOGI("get rsp from cmd2");
|
||||||
|
ASSERT(rsp == customType);
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("3. finally测试");
|
||||||
|
{
|
||||||
|
bool pass = false;
|
||||||
|
bool pass_finally = false;
|
||||||
|
rpc->subscribe("cmd3", [&](const std::string& msg) {
|
||||||
|
return msg;
|
||||||
|
});
|
||||||
|
rpc->cmd("cmd3")
|
||||||
|
->msg(std::string("test"))
|
||||||
|
->rsp([&](const std::string& rsp) {
|
||||||
|
ASSERT(rsp == "test");
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->finally([&](finally_t type) {
|
||||||
|
ASSERT(type == finally_t::normal);
|
||||||
|
ASSERT(!pass_finally);
|
||||||
|
pass_finally = true;
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
ASSERT(pass_finally);
|
||||||
|
|
||||||
|
pass_finally = false;
|
||||||
|
rpc->cmd("cmd3")
|
||||||
|
->msg(std::string("test"))
|
||||||
|
->finally([&](finally_t type) {
|
||||||
|
ASSERT(type == finally_t::no_need_rsp);
|
||||||
|
ASSERT(!pass_finally);
|
||||||
|
pass_finally = true;
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass_finally);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("4. 多种使用场景测试");
|
||||||
|
{
|
||||||
|
RPC_CORE_LOG("4.1 有参数 有返回");
|
||||||
|
{
|
||||||
|
bool pass_cmd = false;
|
||||||
|
bool pass_rsp = false;
|
||||||
|
rpc->subscribe("cmd4", [&](const std::string& msg) -> std::string {
|
||||||
|
ASSERT(msg == "test");
|
||||||
|
pass_cmd = true;
|
||||||
|
return "test";
|
||||||
|
});
|
||||||
|
rpc->cmd("cmd4")
|
||||||
|
->msg(std::string("test"))
|
||||||
|
->rsp([&](const std::string& msg) {
|
||||||
|
ASSERT(msg == "test");
|
||||||
|
pass_rsp = true;
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass_cmd);
|
||||||
|
ASSERT(pass_rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("4.2 有参数 无返回");
|
||||||
|
{
|
||||||
|
bool pass_cmd = false;
|
||||||
|
rpc->subscribe("cmd4", [&](const std::string& msg) {
|
||||||
|
ASSERT(msg == "test");
|
||||||
|
pass_cmd = true;
|
||||||
|
});
|
||||||
|
rpc->cmd("cmd4")->msg(std::string("test"))->call();
|
||||||
|
ASSERT(pass_cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("4.3 无参数 有返回");
|
||||||
|
{
|
||||||
|
bool pass_cmd = false;
|
||||||
|
bool pass_rsp = false;
|
||||||
|
rpc->subscribe("cmd4", [&]() -> std::string {
|
||||||
|
pass_cmd = true;
|
||||||
|
return "test";
|
||||||
|
});
|
||||||
|
rpc->cmd("cmd4")
|
||||||
|
->rsp([&](const std::string& msg) {
|
||||||
|
pass_rsp = true;
|
||||||
|
ASSERT(msg == "test");
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass_cmd);
|
||||||
|
ASSERT(pass_rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("4.4 无参数 无返回");
|
||||||
|
{
|
||||||
|
bool pass_cmd = false;
|
||||||
|
rpc->subscribe("cmd4", [&]() {
|
||||||
|
pass_cmd = true;
|
||||||
|
});
|
||||||
|
rpc->cmd("cmd4")->call();
|
||||||
|
ASSERT(pass_cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("5. ping pong测试");
|
||||||
|
{
|
||||||
|
bool pass = false;
|
||||||
|
rpc->ping("test")
|
||||||
|
->rsp([&](const std::string& payload) {
|
||||||
|
RPC_CORE_LOGI("get rsp from ping: %s", payload.c_str());
|
||||||
|
ASSERT(payload == "test");
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
RPC_CORE_LOG("6. dispose测试");
|
||||||
|
{
|
||||||
|
bool pass = false;
|
||||||
|
auto request = rpc->ping("test")
|
||||||
|
->rsp([&](const std::string& payload) {
|
||||||
|
RPC_CORE_UNUSED(payload);
|
||||||
|
ASSERT(false);
|
||||||
|
})
|
||||||
|
->finally([&](finally_t type) {
|
||||||
|
ASSERT(type == finally_t::canceled);
|
||||||
|
pass = true;
|
||||||
|
});
|
||||||
|
{
|
||||||
|
dispose dispose;
|
||||||
|
request->add_to(dispose);
|
||||||
|
}
|
||||||
|
request->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef RPC_CORE_FEATURE_DISABLE_FUTURE
|
||||||
|
RPC_CORE_LOG("7. future模式测试");
|
||||||
|
{
|
||||||
|
{
|
||||||
|
auto result = rpc->ping("test")->future<std::string>().get();
|
||||||
|
ASSERT(result.type == finally_t::normal);
|
||||||
|
ASSERT(result.data == "test");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto result = rpc->ping()->future<void>().get();
|
||||||
|
ASSERT(result.type == finally_t::normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
RPC_CORE_LOG("8. 未ready的rpc对象");
|
||||||
|
{
|
||||||
|
bool pass = false;
|
||||||
|
auto rpc_tmp = rpc::create(connection);
|
||||||
|
rpc_tmp->cmd("cmd")->call(); // should not crash
|
||||||
|
rpc_tmp->cmd("cmd")
|
||||||
|
->finally([&](finally_t type) {
|
||||||
|
RPC_CORE_LOG("finally: %d", (int)type);
|
||||||
|
ASSERT(type == finally_t::rpc_not_ready);
|
||||||
|
pass = true;
|
||||||
|
})
|
||||||
|
->call();
|
||||||
|
ASSERT(pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rpc_core_test
|
586
3party/rpc_core/test/test_serialize.cpp
Normal file
586
3party/rpc_core/test/test_serialize.cpp
Normal file
@ -0,0 +1,586 @@
|
|||||||
|
#include <cinttypes>
|
||||||
|
|
||||||
|
#include "assert_def.h"
|
||||||
|
#include "rpc_core.hpp"
|
||||||
|
#include "serialize/CustomType.h"
|
||||||
|
|
||||||
|
namespace rpc_core_test {
|
||||||
|
|
||||||
|
static size_t last_serialize_size = 0;
|
||||||
|
|
||||||
|
template <typename T, typename R>
|
||||||
|
void serialize_test(const T& a, R& b) {
|
||||||
|
std::string data = rpc_core::serialize(a);
|
||||||
|
last_serialize_size = data.size();
|
||||||
|
RPC_CORE_LOGI(" size: %zu", last_serialize_size);
|
||||||
|
bool ret = rpc_core::deserialize(data, b);
|
||||||
|
ASSERT(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void raw_type_test() {
|
||||||
|
T a = 123;
|
||||||
|
T b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
auto ok = (0 == memcmp(&a, &b, sizeof(T))); // NOLINT
|
||||||
|
ASSERT(ok);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define RAW_TYPE_TEST(t) \
|
||||||
|
RPC_CORE_LOGI(" <" #t ">"); \
|
||||||
|
raw_type_test<t>();
|
||||||
|
|
||||||
|
#define ASSERT_SERIALIZE_SIZE(x) ASSERT(last_serialize_size == x)
|
||||||
|
|
||||||
|
static bool is_little_endian() {
|
||||||
|
int x = 1;
|
||||||
|
return *(char*)&x != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_auto_size() {
|
||||||
|
using namespace rpc_core::detail;
|
||||||
|
auto test_auto_size = [](size_t value, int except_size) {
|
||||||
|
RPC_CORE_LOGI("value: 0x%" PRIxMAX "(%" PRIiMAX ") except: %d", value, value, except_size);
|
||||||
|
auto_size a(value);
|
||||||
|
std::string payload = a.serialize();
|
||||||
|
ASSERT(payload.size() == (size_t)except_size);
|
||||||
|
auto_size b;
|
||||||
|
int cost = b.deserialize(payload.data());
|
||||||
|
ASSERT(cost = except_size);
|
||||||
|
ASSERT(value == b.value);
|
||||||
|
};
|
||||||
|
test_auto_size(0x00, 1);
|
||||||
|
test_auto_size(0x01, 2);
|
||||||
|
test_auto_size(0xff, 2);
|
||||||
|
test_auto_size(0xfff, 3);
|
||||||
|
test_auto_size(0xffff, 3);
|
||||||
|
test_auto_size(0xfffff, 4);
|
||||||
|
test_auto_size(0xffffff, 4);
|
||||||
|
test_auto_size(0xfffffff, 5);
|
||||||
|
test_auto_size(0xffffffff, 5);
|
||||||
|
|
||||||
|
auto test_auto_int = [](intmax_t value, int except_size) {
|
||||||
|
RPC_CORE_LOGI("value: 0x%" PRIxMAX "(%" PRIiMAX ") except: %d", value, value, except_size);
|
||||||
|
auto_intmax a(value);
|
||||||
|
std::string payload = a.serialize();
|
||||||
|
ASSERT(payload.size() == (size_t)except_size);
|
||||||
|
auto_intmax b;
|
||||||
|
int cost = b.deserialize(payload.data());
|
||||||
|
ASSERT(cost = except_size);
|
||||||
|
ASSERT(value == b.value);
|
||||||
|
};
|
||||||
|
test_auto_int(0x00, 1);
|
||||||
|
test_auto_int(0xff, 2);
|
||||||
|
test_auto_int(-0xff, 2);
|
||||||
|
test_auto_int(0xffff, 3);
|
||||||
|
test_auto_int(-0xffff, 3);
|
||||||
|
test_auto_int(0xffffff, 4);
|
||||||
|
test_auto_int(-0xffffff, 4);
|
||||||
|
test_auto_int(intmax_t(0xffffffff), 5);
|
||||||
|
test_auto_int(-(intmax_t(0xffffffff)), 5);
|
||||||
|
|
||||||
|
auto test_auto_uint = [](uintmax_t value, int except_size) {
|
||||||
|
RPC_CORE_LOGI("value: 0x%" PRIxMAX "(%" PRIiMAX ") except: %d", value, value, except_size);
|
||||||
|
auto_uintmax a(value);
|
||||||
|
std::string payload = a.serialize();
|
||||||
|
ASSERT(payload.size() == (size_t)except_size);
|
||||||
|
auto_uintmax b;
|
||||||
|
int cost = b.deserialize(payload.data());
|
||||||
|
ASSERT(cost = except_size);
|
||||||
|
ASSERT(value == b.value);
|
||||||
|
};
|
||||||
|
test_auto_uint(0x00, 1);
|
||||||
|
test_auto_uint(0xff, 2);
|
||||||
|
test_auto_uint(0xffff, 3);
|
||||||
|
test_auto_uint(0xffffff, 4);
|
||||||
|
test_auto_uint(uintmax_t(0xffffffff), 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_serialize() {
|
||||||
|
/// only support little endian
|
||||||
|
ASSERT(is_little_endian());
|
||||||
|
|
||||||
|
/// auto_size
|
||||||
|
test_auto_size();
|
||||||
|
|
||||||
|
/// raw type
|
||||||
|
{
|
||||||
|
int32_t a = -1;
|
||||||
|
int32_t b = 0;
|
||||||
|
|
||||||
|
std::string data = rpc_core::serialize(a);
|
||||||
|
bool ret = rpc_core::deserialize(data, b);
|
||||||
|
ASSERT(ret);
|
||||||
|
|
||||||
|
RPC_CORE_LOGI("raw type test...");
|
||||||
|
RAW_TYPE_TEST(char);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1);
|
||||||
|
RAW_TYPE_TEST(int8_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1);
|
||||||
|
RAW_TYPE_TEST(uint8_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1);
|
||||||
|
RAW_TYPE_TEST(int16_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
RAW_TYPE_TEST(uint16_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
RAW_TYPE_TEST(int32_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
RAW_TYPE_TEST(uint32_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
RAW_TYPE_TEST(int64_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
RAW_TYPE_TEST(uint64_t);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
RAW_TYPE_TEST(float);
|
||||||
|
ASSERT_SERIALIZE_SIZE(4);
|
||||||
|
RAW_TYPE_TEST(double);
|
||||||
|
ASSERT_SERIALIZE_SIZE(8);
|
||||||
|
RAW_TYPE_TEST(long double);
|
||||||
|
ASSERT_SERIALIZE_SIZE(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// enum
|
||||||
|
{
|
||||||
|
enum class Enum {
|
||||||
|
k_0,
|
||||||
|
k_1,
|
||||||
|
};
|
||||||
|
RPC_CORE_LOGI("enum...");
|
||||||
|
Enum a = Enum::k_1;
|
||||||
|
Enum b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::array
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::array...");
|
||||||
|
std::array<uint32_t, 3> a{1, 2, 3};
|
||||||
|
std::array<uint32_t, 3> b{};
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::string
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::string...");
|
||||||
|
std::string a = "test";
|
||||||
|
std::string b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(b == a);
|
||||||
|
ASSERT_SERIALIZE_SIZE(a.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::wstring
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::wstring...");
|
||||||
|
std::wstring a = L"中文";
|
||||||
|
std::wstring b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(b == a);
|
||||||
|
ASSERT_SERIALIZE_SIZE(a.size() * sizeof(wchar_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::tuple
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::tuple...");
|
||||||
|
bool msg1 = true;
|
||||||
|
uint32_t msg2 = 12;
|
||||||
|
std::string msg3 = "test";
|
||||||
|
std::tuple<bool, uint32_t, std::string> a(msg1, msg2, msg3);
|
||||||
|
std::tuple<bool, uint32_t, std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(std::get<0>(b) == msg1);
|
||||||
|
ASSERT(std::get<1>(b) == msg2);
|
||||||
|
ASSERT(std::get<2>(b) == msg3);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE((1) + (2) + (2 /*size*/ + msg3.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::pair
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::pair...");
|
||||||
|
std::pair<std::string, std::string> a{"k:1", "v:1"};
|
||||||
|
std::pair<std::string, std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(b == a);
|
||||||
|
ASSERT_SERIALIZE_SIZE((2 /*size*/ + 3) * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// list_like type
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::vector...");
|
||||||
|
std::vector<uint32_t> a{1, 2, 3};
|
||||||
|
std::vector<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::list...");
|
||||||
|
std::list<uint32_t> a{1, 2, 3};
|
||||||
|
std::list<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::deque...");
|
||||||
|
std::deque<uint32_t> a{1, 2, 3};
|
||||||
|
std::deque<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std container adaptors
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::stack...");
|
||||||
|
std::stack<uint32_t> a;
|
||||||
|
a.push(1);
|
||||||
|
a.push(2);
|
||||||
|
a.push(3);
|
||||||
|
std::stack<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::queue...");
|
||||||
|
std::queue<uint32_t> a;
|
||||||
|
a.push(1);
|
||||||
|
a.push(2);
|
||||||
|
a.push(3);
|
||||||
|
std::queue<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::priority_queue...");
|
||||||
|
std::priority_queue<uint32_t> a;
|
||||||
|
a.push(1);
|
||||||
|
a.push(2);
|
||||||
|
a.push(3);
|
||||||
|
std::priority_queue<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
for (uint32_t i = 0; i < a.size(); ++i) {
|
||||||
|
ASSERT(a.top() == b.top());
|
||||||
|
a.pop();
|
||||||
|
b.pop();
|
||||||
|
}
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::bitset
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::bitset...");
|
||||||
|
std::bitset<8> a;
|
||||||
|
a.set();
|
||||||
|
std::bitset<8> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(8 /*11111111*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::forward_list
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::forward_list...");
|
||||||
|
std::forward_list<uint32_t> a{1, 2, 3};
|
||||||
|
std::forward_list<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::set
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::set...");
|
||||||
|
std::set<uint32_t> a{1, 2, 3};
|
||||||
|
std::set<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::multiset
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::multiset...");
|
||||||
|
std::multiset<uint32_t> a{1, 2, 3};
|
||||||
|
std::multiset<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::unordered_multiset
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::unordered_multiset...");
|
||||||
|
std::unordered_multiset<uint32_t> a{1, 2, 3};
|
||||||
|
std::unordered_multiset<uint32_t> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + 2 * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::map
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::map...");
|
||||||
|
std::map<std::string, std::string> a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}};
|
||||||
|
std::map<std::string, std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::unordered_map
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::unordered_map...");
|
||||||
|
std::unordered_map<std::string, std::string> a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}};
|
||||||
|
std::unordered_map<std::string, std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::multimap
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::multimap...");
|
||||||
|
std::multimap<std::string, std::string> a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}};
|
||||||
|
std::multimap<std::string, std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::unordered_multimap
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::unordered_multimap...");
|
||||||
|
std::unordered_multimap<std::string, std::string> a{{"k:1", "v:1"}, {"k:2", "v:2"}, {"k:3", "v:3"}};
|
||||||
|
std::unordered_multimap<std::string, std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + (2 /*std::pair*/ + (2 + 3) * 2) * 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ptr
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("ptr...");
|
||||||
|
int* a = (int*)123;
|
||||||
|
int* b = nullptr;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2); // auto size
|
||||||
|
}
|
||||||
|
|
||||||
|
/// binary_wrap
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("binary_wrap...");
|
||||||
|
{
|
||||||
|
uint8_t array[] = {1, 2, 3};
|
||||||
|
size_t data_bytes = sizeof(array);
|
||||||
|
rpc_core::binary_wrap a(array, data_bytes);
|
||||||
|
rpc_core::binary_wrap b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(b.size == data_bytes);
|
||||||
|
ASSERT(b.data != array);
|
||||||
|
ASSERT(0 == memcmp(array, b.data, data_bytes));
|
||||||
|
ASSERT_SERIALIZE_SIZE(2 /*size*/ + data_bytes);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
uint8_t array[] = {1, 2, 3};
|
||||||
|
struct Test {
|
||||||
|
uint8_t* ptr = nullptr;
|
||||||
|
rpc_core::binary_wrap bin;
|
||||||
|
RPC_CORE_DEFINE_TYPE_INNER(ptr, bin);
|
||||||
|
};
|
||||||
|
Test a;
|
||||||
|
a.ptr = array;
|
||||||
|
a.bin = {array, sizeof(array)};
|
||||||
|
Test b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(b.ptr == array);
|
||||||
|
ASSERT(b.bin.size == sizeof(array));
|
||||||
|
ASSERT(b.bin.data != array);
|
||||||
|
ASSERT(0 == memcmp(array, b.bin.data, sizeof(array)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::shared_ptr
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::shared_ptr...");
|
||||||
|
{
|
||||||
|
std::shared_ptr<std::string> a = std::make_shared<std::string>("test");
|
||||||
|
std::shared_ptr<std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(*a == *b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1 /*flag*/ + a->size());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::shared_ptr<std::string> a = nullptr;
|
||||||
|
std::shared_ptr<std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1 /*flag*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::unique_ptr
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::unique_ptr...");
|
||||||
|
{
|
||||||
|
std::unique_ptr<std::string> a = std::unique_ptr<std::string>(new std::string("test"));
|
||||||
|
std::unique_ptr<std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(*a == *b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1 /*flag*/ + a->size());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::unique_ptr<std::string> a = nullptr;
|
||||||
|
std::unique_ptr<std::string> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(1 /*flag*/);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::complex
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::complex...");
|
||||||
|
{
|
||||||
|
std::complex<float> a;
|
||||||
|
a.real(1.23f);
|
||||||
|
a.imag(3.21f);
|
||||||
|
std::complex<float> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(4 /*float*/ * 2);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::complex<CustomType> a;
|
||||||
|
{
|
||||||
|
CustomType t;
|
||||||
|
t.id = 1;
|
||||||
|
t.ids = {1, 2, 3};
|
||||||
|
t.name = "test";
|
||||||
|
a.real(t);
|
||||||
|
a.imag(t);
|
||||||
|
}
|
||||||
|
std::complex<CustomType> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(40);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::duration
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::duration...");
|
||||||
|
std::chrono::seconds a(123);
|
||||||
|
std::chrono::seconds b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(2); // auto size
|
||||||
|
}
|
||||||
|
|
||||||
|
/// std::time_point
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("std::time_point...");
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> a = std::chrono::time_point<std::chrono::steady_clock>::max();
|
||||||
|
std::chrono::time_point<std::chrono::steady_clock> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(9);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// custom class/struct
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("custom type...");
|
||||||
|
CustomType a;
|
||||||
|
a.id = 1;
|
||||||
|
a.ids = {1, 2, 3};
|
||||||
|
a.name = "test";
|
||||||
|
CustomType b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE((2) + (2 /*ids bytes*/ + 2 /*ids size*/ + 2 * 3) + (2 /*name bytes*/ + 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("custom ptr...");
|
||||||
|
CustomTypePtr a;
|
||||||
|
a.int_n = nullptr;
|
||||||
|
a.int_v = (int32_t*)1;
|
||||||
|
a.unique_ptr_n = nullptr;
|
||||||
|
a.unique_ptr_v = std::unique_ptr<int32_t>(new int32_t(1));
|
||||||
|
a.shared_ptr_n = nullptr;
|
||||||
|
a.shared_ptr_v = std::make_shared<int32_t>(1);
|
||||||
|
CustomTypePtr b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(b.int_n == nullptr);
|
||||||
|
ASSERT(b.int_v == (int32_t*)1);
|
||||||
|
ASSERT(b.unique_ptr_n == nullptr);
|
||||||
|
ASSERT(*b.unique_ptr_v == 1);
|
||||||
|
ASSERT(b.shared_ptr_n == nullptr);
|
||||||
|
ASSERT(*b.shared_ptr_v == 1);
|
||||||
|
ASSERT_SERIALIZE_SIZE(23);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("custom type(different alignas)...");
|
||||||
|
CustomType2 a;
|
||||||
|
a.id1 = 1;
|
||||||
|
a.id2 = 2;
|
||||||
|
a.id3 = 3;
|
||||||
|
CustomType3 b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a.id1 == b.id1);
|
||||||
|
ASSERT(a.id2 == b.id2);
|
||||||
|
ASSERT(a.id3 == b.id3);
|
||||||
|
ASSERT_SERIALIZE_SIZE(4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("custom type(nest define)...");
|
||||||
|
test::CustomTypeNest a;
|
||||||
|
a.c2.id1 = 1;
|
||||||
|
a.c2.id2 = 2;
|
||||||
|
a.c2.id3 = 3;
|
||||||
|
test::CustomTypeNest b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a.c2.id1 == b.c2.id1);
|
||||||
|
ASSERT(a.c2.id2 == b.c2.id2);
|
||||||
|
ASSERT(a.c2.id3 == b.c2.id3);
|
||||||
|
ASSERT_SERIALIZE_SIZE(14);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("custom type(inner)...");
|
||||||
|
test::CustomTypeNest2 a;
|
||||||
|
a.c2.id1 = 1;
|
||||||
|
a.c2.id2 = 2;
|
||||||
|
a.c2.id3 = 3;
|
||||||
|
test::CustomTypeNest2 b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a.c2.id1 == b.c2.id1);
|
||||||
|
ASSERT(a.c2.id2 == b.c2.id2);
|
||||||
|
ASSERT(a.c2.id3 == b.c2.id3);
|
||||||
|
ASSERT_SERIALIZE_SIZE(14);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// misc types
|
||||||
|
{
|
||||||
|
RPC_CORE_LOGI("misc types...");
|
||||||
|
CustomType customType;
|
||||||
|
customType.id = 1;
|
||||||
|
customType.ids = {1, 2, 3};
|
||||||
|
customType.name = "test";
|
||||||
|
std::tuple<bool, std::vector<std::tuple<uint32_t>>, std::string, CustomType> a{true, {{1}, {2}}, "test", customType};
|
||||||
|
std::tuple<bool, std::vector<std::tuple<uint32_t>>, std::string, CustomType> b;
|
||||||
|
serialize_test(a, b);
|
||||||
|
ASSERT(a == b);
|
||||||
|
ASSERT_SERIALIZE_SIZE(39);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace rpc_core_test
|
@ -103,6 +103,7 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
3party/mongoose
|
3party/mongoose
|
||||||
3party/nlohmann
|
3party/nlohmann
|
||||||
3party/nonstd
|
3party/nonstd
|
||||||
|
3party/rpc_core/include
|
||||||
3party/rxcpp/Ix/CPP/src
|
3party/rxcpp/Ix/CPP/src
|
||||||
3party/rxcpp/Rx/v2/src
|
3party/rxcpp/Rx/v2/src
|
||||||
3party/sigslot
|
3party/sigslot
|
||||||
|
40
tests/3party/rpc_core/rpc_core_unittest.cpp
Normal file
40
tests/3party/rpc_core/rpc_core_unittest.cpp
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "rpc_core/connection.hpp"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <rpc_core.hpp>
|
||||||
|
#include <ulib/base/types.h>
|
||||||
|
|
||||||
|
struct TestType {
|
||||||
|
int a;
|
||||||
|
std::string b;
|
||||||
|
bool c;
|
||||||
|
std::vector<int> d;
|
||||||
|
std::map<std::string, int> e;
|
||||||
|
std::vector<std::map<std::string, int>> f;
|
||||||
|
RPC_CORE_DEFINE_TYPE_INNER(a, b, c, d, e, f);
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(rpc_core, base)
|
||||||
|
{
|
||||||
|
TestType test_type;
|
||||||
|
auto loopback = std::make_shared<rpc_core::loopback_connection>();
|
||||||
|
auto rpc_s = rpc_core::rpc::create(loopback);
|
||||||
|
rpc_s->set_timer([](uint32_t ms, const rpc_core::rpc::timeout_cb &cb) {
|
||||||
|
// RPC_CORE_UNUSED(ms);
|
||||||
|
// RPC_CORE_UNUSED(cb);
|
||||||
|
});
|
||||||
|
rpc_s->set_ready(true);
|
||||||
|
|
||||||
|
rpc_s->subscribe(
|
||||||
|
"test", [](const std::string &msg) -> std::string { return "ok"; });
|
||||||
|
|
||||||
|
auto rpc_c = rpc_core::rpc::create(loopback);
|
||||||
|
rpc_c->set_timer([](uint32_t ms, const rpc_core::rpc::timeout_cb &cb) {
|
||||||
|
RPC_CORE_UNUSED(ms);
|
||||||
|
RPC_CORE_UNUSED(cb);
|
||||||
|
});
|
||||||
|
rpc_c->set_ready(true);
|
||||||
|
rpc_c->cmd("test")
|
||||||
|
->msg(std::string("hello"))
|
||||||
|
->rsp([](const std::string &rsp) { EXPECT_EQ(rsp, "ok"); })
|
||||||
|
->call();
|
||||||
|
}
|
@ -9,6 +9,7 @@ add_executable(ulib_test
|
|||||||
3party/inja/inja_unittest.cpp
|
3party/inja/inja_unittest.cpp
|
||||||
3party/nonstd/any_unittest.cpp
|
3party/nonstd/any_unittest.cpp
|
||||||
3party/nonstd/optional_unittest.cpp
|
3party/nonstd/optional_unittest.cpp
|
||||||
|
3party/rpc_core/rpc_core_unittest.cpp
|
||||||
3party/sqlpp11/sqlpp11_unittest.cpp
|
3party/sqlpp11/sqlpp11_unittest.cpp
|
||||||
ulib/base/types_unittest.cpp
|
ulib/base/types_unittest.cpp
|
||||||
ulib/concorrency/countdown_latch_unittest.cpp
|
ulib/concorrency/countdown_latch_unittest.cpp
|
||||||
|
Loading…
Reference in New Issue
Block a user