{"id":15048022,"url":"https://github.com/shuai132/rpc_core","last_synced_at":"2025-04-06T01:09:30.178Z","repository":{"id":124277311,"uuid":"265753827","full_name":"shuai132/rpc_core","owner":"shuai132","description":"a tiny rpc library, support c++14 and rust","archived":false,"fork":false,"pushed_at":"2025-03-27T09:50:08.000Z","size":432,"stargazers_count":45,"open_issues_count":3,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-30T00:09:45.961Z","etag":null,"topics":["cpp11","cpp14","mcu","rpc","rpccore","rust","serialization"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/shuai132.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-05-21T04:24:20.000Z","updated_at":"2025-03-27T09:50:11.000Z","dependencies_parsed_at":"2024-01-06T07:30:15.364Z","dependency_job_id":"383b8c28-ae14-41d8-9ca4-cdaf4518a27e","html_url":"https://github.com/shuai132/rpc_core","commit_stats":{"total_commits":262,"total_committers":2,"mean_commits":131.0,"dds":0.007633587786259555,"last_synced_commit":"9ae0d3075f94840fdd783c19a4439c33f2c23b35"},"previous_names":["shuai132/rpc_core"],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuai132%2Frpc_core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuai132%2Frpc_core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuai132%2Frpc_core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/shuai132%2Frpc_core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/shuai132","download_url":"https://codeload.github.com/shuai132/rpc_core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247419860,"owners_count":20936012,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp11","cpp14","mcu","rpc","rpccore","rust","serialization"],"created_at":"2024-09-24T21:07:00.272Z","updated_at":"2025-04-06T01:09:30.160Z","avatar_url":"https://github.com/shuai132.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rpc_core\n\n[![Build Status](https://github.com/shuai132/rpc_core/workflows/cpp/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=cpp)\n[![Build Status](https://github.com/shuai132/rpc_core/workflows/rust/badge.svg)](https://github.com/shuai132/rpc_core/actions?workflow=rust)\n[![Release](https://img.shields.io/github/release/shuai132/rpc_core.svg)](https://github.com/shuai132/rpc_core/releases)\n[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\na tiny C++14 rpc library, supports all platforms (macOS, Linux, Windows, iOS, Android, etc.) and most microchips (\nArduino, STM32, ESP32/ESP8266, etc.)\n\n**Recommend TCP-based implementation: [asio_net](https://github.com/shuai132/asio_net)**\n\n## Introduction\n\nFull-feature rpc frameworks (e.g. `gRPC` and `bRPC`) are very complex and not suitable for use on embedded platforms.\n\nThis project offers a lightweight and user-friend rpc library that is better suited for one-to-one rpc calls.\nIt supports all platforms and a wide range of microchips, including Arduino, STM32, ESP32/ESP8266, and more.\n\nNote:\nThis library only offers the protocol layer and API, it **does not** include the implementation of the transport layer.\nFor TCP-based implementation: [asio_net](https://github.com/shuai132/asio_net)\n\n## Features\n\n* Header-Only\n* No-Schema\n* Support performance-limited platforms including microchips\n* Support any connection type (`tcp socket`, `serial port`, etc.)\n* High Performance Serialization, support most STL containers and user type\n* Serialization plugins implementations for `flatbuffers` and `nlohmann::json`\n* Support `co_await`, depend on `C++20` and `asio`, or custom implementation\n* Support subscribe async callback, async coroutine, and custom scheduler\n* RAII-based `dispose` for automatic cancel request\n* Support timeout, retry, cancel api\n* Comprehensive unittests\n\n## TCP-based implementations\n\n* C++\n    - [asio_net](https://github.com/shuai132/asio_net): based on [asio](https://think-async.com/Asio/#)  \n      Support macOS, Linux, Windows, iOS, Android, etc. and can be used on MCUs that support asio, such as ESP32.\n\n* Rust\n    - [./rust](./rust): based on [tokio](https://github.com/tokio-rs/tokio)  \n      Support callback and async/await, details: [README.md](./rust/README.md)\n\n## Requirements\n\n* C++14\n* Provide your connection implementation: [connection](include/rpc_core/connection.hpp)  \n  NOTICE: complete data packets are required for data transmission, such as `websocket`.  \n  If using `tcp socket`, `serial port`, etc., message pack and unpack need to be implemented.\n  Or you can use [stream_connection](include/rpc_core/connection.hpp).\n* Optional: C++20 (for coroutine api, co_await co_call)\n\n## Usage\n\n* basic usage:  \n  notice: both sender and receiver can use `subscribe` and `call` apis\n\n```c++\n// receiver\nrpc-\u003esubscribe(\"cmd\", [](const std::string\u0026 msg) -\u003e std::string {\n    assert(msg == \"hello\");\n    return \"world\";\n});\n\n// sender\nrpc-\u003ecmd(\"cmd\")\n    -\u003emsg(std::string(\"hello\"))\n    -\u003ersp([](const std::string\u0026 rsp) {\n      assert(rsp == \"world\");\n    })\n    -\u003ecall();\n// or: rpc-\u003ecall(\"cmd\", std::string(\"hello\"), [](const std::string\u0026 rsp) {});\n```\n\n* async response:  \n  just use `request_response\u003c\u003e` type, with `scheduler` support\n\n```c++\nrpc-\u003esubscribe(\"cmd\", [\u0026](request_response\u003cstd::string, std::string\u003e rr) {\n    assert(rr-\u003ereq == \"hello\");\n    rr-\u003ersp(\"world\"); // call rr-\u003ersp() when data is ready\n}, scheduler);\n```\n\n* async call and response using c++20 coroutine:  \n  here is an example using asio, custom async/coroutine implementation is supported\n\n```c++\n// receiver\nrpc-\u003esubscribe(\"cmd\", [\u0026](request_response\u003cstd::string, std::string\u003e rr) -\u003e asio::awaitable\u003cvoid\u003e {\n    assert(rr-\u003ereq == \"hello\");\n    asio::steady_timer timer(context);\n    timer.expires_after(std::chrono::seconds(1));\n    co_await timer.async_wait();\n    rr-\u003ersp(\"world\");\n}, scheduler_asio_coroutine);\n\n// sender\n// use C++20 co_await with asio, or you can use custom async implementation, and co_await it!\nauto rsp = co_await rpc-\u003ecmd(\"cmd\")-\u003emsg(std::string(\"hello\"))-\u003eco_call\u003cstd::string\u003e();\n// or: auto rsp = co_await rpc-\u003eco_call\u003cstd::string\u003e(\"cmd\", std::string(\"hello\"));\nassert(rsp.data == \"world\");\n```\n\nInspect the code for more\ndetails: [rpc_s_coroutine.cpp](https://github.com/shuai132/asio_net/blob/main/test/rpc_s_coroutine.cpp)\nand [rpc_c_coroutine.cpp](https://github.com/shuai132/asio_net/blob/main/test/rpc_c_coroutine.cpp)\n\n* Addition:\n\n1. `msg` and `rsp` support any serializable type, refer to [Serialization](#Serialization).\n2. Detailed usages and unittests can be found here: [rpc_test.cpp](test/test_rpc.cpp)\n3. There is an example shows custom async\n   impl: [rpc_c_coroutine.hpp](https://github.com/shuai132/asio_net/blob/main/test/rpc_c_coroutine.hpp)\n\n## Serialization\n\nHigh-performance and memory-saving binary serialization.\n\n* api is very simple to use: [include/rpc_core/serialize_api.hpp](include/rpc_core/serialize_api.hpp)\n* usage and comprehensive unittest: [test/test_serialize.cpp](test/test_serialize.cpp)\n* the design balance cpu and memory usage, and zero-copy if possible.\n* std::string is used as inner data container, it's serialize/deserialize is zero-overhead. so, it is recommended to use\n  std::string whenever possible, using it to store binary data is also a good choice.\n\n### Why design a new serialization\n\nFist of all, I want to keep `rpc_core` library standalone, without any dependencies, except for STL.\n\nMoreover, these serialization libraries do not align with my design goals:\n\n* protobuf library is too large for some platforms, and it's Varint, Zigzag, and GZIP will use a lot of cpu.\n* msgpack has similarity reason to protobuf.\n* flatbuffers serialized data is too large.\n\nOf course, when communicating across languages, it is recommended to use the above serialization libraries!\n\nFinally, it also provides a way to use thirdparty serialization libraries directly, refer\nto [Serialization Plugins](#Serialization-Plugins).\n\n### Usage\n\nFor example, user data:\n\n```c++\nstruct Type {\n  uint8_t id = 1;\n  uint8_t age = 18;\n  std::string name = \"test\";\n};\n```\n\njson: `{\"id\":1,\"age\":18,\"name\":\"test\"}`\n\n| library     | bytes |\n|-------------|:-----:|\n| json        |  31   |\n| flatbuffers |  44   |\n| protobuf    |  10   |\n| msgpack     |  20   |\n| rpc_core    |   8   |\n\n- [x] [std::string](https://en.cppreference.com/w/cpp/string/basic_string)\n- [x] [std::wstring](https://en.cppreference.com/w/cpp/string/basic_string)\n- [x] [std::array](https://en.cppreference.com/w/cpp/container/array)\n- [x] [std::vector](https://en.cppreference.com/w/cpp/container/vector)\n- [x] [std::list](https://en.cppreference.com/w/cpp/container/list)\n- [x] [std::forward_list](https://en.cppreference.com/w/cpp/container/forward_list)\n- [x] [std::deque](https://en.cppreference.com/w/cpp/container/deque)\n- [x] [std::pair](https://en.cppreference.com/w/cpp/utility/pair)\n- [x] [std::tuple](https://en.cppreference.com/w/cpp/utility/tuple)\n- [x] [std::map](https://en.cppreference.com/w/cpp/container/map)\n- [x] [std::unordered_map](https://en.cppreference.com/w/cpp/container/unordered_map)\n- [x] [std::multimap](https://en.cppreference.com/w/cpp/container/multimap)\n- [x] [std::unordered_multimap](https://en.cppreference.com/w/cpp/container/unordered_multimap)\n- [x] [std::set](https://en.cppreference.com/w/cpp/container/set)\n- [x] [std::unordered_set](https://en.cppreference.com/w/cpp/container/unordered_set)\n- [x] [std::multiset](https://en.cppreference.com/w/cpp/container/multiset)\n- [x] [std::unordered_multiset](https://en.cppreference.com/w/cpp/container/unordered_multiset)\n- [x] [std::stack](https://en.cppreference.com/w/cpp/container/stack)\n- [x] [std::queue](https://en.cppreference.com/w/cpp/container/queue)\n- [x] [std::priority_queue](https://en.cppreference.com/w/cpp/container/priority_queue)\n- [x] [std::bitset](https://en.cppreference.com/w/cpp/utility/bitset)\n- [x] [std::complex](https://en.cppreference.com/w/cpp/numeric/complex)\n- [x] [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration)\n- [x] [std::chrono::time_point](https://en.cppreference.com/w/cpp/chrono/time_point)\n- [x] [std::unique_ptr](https://en.cppreference.com/w/cpp/memory/unique_ptr)\n- [x] [std::shared_ptr](https://en.cppreference.com/w/cpp/memory/shared_ptr)\n- [x] [rpc_core::binary_wrap](include/rpc_core/serialize/binary_wrap.hpp)\n- [x] [custom struct/class](test/serialize/CustomType.h)\n  ```c++\n  #include \"rpc_core/serialize.hpp\"\n  struct TestStruct {\n    uint8_t a;\n    std::string b;\n    OtherType c\n    // RPC_CORE_DEFINE_TYPE_INNER(a, b, c);\n  };\n  RPC_CORE_DEFINE_TYPE(TestStruct, a, b, c);\n  ```\n  choose `RPC_CORE_DEFINE_TYPE` or `RPC_CORE_DEFINE_TYPE_INNER` for private member variable.\n\n## Serialization Plugins\n\n* [flatbuffers.hpp](include/rpc_core/plugin/flatbuffers.hpp)  \n  Supports using types generated by `flatbuffers` directly as message  \n  (add the option `--gen-object-api` when using `flatc`)\n\n\n* [json_msg.hpp](include/rpc_core/plugin/json_msg.hpp)  \n  Supports using types supported by [nlohmann/json](https://github.com/nlohmann/json) directly as message  \n  (the `to_json/from_json` rules in `nlohmann/json` need to be satisfied, and use `DEFINE_JSON_CLASS`).\n\n\n* [json.hpp](include/rpc_core/plugin/json.hpp)  \n  A flexible way to use `nlohmann/json`\n\n# License\n\nThis project is licensed under the [MIT license](LICENSE).\n\n# Links\n\n* Implementation based on asio: [asio_net](https://github.com/shuai132/asio_net)\n\n\n* Implementation suitable for ESP8266: [esp_rpc](https://github.com/shuai132/esp_rpc)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuai132%2Frpc_core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshuai132%2Frpc_core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshuai132%2Frpc_core/lists"}