Add msgpack packer support for ranges of objects.
This commit is contained in:
parent
cb2b5b47b0
commit
3d7ba40289
@ -38,6 +38,10 @@ constexpr auto pack_integral(T value, Itr out, std::size_t sz) noexcept {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dummy_packer {
|
||||||
|
std::byte* out;
|
||||||
|
};
|
||||||
|
|
||||||
// Defines a range of bytes for binary formats.
|
// Defines a range of bytes for binary formats.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
concept byte_range = std::ranges::contiguous_range<T>
|
concept byte_range = std::ranges::contiguous_range<T>
|
||||||
@ -66,25 +70,23 @@ struct builtin_packer;
|
|||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct builtin_packer<invalid> : builtin_packer_base {
|
struct builtin_packer<invalid> : builtin_packer_base {
|
||||||
static constexpr auto pack(auto, auto out) noexcept -> decltype(out) {
|
static constexpr void pack(auto, auto& packer) noexcept {
|
||||||
*out++ = format::invalid::marker;
|
*(packer.out)++ = format::invalid::marker;
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct builtin_packer<nil> : builtin_packer_base {
|
struct builtin_packer<nil> : builtin_packer_base {
|
||||||
static constexpr auto pack(auto, auto out) noexcept -> decltype(out) {
|
static constexpr void pack(auto, auto& packer) noexcept {
|
||||||
*out++ = format::nil::marker;
|
*(packer.out)++ = format::nil::marker;
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct builtin_packer<bool> : builtin_packer_base {
|
struct builtin_packer<bool> : builtin_packer_base {
|
||||||
static constexpr auto pack(bool value, auto out) noexcept -> decltype(out) {
|
static constexpr void pack(bool value, auto& packer) noexcept {
|
||||||
*out++ = format::boolean::marker | static_cast<std::byte>(value);
|
*(packer.out)++ =
|
||||||
return out;
|
format::boolean::marker | static_cast<std::byte>(value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,10 +111,9 @@ struct builtin_packer<T> : builtin_packer_base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto pack(
|
static constexpr void pack(T const& value, auto& packer) noexcept {
|
||||||
T const& value, auto out) noexcept -> decltype(out) {
|
*(packer.out)++ = marker(value);
|
||||||
*out++ = marker(value);
|
packer.out = detail::pack_integral(value, packer.out, rep_size(value));
|
||||||
return detail::pack_integral(value, out, rep_size(value));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,10 +145,9 @@ struct builtin_packer<T> : builtin_packer_base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto pack(
|
static constexpr void pack(T const& value, auto& packer) noexcept {
|
||||||
T const& value, auto out) noexcept -> decltype(out) {
|
*(packer.out)++ = marker(value);
|
||||||
*out++ = marker(value);
|
packer.out = detail::pack_integral(value, packer.out, rep_size(value));
|
||||||
return detail::pack_integral(value, out, rep_size(value));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -175,12 +175,11 @@ struct builtin_packer<T> : builtin_packer_base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto pack(
|
static constexpr void pack(T const& value, auto& packer) noexcept {
|
||||||
T const& value, auto out) noexcept -> decltype(out) {
|
*(packer.out)++ = marker(value);
|
||||||
*out++ = marker(value);
|
packer.out = detail::pack_integral(
|
||||||
out = detail::pack_integral(
|
std::ranges::size(value), packer.out, len_size(value));
|
||||||
std::ranges::size(value), out, len_size(value));
|
packer.out = std::ranges::copy(value, packer.out).out;
|
||||||
return std::ranges::copy(value, out).out;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -211,13 +210,12 @@ struct builtin_packer<std::string_view> : builtin_packer_base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto pack(
|
static constexpr void pack(std::string_view value, auto& packer) noexcept {
|
||||||
std::string_view value, auto out) noexcept -> decltype(out) {
|
*(packer.out)++ = marker(value);
|
||||||
*out++ = marker(value);
|
|
||||||
auto const size = std::size(value);
|
auto const size = std::size(value);
|
||||||
out = detail::pack_integral(size, out, len_size(value));
|
packer.out = detail::pack_integral(size, packer.out, len_size(value));
|
||||||
auto const* beg = reinterpret_cast<std::byte const*>(&*value.begin());
|
auto const* beg = reinterpret_cast<std::byte const*>(&*value.begin());
|
||||||
return std::ranges::copy(beg, beg + size, out).out;
|
packer.out = std::ranges::copy(beg, beg + size, packer.out).out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -249,9 +247,10 @@ struct builtin_packer<array_desc> : builtin_packer_base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto pack(array_desc value, auto out) noexcept {
|
static constexpr auto pack(array_desc value, auto& packer) noexcept {
|
||||||
*out++ = marker(value);
|
*(packer.out)++ = marker(value);
|
||||||
return detail::pack_integral(value.count, out, rep_size(value));
|
packer.out =
|
||||||
|
detail::pack_integral(value.count, packer.out, rep_size(value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -278,21 +277,22 @@ struct builtin_packer<map_desc> : builtin_packer_base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr auto pack(map_desc value, auto out) noexcept {
|
static constexpr void pack(map_desc value, auto& packer) noexcept {
|
||||||
*out++ = marker(value);
|
*(packer.out)++ = marker(value);
|
||||||
return detail::pack_integral(value.count, out, rep_size(value));
|
packer.out =
|
||||||
|
detail::pack_integral(value.count, packer.out, rep_size(value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* template <> */
|
|
||||||
/* struct builtin_packer<map_desc> */
|
|
||||||
/* : builtin_packer_base<format::type::map> {}; */
|
|
||||||
|
|
||||||
// Requirements for builtin_packable types.
|
// Requirements for builtin_packable types.
|
||||||
template <typename T>
|
template <typename T, typename Packer = detail::dummy_packer>
|
||||||
concept builtin_packable = requires(T const& value, std::byte* dest) {
|
concept builtin_packable = requires(T&& value, Packer& dest) {
|
||||||
{ builtin_packer<T>::total_size(value) } -> std::same_as<std::size_t>;
|
{
|
||||||
{ builtin_packer<T>::pack(value, dest) } -> std::same_as<decltype(dest)>;
|
builtin_packer<std::remove_cvref_t<T>>::total_size(value)
|
||||||
|
} -> std::same_as<std::size_t>;
|
||||||
|
{
|
||||||
|
builtin_packer<std::remove_cvref_t<T>>::pack(value, dest)
|
||||||
|
} -> std::same_as<void>;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msgpack
|
} // namespace msgpack
|
||||||
|
|||||||
@ -31,11 +31,23 @@ template <typename T>
|
|||||||
concept packable_range = std::ranges::input_range<T>
|
concept packable_range = std::ranges::input_range<T>
|
||||||
&& builtin_packable<std::ranges::range_value_t<T>>;
|
&& builtin_packable<std::ranges::range_value_t<T>>;
|
||||||
|
|
||||||
static_assert(packable_range<std::array<std::string_view, 5>>);
|
|
||||||
static_assert(packable_range<std::span<std::string_view>>);
|
|
||||||
|
|
||||||
template <packable_range T>
|
template <packable_range T>
|
||||||
struct builtin_packer<T> {
|
struct builtin_packer<T> : builtin_packer_base {
|
||||||
|
static constexpr std::size_t rep_size(T const& value) {
|
||||||
|
return std::ranges::size(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr auto marker(T const& value) {
|
||||||
|
array_desc desc(rep_size(value));
|
||||||
|
return builtin_packer<array_desc>::marker(desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr void pack(T const& value, auto& packer) noexcept {
|
||||||
|
packer.pack(array_desc(rep_size(value)));
|
||||||
|
for (auto const& element : value) {
|
||||||
|
packer.pack(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace msgpack
|
} // namespace msgpack
|
||||||
|
|||||||
@ -39,6 +39,7 @@
|
|||||||
#define msgpack_core_packer_1d5939e9c1498568
|
#define msgpack_core_packer_1d5939e9c1498568
|
||||||
|
|
||||||
#include "parselink/msgpack/core/detail/builtin_packable_types.h"
|
#include "parselink/msgpack/core/detail/builtin_packable_types.h"
|
||||||
|
#include "parselink/msgpack/core/detail/packable_ranges.h"
|
||||||
#include "parselink/msgpack/core/error.h"
|
#include "parselink/msgpack/core/error.h"
|
||||||
#include "parselink/msgpack/core/format.h"
|
#include "parselink/msgpack/core/format.h"
|
||||||
#include "parselink/msgpack/util/endianness.h"
|
#include "parselink/msgpack/util/endianness.h"
|
||||||
@ -75,9 +76,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <packable_type T>
|
template <packable_type T>
|
||||||
constexpr tl::expected<tl::monostate, error> pack(T&& v) noexcept {
|
constexpr tl::expected<tl::monostate, error> pack(T const& v) noexcept {
|
||||||
using diff_type =
|
|
||||||
std::iterator_traits<decltype(curr_)>::difference_type;
|
|
||||||
auto rem = remaining();
|
auto rem = remaining();
|
||||||
decltype(rem) needed = builtin_packer<T>::total_size(v);
|
decltype(rem) needed = builtin_packer<T>::total_size(v);
|
||||||
if (needed > rem) {
|
if (needed > rem) {
|
||||||
@ -93,10 +92,12 @@ public:
|
|||||||
constexpr tl::expected<tl::monostate, error> pack(T&& v) noexcept {
|
constexpr tl::expected<tl::monostate, error> pack(T&& v) noexcept {
|
||||||
context ctx{curr_, end_};
|
context ctx{curr_, end_};
|
||||||
// If packing is successful, it updates iterators.
|
// If packing is successful, it updates iterators.
|
||||||
return ctx.pack(std::forward<T>(v)).map([&]{
|
auto ret = ctx.pack(std::forward<T>(v));
|
||||||
|
if (!!ret) {
|
||||||
curr_ = ctx.out;
|
curr_ = ctx.out;
|
||||||
end_ = ctx.end;
|
end_ = ctx.end;
|
||||||
});
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto tell() const noexcept {
|
constexpr auto tell() const noexcept {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user