41#include <nlohmann/json.hpp> 
   52        using serial_t = nlohmann::json;
 
   53        using bytes_t = std::string;
 
   59        [[nodiscard]] 
static std::string to_bytes(nlohmann::json&& serial_obj)
 
   61            return std::move(serial_obj).dump();
 
   64        [[nodiscard]] 
static std::optional<nlohmann::json> from_bytes(std::string&& bytes)
 
   70                obj = nlohmann::json::parse(std::move(bytes));
 
   72            catch (
const nlohmann::json::parse_error&)
 
   82            if (obj.contains(
"except_type"))
 
   84                if (obj[
"except_type"] != 0 && !obj.contains(
"err_mesg"))
 
   90                return std::make_optional(std::move(obj));
 
   93            if (
const auto fname_it = obj.find(
"func_name");
 
   94                fname_it == obj.end() || !fname_it->is_string() || fname_it->empty())
 
   99            if (
const auto args_it = obj.find(
"args"); args_it == obj.end() || !args_it->is_array())
 
  104            return std::make_optional(std::move(obj));
 
  107        static nlohmann::json empty_object() { 
return nlohmann::json::object(); }
 
  109        template<
typename R, 
typename... Args>
 
  110        [[nodiscard]] 
static nlohmann::json serialize_pack(
 
  111            const detail::packed_func<R, Args...>& pack)
 
  113            nlohmann::json obj{};
 
  114            obj[
"func_name"] = pack.get_func_name();
 
  115            obj[
"args"] = nlohmann::json::array();
 
  116            auto& arg_arr = obj[
"args"];
 
  117            arg_arr.get_ref<nlohmann::json::array_t&>().reserve(
sizeof...(Args));
 
  119            detail::for_each_tuple(pack.get_args(),
 
  120                [&arg_arr](
auto&& elem)
 
  121                { push_args(std::forward<decltype(elem)>(elem), arg_arr); });
 
  125                obj[
"except_type"] = pack.get_except_type();
 
  126                obj[
"err_mesg"] = pack.get_err_mesg();
 
  130            if constexpr (!std::is_void_v<R>)
 
  133                push_arg(pack.get_result(), obj[
"result"]);
 
  139        template<
typename R, 
typename... Args>
 
  140        [[nodiscard]] 
static detail::packed_func<R, Args...> deserialize_pack(
 
  141            const nlohmann::json& serial_obj)
 
  143            const auto& args_val = serial_obj[
"args"];
 
  144            [[maybe_unused]] 
unsigned arg_counter = 0;
 
  145            typename detail::packed_func<R, Args...>::args_t args{ parse_args<Args>(
 
  146                args_val, arg_counter)... };
 
  148            if constexpr (std::is_void_v<R>)
 
  150                detail::packed_func<void, Args...> pack(serial_obj[
"func_name"], std::move(args));
 
  152                if (serial_obj.contains(
"except_type"))
 
  154                    pack.set_exception(serial_obj[
"err_mesg"],
 
  155                        static_cast<exception_type
>(serial_obj[
"except_type"]));
 
  162                if (serial_obj.contains(
"result") && !serial_obj[
"result"].is_null())
 
  164                    return detail::packed_func<R, Args...>(serial_obj[
"func_name"],
 
  165                        parse_arg<R>(serial_obj[
"result"]), std::move(args));
 
  168                detail::packed_func<R, Args...> pack(
 
  169                    serial_obj[
"func_name"], std::nullopt, std::move(args));
 
  171                if (serial_obj.contains(
"except_type"))
 
  173                    pack.set_exception(serial_obj[
"err_mesg"],
 
  174                        static_cast<exception_type
>(serial_obj[
"except_type"]));
 
  181        [[nodiscard]] 
static std::string get_func_name(
const nlohmann::json& serial_obj)
 
  183            return serial_obj[
"func_name"];
 
  186        [[nodiscard]] 
static rpc_exception extract_exception(
const nlohmann::json& serial_obj)
 
  188            return rpc_exception{ serial_obj.at(
"err_mesg").get<std::string>(),
 
  189                static_cast<exception_type
>(serial_obj.at(
"except_type").get<
int>()) };
 
  192        static void set_exception(nlohmann::json& serial_obj, 
const rpc_exception& ex)
 
  194            serial_obj[
"except_type"] = ex.get_type();
 
  195            serial_obj[
"err_mesg"] = ex.what();
 
  199        static nlohmann::json serialize(
const T& val) = 
delete;
 
  202        static T deserialize(
const nlohmann::json& serial_obj) = 
delete;
 
  207        [[nodiscard]] 
static constexpr bool validate_arg(
const nlohmann::json& arg) 
noexcept 
  209            if constexpr (std::is_same_v<T, bool>)
 
  211                return arg.is_boolean();
 
  213            else if constexpr (std::is_integral_v<T>)
 
  215                return arg.is_number() && !arg.is_number_float();
 
  217            else if constexpr (std::is_floating_point_v<T>)
 
  219                return arg.is_number_float();
 
  221            else if constexpr (std::is_same_v<T, std::string>)
 
  223                return arg.is_string();
 
  225            else if constexpr (detail::is_container_v<T>)
 
  227                return arg.is_array();
 
  231                return !arg.is_null();
 
  236        [[nodiscard]] 
static std::string mismatch_string(
 
  237            std::string&& expect_type, 
const nlohmann::json& arg)
 
  239            return { 
"njson expected type: " + std::move(expect_type)
 
  240                + 
", got type: " + arg.type_name() };
 
  244        static void push_arg(T&& arg, nlohmann::json& obj)
 
  246            using no_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
 
  248            if constexpr (std::is_arithmetic_v<no_ref_t> || std::is_same_v<no_ref_t, std::string>)
 
  250                obj = std::forward<T>(arg);
 
  252            else if constexpr (detail::is_container_v<no_ref_t>)
 
  254                obj = nlohmann::json::array();
 
  255                obj.get_ref<nlohmann::json::array_t&>().reserve(arg.size());
 
  257                for (
auto&& val : arg)
 
  259                    push_args(std::forward<
decltype(val)>(val), obj);
 
  262            else if constexpr (detail::is_serializable_v<njson_adapter, no_ref_t>)
 
  264                obj = no_ref_t::template serialize<njson_adapter>(std::forward<T>(arg));
 
  268                obj = serialize<no_ref_t>(std::forward<T>(arg));
 
  273        static void push_args(T&& arg, nlohmann::json& obj_arr)
 
  275            nlohmann::json tmp{};
 
  276            push_arg(std::forward<T>(arg), tmp);
 
  277            obj_arr.push_back(std::move(tmp));
 
  282        [[nodiscard]] 
static std::remove_cv_t<std::remove_reference_t<T>> parse_arg(
 
  283            const nlohmann::json& arg)
 
  285            using no_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
 
  287            if (!validate_arg<T>(arg))
 
  292            if constexpr (std::is_arithmetic_v<no_ref_t> || std::is_same_v<no_ref_t, std::string>)
 
  294                return arg.get<no_ref_t>();
 
  296            else if constexpr (detail::is_container_v<no_ref_t>)
 
  298                using value_t = 
typename no_ref_t::value_type;
 
  300                no_ref_t container{};
 
  301                container.reserve(arg.size());
 
  302                unsigned arg_counter = 0;
 
  304                for (
const auto& val : arg)
 
  306                    container.push_back(parse_args<value_t>(val, arg_counter));
 
  311            else if constexpr (detail::is_serializable_v<njson_adapter, no_ref_t>)
 
  313                return no_ref_t::template deserialize<njson_adapter>(arg);
 
  317                return deserialize<no_ref_t>(arg);
 
  323        [[nodiscard]] 
static std::remove_cv_t<std::remove_reference_t<T>> parse_args(
 
  324            const nlohmann::json& arg_arr, 
unsigned& index)
 
  326            if (index >= arg_arr.size())
 
  331            const auto& arg = arg_arr.is_array() ? arg_arr[index++] : arg_arr;
 
  332            return parse_arg<T>(arg);
 
Definition: rpc_njson.hpp:57
 
Top-level namespace for rpc.hpp classes and functions.
Definition: rpc.hpp:88