41#include <bitsery/bitsery.h>
42#include <bitsery/adapter/buffer.h>
43#include <bitsery/ext/std_tuple.h>
44#include <bitsery/traits/array.h>
45#include <bitsery/traits/string.h>
46#include <bitsery/traits/vector.h>
51#if defined(RPC_HPP_ENABLE_SERVER_CACHE)
55struct std::hash<std::vector<uint8_t>>
57 [[nodiscard]]
inline size_t operator()(
const std::vector<uint8_t>& vec)
const noexcept
59 static constexpr auto seed_hash = [](
size_t seed,
size_t val)
noexcept
61 static constexpr size_t magic_hash_val = 0x9E3779B9UL;
62 return seed ^ (val + magic_hash_val + (seed << 6) + (seed >> 2));
65 return std::accumulate(vec.begin(), vec.end(), vec.size(), seed_hash);
74 class bitsery_adapter;
79 using serial_t = std::vector<uint8_t>;
80 using bytes_t = std::vector<uint8_t>;
88#if defined(RPC_HPP_BITSERY_EXACT_SZ)
89 static constexpr bool use_exact_size =
true;
91 static constexpr bool use_exact_size =
false;
94 static const uint64_t max_func_name_size;
95 static const uint64_t max_string_size;
96 static const uint64_t max_container_size;
99 [[nodiscard]]
static std::vector<uint8_t> to_bytes(std::vector<uint8_t>&& serial_obj)
101 return std::move(serial_obj);
104 [[nodiscard]]
static std::optional<std::vector<uint8_t>> from_bytes(
105 std::vector<uint8_t>&& bytes)
108 return std::make_optional(std::move(bytes));
111 static std::vector<uint8_t> empty_object()
113 std::vector<uint8_t> buffer(
sizeof(
int) + 2);
114 bitsery::quickSerialization<output_adapter>(buffer, pack_helper<void>{});
118 template<
typename R,
typename... Args>
119 [[nodiscard]]
static std::vector<uint8_t> serialize_pack(
120 const detail::packed_func<R, Args...>& pack)
122 const auto helper = to_helper(pack);
123 std::vector<uint8_t> buffer{};
126 const auto bytes_written = bitsery::quickSerialization<output_adapter>(buffer, helper);
127 buffer.resize(bytes_written);
131 template<
typename R,
typename... Args>
132 [[nodiscard]]
static detail::packed_func<R, Args...> deserialize_pack(
133 const std::vector<uint8_t>& serial_obj)
135 pack_helper<R, Args...> helper{};
137 if (
const auto [error, _] = bitsery::quickDeserialization(
138 input_adapter{ serial_obj.begin(), serial_obj.size() }, helper);
139 error != bitsery::ReaderError::NoError)
143 case bitsery::ReaderError::ReadingError:
144 throw deserialization_error(
145 "Bitsery deserialization failed due to a reading error");
147 case bitsery::ReaderError::DataOverflow:
148 throw function_mismatch(
"Bitsery deserialization failed due to data "
149 "overflow (likely mismatched "
150 "function signature)");
152 case bitsery::ReaderError::InvalidData:
153 throw deserialization_error(
154 "Bitsery deserialization failed due to a invalid data");
156 case bitsery::ReaderError::InvalidPointer:
157 throw deserialization_error(
158 "Bitsery deserialization failed due to an invalid pointer");
160 case bitsery::ReaderError::NoError:
162 throw deserialization_error(
163 "Bitsery deserialization failed due to extra data on the end");
167 return from_helper(helper);
170 [[nodiscard]]
static std::string get_func_name(
const std::vector<uint8_t>& serial_obj)
172 size_t index =
sizeof(int);
173 const auto len = extract_length(serial_obj, index);
175 assert(index < serial_obj.size());
176 assert(index <= std::numeric_limits<ptrdiff_t>::max());
178 return { std::next(serial_obj.begin(), index),
179 std::next(serial_obj.begin(), index + len) };
182 [[nodiscard]]
static rpc_exception extract_exception(
const std::vector<uint8_t>& serial_obj)
184 const auto pack = deserialize_pack<void>(serial_obj);
185 return rpc_exception{ pack.get_err_mesg(), pack.get_except_type() };
188 static void set_exception(std::vector<uint8_t>& serial_obj,
const rpc_exception& ex)
191 const int ex_type =
static_cast<int>(ex.get_type());
192 memcpy(&serial_obj[0], &ex_type,
sizeof(
int));
193 const std::string_view mesg = ex.what();
194 const auto new_err_len =
static_cast<unsigned>(mesg.size());
196 size_t index =
sizeof(int);
197 const auto name_len = extract_length(serial_obj, index);
198 const size_t name_sz_len = index;
202 if (
const auto err_len = extract_length(serial_obj, index); new_err_len != err_len)
206 assert(index < serial_obj.size());
207 assert(index <= std::numeric_limits<ptrdiff_t>::max());
209 serial_obj.erase(std::next(serial_obj.begin(), name_sz_len + name_len),
210 std::next(serial_obj.begin(), index + err_len));
213 index = name_sz_len + name_len;
214 write_length(serial_obj, new_err_len, index);
217 for (
unsigned i = 0; i < new_err_len; ++i)
219 assert(index < serial_obj.size());
220 assert(index <= std::numeric_limits<ptrdiff_t>::max());
223 std::next(serial_obj.begin(), index++),
static_cast<unsigned char>(mesg[i]));
228 using bit_buffer = std::vector<uint8_t>;
229 using output_adapter = bitsery::OutputBufferAdapter<bit_buffer>;
230 using input_adapter = bitsery::InputBufferAdapter<bit_buffer>;
234 int = std::is_arithmetic_v<T> + std::is_integral_v<T> * 2 + std::is_signed_v<T> * 3>
246 using type = uint64_t;
252 static_assert(!std::is_same_v<T, long double>,
253 "long double is not supported for RPC bitsery serialization!");
260 using type = int64_t;
264 using largest_t =
typename largest<T>::type;
266 template<
typename R,
typename... Args>
269 static_assert(!std::is_same_v<R, long double>,
270 "long double is not supported for RPC bitsery serialization!");
272#if defined(RPC_HPP_BITSERY_EXACT_SZ)
273 using args_t = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
276 std::tuple<largest_t<std::remove_cv_t<std::remove_reference_t<Args>>>...>;
279 pack_helper() =
default;
282 std::string func_name{};
283 std::string err_mesg{};
290 s.template value<sizeof(int)>(except_type);
291 s.text1b(func_name, config::max_func_name_size);
292 s.text1b(err_mesg, config::max_string_size);
294 if constexpr (std::is_arithmetic_v<R>)
296 s.template value<sizeof(R)>(result);
298 else if constexpr (rpc_hpp::detail::is_container_v<R>)
300 if constexpr (std::is_arithmetic_v<typename R::value_type>)
302 s.template container<sizeof(typename R::value_type)>(
303 result, config::max_container_size);
307 s.container(result, config::max_container_size);
316 ::bitsery::ext::StdTuple{ [](S& s2, std::string& str)
317 { s2.text1b(str, config::max_string_size); },
319 [](
auto& s2,
auto& val)
321 using T = std::remove_cv_t<std::remove_reference_t<
decltype(val)>>;
323 if constexpr (std::is_arithmetic_v<T>)
325 if constexpr (config::use_exact_size)
327 s2.template value<sizeof(val)>(val);
334 else if constexpr (rpc_hpp::detail::is_container_v<T>)
336 if constexpr (std::is_arithmetic_v<typename T::value_type>)
338 s2.template container<sizeof(typename T::value_type)>(
339 val, config::max_container_size);
343 s2.container(val, config::max_container_size);
354 template<
typename... Args>
355 struct pack_helper<void, Args...>
357#if defined(RPC_HPP_BITSERY_EXACT_SZ)
358 using args_t = std::tuple<std::remove_cv_t<std::remove_reference_t<Args>>...>;
361 std::tuple<largest_t<std::remove_cv_t<std::remove_reference_t<Args>>>...>;
364 pack_helper() =
default;
367 std::string func_name{};
368 std::string err_mesg{};
374 s.template value<sizeof(int)>(except_type);
375 s.text1b(func_name, config::max_func_name_size);
376 s.text1b(err_mesg, config::max_string_size);
379 bitsery::ext::StdTuple{ [](S& s2, std::string& str)
380 { s2.text1b(str, config::max_string_size); },
382 [](
auto& s2,
auto& val)
384 using T = std::remove_cv_t<std::remove_reference_t<
decltype(val)>>;
386 if constexpr (std::is_arithmetic_v<T>)
388 if constexpr (config::use_exact_size)
390 s2.template value<sizeof(val)>(val);
397 else if constexpr (rpc_hpp::detail::is_container_v<T>)
399 if constexpr (std::is_arithmetic_v<typename T::value_type>)
401 s2.template container<sizeof(typename T::value_type)>(
402 val, config::max_container_size);
406 s2.container(val, config::max_container_size);
418 template<
typename R,
typename... Args>
419 [[nodiscard]]
static pack_helper<R, Args...> to_helper(
420 const detail::packed_func<R, Args...>& pack)
422 pack_helper<R, Args...> helper{};
423 helper.func_name = pack.get_func_name();
424 helper.args = pack.get_args();
428 helper.except_type =
static_cast<int>(pack.get_except_type());
429 helper.err_mesg = pack.get_err_mesg();
433 if constexpr (!std::is_void_v<R>)
435 helper.result = pack.get_result();
442 template<
typename R,
typename... Args>
443 [[nodiscard]]
static detail::packed_func<R, Args...> from_helper(
444 pack_helper<R, Args...> helper)
446 if constexpr (std::is_void_v<R>)
448 if (helper.except_type == 0)
450 return detail::packed_func<void, Args...>{ std::move(helper.func_name),
451 std::move(helper.args) };
454 detail::packed_func<void, Args...> pack{ std::move(helper.func_name),
455 std::move(helper.args) };
458 std::move(helper.err_mesg),
static_cast<exception_type
>(helper.except_type));
464 if (helper.err_mesg.empty())
466 return detail::packed_func<R, Args...>{ std::move(helper.func_name),
467 std::move(helper.result), std::move(helper.args) };
470 detail::packed_func<R, Args...> pack{ std::move(helper.func_name), std::nullopt,
471 std::move(helper.args) };
474 std::move(helper.err_mesg),
static_cast<exception_type
>(helper.except_type));
481 static unsigned extract_length(
const bit_buffer& bytes,
size_t& index)
noexcept
483 RPC_HPP_PRECONDITION(index < bytes.size());
485 const uint8_t hb = bytes[index++];
492 assert(index < bytes.size());
493 const uint8_t lb = bytes[index++];
495 if ((hb & 0x40U) != 0U)
497 assert(index < bytes.size());
498 const uint16_t lw = *
reinterpret_cast<const uint16_t*
>(&bytes[index++]);
499 return ((((hb & 0x3FU) << 8) | lb) << 16) | lw;
502 return ((hb & 0x7FU) << 8) | lb;
506 static void write_length(bit_buffer& bytes,
size_t size,
size_t& index)
508 RPC_HPP_PRECONDITION(size < 0x40000000U);
512 assert(index < size);
513 assert(index <= std::numeric_limits<ptrdiff_t>::max());
515 bytes.insert(std::next(bytes.begin(), index++),
static_cast<uint8_t
>(size));
522 std::next(bytes.begin(), index++),
static_cast<uint8_t
>((size >> 8) | 0x80U));
524 bytes.insert(std::next(bytes.begin(), index++),
static_cast<uint8_t
>(size));
529 std::next(bytes.begin(), index++),
static_cast<uint8_t
>((size >> 24) | 0xC0U));
531 bytes.insert(std::next(bytes.begin(), index++),
static_cast<uint8_t
>(size >> 16));
534 std::next(bytes.begin(), index++), *
reinterpret_cast<const uint8_t*
>(&size));
537 std::next(bytes.begin(), index++), *
reinterpret_cast<const uint8_t*
>(&size) + 1);
Definition: rpc_bitsery.hpp:84
Top-level namespace for rpc.hpp classes and functions.
Definition: rpc.hpp:88
Definition: rpc_bitsery.hpp:87