41#include <rapidjson/document.h>
42#include <rapidjson/stringbuffer.h>
43#include <rapidjson/writer.h>
49 class rapidjson_adapter;
54 using serial_t = rapidjson::Document;
55 using bytes_t = std::string;
61 [[nodiscard]]
static std::string to_bytes(rapidjson::Document&& serial_obj)
63 rapidjson::StringBuffer buffer{};
64 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
65 std::move(serial_obj).Accept(writer);
66 return buffer.GetString();
69 [[nodiscard]]
static std::optional<rapidjson::Document> from_bytes(std::string&& bytes)
71 rapidjson::Document d{};
73 d.Parse(std::move(bytes).c_str());
75 if (d.HasParseError())
80 if (
const auto ex_it = d.FindMember(
"except_type"); ex_it != d.MemberEnd())
82 if (
const auto& ex_val = ex_it->value;
83 !ex_val.IsInt() || (ex_val.GetInt() != 0 && !d.HasMember(
"err_mesg")))
89 return std::make_optional(std::move(d));
92 if (
const auto fname_it = d.FindMember(
"func_name"); fname_it == d.MemberEnd()
93 || !fname_it->value.IsString() || fname_it->value.GetStringLength() == 0)
98 if (
const auto args_it = d.FindMember(
"args");
99 args_it == d.MemberEnd() || !args_it->value.IsArray())
104 return std::make_optional(std::move(d));
107 static rapidjson::Document empty_object()
109 rapidjson::Document d{};
114 template<
typename R,
typename... Args>
115 [[nodiscard]]
static rapidjson::Document serialize_pack(
116 const detail::packed_func<R, Args...>& pack)
118 rapidjson::Document d{};
119 auto& alloc = d.GetAllocator();
121 d.AddMember(
"func_name",
122 rapidjson::Value{}.SetString(pack.get_func_name().c_str(), alloc), alloc);
124 if constexpr (!std::is_void_v<R>)
126 rapidjson::Value result{};
130 if constexpr (std::is_arithmetic_v<R>)
132 result.Set<R>(pack.get_result());
134 else if constexpr (std::is_same_v<R, std::string>)
136 result.SetString(pack.get_result().c_str(), alloc);
138 else if constexpr (rpc_hpp::detail::is_container_v<R>)
140 const auto& container = pack.get_result();
142 result.Reserve(
static_cast<rapidjson::SizeType
>(container.size()), alloc);
144 for (
const auto& val : container)
146 result.PushBack(val, alloc);
149 else if constexpr (rpc_hpp::detail::is_serializable_v<rapidjson_adapter, R>)
151 const rapidjson::Document tmp =
152 R::template serialize<rapidjson_adapter>(pack.get_result());
154 result.CopyFrom(tmp, alloc);
158 result = serialize<R>(pack.get_result(), alloc);
162 d.AddMember(
"result", result, alloc);
165 rapidjson::Value args{};
167 args.Reserve(
static_cast<rapidjson::SizeType
>(
sizeof...(Args)), alloc);
168 detail::for_each_tuple(pack.get_args(),
169 [&args, &alloc](
auto&& elem)
170 { push_args(std::forward<decltype(elem)>(elem), args, alloc); });
172 d.AddMember(
"args", std::move(args), alloc);
176 template<
typename R,
typename... Args>
177 [[nodiscard]]
static detail::packed_func<R, Args...> deserialize_pack(
178 const rapidjson::Document& serial_obj)
180 const auto& args_val = serial_obj[
"args"];
181 [[maybe_unused]]
unsigned arg_counter = 0;
182 typename detail::packed_func<R, Args...>::args_t args{ parse_args<Args>(
183 args_val, arg_counter)... };
185 if constexpr (std::is_void_v<R>)
187 detail::packed_func<void, Args...> pack(
188 serial_obj[
"func_name"].GetString(), std::move(args));
190 if (serial_obj.HasMember(
"except_type"))
192 pack.set_exception(serial_obj[
"err_mesg"].GetString(),
193 static_cast<exception_type
>(serial_obj[
"except_type"].GetInt()));
200 if (serial_obj.HasMember(
"result") && !serial_obj[
"result"].IsNull())
202 const rapidjson::Value& result = serial_obj[
"result"];
203 return detail::packed_func<R, Args...>(
204 serial_obj[
"func_name"].GetString(), parse_arg<R>(result), std::move(args));
207 detail::packed_func<R, Args...> pack(
208 serial_obj[
"func_name"].GetString(), std::nullopt, std::move(args));
210 if (serial_obj.HasMember(
"except_type"))
212 pack.set_exception(serial_obj[
"err_mesg"].GetString(),
213 static_cast<exception_type
>(serial_obj[
"except_type"].GetInt()));
220 [[nodiscard]]
static std::string get_func_name(
const rapidjson::Document& serial_obj)
222 return serial_obj[
"func_name"].GetString();
225 [[nodiscard]]
static rpc_exception extract_exception(
const rapidjson::Document& serial_obj)
228 static_cast<exception_type
>(serial_obj[
"except_type"].GetInt()) };
231 static void set_exception(rapidjson::Document& serial_obj,
const rpc_exception& ex)
233 auto& alloc = serial_obj.GetAllocator();
235 if (
const auto ex_it = serial_obj.FindMember(
"except_type");
236 ex_it != serial_obj.MemberEnd())
238 ex_it->value.SetInt(
static_cast<int>(ex.get_type()));
239 serial_obj[
"err_mesg"].SetString(ex.what(), alloc);
243 serial_obj.AddMember(
"except_type",
static_cast<int>(ex.get_type()), alloc);
244 serial_obj.AddMember(
245 "err_mesg", rapidjson::Value{}.SetString(ex.what(), alloc), alloc);
250 static rapidjson::Value serialize(
251 const T& val, rapidjson::MemoryPoolAllocator<>& alloc) =
delete;
254 static T deserialize(
const rapidjson::Value& serial_obj) =
delete;
259 [[nodiscard]]
static constexpr bool validate_arg(
const rapidjson::Value& arg)
noexcept
261 if constexpr (std::is_same_v<T, bool>)
265 else if constexpr (std::is_integral_v<T>)
267 if constexpr (std::is_signed_v<T>)
269 if constexpr (
sizeof(T) < 8)
275 return arg.IsInt64();
280 if constexpr (
sizeof(T) < 8)
286 return arg.IsUint64();
290 else if constexpr (std::is_same_v<T, float>)
292 return arg.IsFloat();
294 else if constexpr (std::is_same_v<T, double>)
296 return arg.IsDouble();
298 else if constexpr (std::is_same_v<T, std::string>)
300 return arg.IsString();
302 else if constexpr (rpc_hpp::detail::is_container_v<T>)
304 return arg.IsArray();
308 return !arg.IsNull();
313 [[nodiscard]]
static std::string mismatch_message(
314 std::string&& expect_type,
const rapidjson::Value& obj)
316 const auto get_type_str = [&obj]()
noexcept
376 return {
"rapidjson expected type: " + std::move(expect_type)
377 +
", got type: " + get_type_str() };
381 static void push_arg(
382 T&& arg, rapidjson::Value& obj, rapidjson::MemoryPoolAllocator<>& alloc)
384 using no_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
386 if constexpr (std::is_same_v<no_ref_t, std::string>)
388 obj.SetString(arg.c_str(), alloc);
390 else if constexpr (std::is_arithmetic_v<no_ref_t>)
394 std::is_same_v<no_ref_t,
395 char> || std::is_same_v<no_ref_t, int8_t> || std::is_same_v<no_ref_t, int16_t>)
399 else if constexpr (std::is_same_v<no_ref_t,
400 uint8_t> || std::is_same_v<no_ref_t, uint16_t>)
406 obj.Set<no_ref_t>(arg);
409 else if constexpr (rpc_hpp::detail::is_container_v<no_ref_t>)
412 obj.Reserve(
static_cast<rapidjson::SizeType
>(arg.size()), alloc);
414 for (
auto&& val : arg)
416 push_args(std::forward<
decltype(val)>(val), obj, alloc);
419 else if constexpr (rpc_hpp::detail::is_serializable_v<rapidjson_adapter, no_ref_t>)
421 const rapidjson::Document serialized =
422 no_ref_t::template serialize<rapidjson_adapter>(std::forward<T>(arg));
424 obj.CopyFrom(serialized, alloc);
428 obj = serialize<no_ref_t>(std::forward<T>(arg), alloc);
433 static void push_args(
434 T&& arg, rapidjson::Value& obj_arr, rapidjson::MemoryPoolAllocator<>& alloc)
436 rapidjson::Value tmp{};
437 push_arg(std::forward<T>(arg), tmp, alloc);
438 obj_arr.PushBack(std::move(tmp), alloc);
443 [[nodiscard]]
static std::remove_cv_t<std::remove_reference_t<T>> parse_arg(
444 const rapidjson::Value& arg)
446 using no_ref_t = std::remove_cv_t<std::remove_reference_t<T>>;
448 if (!validate_arg<no_ref_t>(arg))
453 if constexpr (std::is_same_v<no_ref_t, std::string>)
455 return arg.GetString();
457 else if constexpr (std::is_arithmetic_v<no_ref_t>)
461 std::is_same_v<no_ref_t,
462 char> || std::is_same_v<no_ref_t, int8_t> || std::is_same_v<no_ref_t, int16_t>)
464 return static_cast<no_ref_t
>(arg.GetInt());
466 else if constexpr (std::is_same_v<no_ref_t,
467 uint8_t> || std::is_same_v<no_ref_t, uint16_t>)
469 return static_cast<no_ref_t
>(arg.GetUint());
473 return arg.Get<no_ref_t>();
476 else if constexpr (rpc_hpp::detail::is_container_v<no_ref_t>)
478 using subvalue_t =
typename no_ref_t::value_type;
480 no_ref_t container{};
481 container.reserve(arg.Size());
482 unsigned arg_counter = 0;
484 for (
const auto& val : arg.GetArray())
486 container.push_back(parse_args<subvalue_t>(val, arg_counter));
491 else if constexpr (rpc_hpp::detail::is_serializable_v<rapidjson_adapter, no_ref_t>)
493 rapidjson::Document d{};
494 d.CopyFrom(arg, d.GetAllocator());
495 return no_ref_t::template deserialize<rapidjson_adapter>(d);
499 return deserialize<no_ref_t>(arg);
505 [[nodiscard]]
static std::remove_cv_t<std::remove_reference_t<T>> parse_args(
506 const rapidjson::Value& arg_arr,
unsigned& index)
508 if (!arg_arr.IsArray())
510 return parse_arg<T>(arg_arr);
513 const auto& arr = arg_arr.GetArray();
515 if (index >= arr.Size())
520 return parse_arg<T>(arr[index++]);
Definition: rpc_rapidjson.hpp:59
Top-level namespace for rpc.hpp classes and functions.
Definition: rpc.hpp:88