Remove builtin_pack_helper.
This commit is contained in:
parent
c89d7cd541
commit
0e00edc378
@ -38,39 +38,59 @@ constexpr auto pack_integral(T value, Itr out, std::size_t sz) noexcept {
|
||||
return out;
|
||||
}
|
||||
|
||||
// This structure helps to derive sizes needed to optimally represent the
|
||||
// given value (for integer formats) or the length (variable-length formats).
|
||||
template <format::type T>
|
||||
struct builtin_pack_helper {
|
||||
#if 0
|
||||
// Returns the number of bytes needed to store the representation of a
|
||||
// value in the associated msgpack format.
|
||||
static constexpr std::size_t rep_bytes(auto /*value*/) noexcept {
|
||||
// Defines a range of bytes for binary formats.
|
||||
template <typename T>
|
||||
concept byte_range = std::ranges::contiguous_range<T>
|
||||
&& std::same_as<std::ranges::range_value_t<T>, std::byte>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
struct builtin_packer_base {
|
||||
static constexpr std::size_t rep_size(auto const&) noexcept { return 0; }
|
||||
|
||||
static constexpr std::size_t len_size(auto const& value) noexcept {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Returns the number of bytes needed to store the length of a value for
|
||||
// a given format. For fixed-size data, this will be zero.
|
||||
static constexpr std::size_t len_bytes(auto /*value*/) noexcept {
|
||||
return 0;
|
||||
static constexpr auto total_size(auto const& value) noexcept {
|
||||
return 1 + len_size(value) + rep_size(value);
|
||||
}
|
||||
};
|
||||
|
||||
// Returns the total number of bytes needed to store a value for a given
|
||||
// format.
|
||||
static constexpr std::size_t total_bytes(auto value) noexcept {
|
||||
return 1 + rep_bytes(value) + len_bytes(value);
|
||||
}
|
||||
template <typename>
|
||||
struct builtin_packer;
|
||||
|
||||
// Get the marker. Defaults to invalid in this structure.
|
||||
static constexpr std::byte marker(auto value) noexcept {
|
||||
return format::invalid::marker;
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Built-in packer specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
struct builtin_packer<invalid> : builtin_packer_base {
|
||||
static constexpr auto pack(auto, auto out) noexcept -> decltype(out) {
|
||||
*out++ = format::invalid::marker;
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::unsigned_int> {
|
||||
static constexpr std::size_t rep_bytes(std::uint64_t value) noexcept {
|
||||
struct builtin_packer<nil> : builtin_packer_base {
|
||||
static constexpr auto pack(auto, auto out) noexcept -> decltype(out) {
|
||||
*out++ = format::nil::marker;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_packer<bool> : builtin_packer_base {
|
||||
static constexpr auto pack(bool value, auto out) noexcept -> decltype(out) {
|
||||
*out++ = format::boolean::marker | static_cast<std::byte>(value);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::unsigned_integral T>
|
||||
struct builtin_packer<T> : builtin_packer_base {
|
||||
static constexpr std::size_t rep_size(std::uint64_t value) noexcept {
|
||||
constexpr auto fixint_size =
|
||||
static_cast<std::uint64_t>(format::positive_fixint::mask);
|
||||
if (value <= fixint_size) return 0;
|
||||
@ -80,7 +100,7 @@ struct builtin_pack_helper<format::type::unsigned_int> {
|
||||
}
|
||||
|
||||
static constexpr std::byte marker(std::uint64_t value) noexcept {
|
||||
switch (rep_bytes(value)) {
|
||||
switch (rep_size(value)) {
|
||||
case 0: return static_cast<std::byte>(value);
|
||||
case 1: return format::uint8::marker;
|
||||
case 2: return format::uint16::marker;
|
||||
@ -88,11 +108,17 @@ struct builtin_pack_helper<format::type::unsigned_int> {
|
||||
default: return format::uint64::marker;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto pack(
|
||||
T const& value, auto out) noexcept -> decltype(out) {
|
||||
*out++ = marker(value);
|
||||
return detail::pack_integral(value, out, rep_size(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::signed_int> {
|
||||
static constexpr std::size_t rep_bytes(std::int64_t value) noexcept {
|
||||
template <std::signed_integral T>
|
||||
struct builtin_packer<T> : builtin_packer_base {
|
||||
static constexpr std::size_t rep_size(std::int64_t value) noexcept {
|
||||
// Probably a better way to do this.
|
||||
if (value < 0 && value >= -32) return 0;
|
||||
auto underlying = static_cast<std::uint64_t>(value);
|
||||
@ -109,7 +135,7 @@ struct builtin_pack_helper<format::type::signed_int> {
|
||||
}
|
||||
|
||||
static constexpr std::byte marker(std::int64_t value) noexcept {
|
||||
switch (rep_bytes(value)) {
|
||||
switch (rep_size(value)) {
|
||||
case 0: return static_cast<std::byte>(value);
|
||||
case 1: return format::int8::marker;
|
||||
case 2: return format::int16::marker;
|
||||
@ -117,176 +143,40 @@ struct builtin_pack_helper<format::type::signed_int> {
|
||||
default: return format::int64::marker;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::nil> {
|
||||
static constexpr std::size_t rep_bytes(nil) noexcept { return 0; }
|
||||
|
||||
static constexpr std::byte marker(nil) noexcept {
|
||||
return format::nil::marker;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::invalid> {
|
||||
static constexpr std::size_t rep_bytes(invalid) noexcept { return 0; }
|
||||
|
||||
static constexpr std::byte marker(invalid) noexcept {
|
||||
return format::invalid::marker;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept byte_range = std::ranges::contiguous_range<T>
|
||||
&& std::same_as<std::ranges::range_value_t<T>, std::byte>;
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::binary> {
|
||||
static constexpr uint32_t max_payload_length = 4;
|
||||
|
||||
static constexpr std::size_t rep_bytes(
|
||||
byte_range auto const& value) noexcept {
|
||||
return std::ranges::size(value);
|
||||
}
|
||||
|
||||
static constexpr std::size_t len_bytes(
|
||||
byte_range auto const& value) noexcept {
|
||||
auto const len = rep_bytes(value);
|
||||
auto const rounded_bytes = std::bit_ceil(static_cast<std::uint32_t>(
|
||||
((std::bit_width(std::ranges::size(value)) + 7) >> 3)));
|
||||
return std::min(max_payload_length, rounded_bytes);
|
||||
}
|
||||
|
||||
static constexpr auto marker(byte_range auto const& value) noexcept {
|
||||
switch (len_bytes(value)) {
|
||||
case 1: return format::bin8::marker;
|
||||
case 2: return format::bin16::marker;
|
||||
case 4:
|
||||
default: return format::bin32::marker;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::string> {
|
||||
static constexpr uint32_t max_payload_length = 4;
|
||||
|
||||
static constexpr std::size_t rep_bytes(auto const& value) noexcept {
|
||||
return std::size(value);
|
||||
}
|
||||
|
||||
static constexpr std::size_t len_bytes(auto const& value) noexcept {
|
||||
auto const len = std::size(value);
|
||||
if (len <= std::uint32_t(format::fixstr::mask)) return 0;
|
||||
return std::min(max_payload_length,
|
||||
std::bit_ceil(std::uint32_t((std::bit_width(len) + 7) >> 3)));
|
||||
}
|
||||
|
||||
static constexpr auto marker(auto const& value) noexcept {
|
||||
switch (len_bytes(value)) {
|
||||
case 0:
|
||||
return format::fixstr::marker
|
||||
| static_cast<std::byte>(std::size(value));
|
||||
case 1: return format::str8::marker;
|
||||
case 2: return format::str16::marker;
|
||||
case 4:
|
||||
default: return format::str32::marker;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_pack_helper<format::type::boolean> {
|
||||
static constexpr std::size_t rep_bytes(auto const&) noexcept { return 0; }
|
||||
|
||||
static constexpr auto marker(auto const& value) noexcept {
|
||||
return format::boolean::marker
|
||||
| (value ? std::byte{0x01} : std::byte{});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <format::type F>
|
||||
struct builtin_packer_base {
|
||||
static constexpr auto format = F;
|
||||
using helper = detail::builtin_pack_helper<F>;
|
||||
|
||||
static constexpr std::size_t rep_size(auto const& value) noexcept {
|
||||
return helper::rep_bytes(value);
|
||||
}
|
||||
|
||||
static constexpr std::size_t len_size(auto const& value) noexcept {
|
||||
if constexpr (requires { helper::len_bytes(value); }) {
|
||||
return helper::len_bytes(value);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto total_size(auto const& value) noexcept {
|
||||
return 1 + len_size(value) + rep_size(value);
|
||||
}
|
||||
|
||||
static constexpr auto marker(auto const& value) noexcept {
|
||||
return helper::marker(value);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename>
|
||||
struct builtin_packer;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Built-in packer specializations
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <>
|
||||
struct builtin_packer<invalid> : builtin_packer_base<format::type::invalid> {
|
||||
static constexpr auto pack(auto, auto out) noexcept -> decltype(out) {
|
||||
*out++ = format::invalid::marker;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_packer<nil> : builtin_packer_base<format::type::nil> {
|
||||
static constexpr auto pack(auto, auto out) noexcept -> decltype(out) {
|
||||
*out++ = format::nil::marker;
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_packer<bool> : builtin_packer_base<format::type::boolean> {
|
||||
static constexpr auto pack(bool value, auto out) noexcept -> decltype(out) {
|
||||
*out++ = marker(value);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
template <std::unsigned_integral T>
|
||||
struct builtin_packer<T> : builtin_packer_base<format::type::unsigned_int> {
|
||||
static constexpr auto pack(T const& value, auto out) noexcept
|
||||
-> decltype(out) {
|
||||
*out++ = marker(value);
|
||||
return detail::pack_integral(value, out, rep_size(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <std::signed_integral T>
|
||||
struct builtin_packer<T> : builtin_packer_base<format::type::signed_int> {
|
||||
static constexpr auto pack(T const& value, auto out) noexcept
|
||||
-> decltype(out) {
|
||||
static constexpr auto pack(
|
||||
T const& value, auto out) noexcept -> decltype(out) {
|
||||
*out++ = marker(value);
|
||||
return detail::pack_integral(value, out, rep_size(value));
|
||||
}
|
||||
};
|
||||
|
||||
template <detail::byte_range T>
|
||||
struct builtin_packer<T> : builtin_packer_base<format::type::binary> {
|
||||
static constexpr auto pack(T const& value, auto out) noexcept
|
||||
-> decltype(out) {
|
||||
struct builtin_packer<T> : builtin_packer_base {
|
||||
static constexpr uint32_t max_payload_length = 4;
|
||||
|
||||
static constexpr std::size_t rep_size(T const& value) noexcept {
|
||||
return std::ranges::size(value);
|
||||
}
|
||||
|
||||
static constexpr std::size_t len_size(T const& value) noexcept {
|
||||
auto const len = rep_size(value);
|
||||
auto const rounded_bytes = std::bit_ceil(static_cast<std::uint32_t>(
|
||||
((std::bit_width(std::ranges::size(value)) + 7) >> 3)));
|
||||
return std::min(max_payload_length, rounded_bytes);
|
||||
}
|
||||
|
||||
static constexpr auto marker(T const& value) noexcept {
|
||||
switch (len_size(value)) {
|
||||
case 1: return format::bin8::marker;
|
||||
case 2: return format::bin16::marker;
|
||||
case 4:
|
||||
default: return format::bin32::marker;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto pack(
|
||||
T const& value, auto out) noexcept -> decltype(out) {
|
||||
*out++ = marker(value);
|
||||
out = detail::pack_integral(
|
||||
std::ranges::size(value), out, len_size(value));
|
||||
@ -295,10 +185,34 @@ struct builtin_packer<T> : builtin_packer_base<format::type::binary> {
|
||||
};
|
||||
|
||||
template <>
|
||||
struct builtin_packer<std::string_view>
|
||||
: builtin_packer_base<format::type::string> {
|
||||
static constexpr auto pack(std::string_view value, auto out) noexcept
|
||||
-> decltype(out) {
|
||||
struct builtin_packer<std::string_view> : builtin_packer_base {
|
||||
static constexpr uint32_t max_payload_length = 4;
|
||||
|
||||
static constexpr std::size_t rep_size(std::string_view value) noexcept {
|
||||
return std::size(value);
|
||||
}
|
||||
|
||||
static constexpr std::size_t len_size(std::string_view value) noexcept {
|
||||
auto const len = std::size(value);
|
||||
if (len <= std::uint32_t(format::fixstr::mask)) return 0;
|
||||
return std::min(max_payload_length,
|
||||
std::bit_ceil(std::uint32_t((std::bit_width(len) + 7) >> 3)));
|
||||
}
|
||||
|
||||
static constexpr auto marker(std::string_view value) noexcept {
|
||||
switch (len_size(value)) {
|
||||
case 0:
|
||||
return format::fixstr::marker
|
||||
| static_cast<std::byte>(rep_size(value));
|
||||
case 1: return format::str8::marker;
|
||||
case 2: return format::str16::marker;
|
||||
case 4:
|
||||
default: return format::str32::marker;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr auto pack(
|
||||
std::string_view value, auto out) noexcept -> decltype(out) {
|
||||
*out++ = marker(value);
|
||||
auto const size = std::size(value);
|
||||
out = detail::pack_integral(size, out, len_size(value));
|
||||
@ -307,16 +221,18 @@ struct builtin_packer<std::string_view>
|
||||
}
|
||||
};
|
||||
|
||||
// All things that convert to std::string_view should use the string_view
|
||||
// overload of builtin_packer.
|
||||
template <std::convertible_to<std::string_view> T>
|
||||
struct builtin_packer<T> : builtin_packer<std::string_view> {};
|
||||
|
||||
template <>
|
||||
struct builtin_packer<msgpack::array_desc>
|
||||
: builtin_packer_base<format::type::array> {};
|
||||
/* template <> */
|
||||
/* struct builtin_packer<msgpack::array_desc> */
|
||||
/* : builtin_packer_base<format::type::array> {}; */
|
||||
|
||||
template <>
|
||||
struct builtin_packer<msgpack::map_desc>
|
||||
: builtin_packer_base<format::type::map> {};
|
||||
/* template <> */
|
||||
/* struct builtin_packer<msgpack::map_desc> */
|
||||
/* : builtin_packer_base<format::type::map> {}; */
|
||||
|
||||
// Requirements for builtin_packable types.
|
||||
template <typename T>
|
||||
|
||||
@ -35,7 +35,8 @@ static_assert(packable_range<std::array<std::string_view, 5>>);
|
||||
static_assert(packable_range<std::span<std::string_view>>);
|
||||
|
||||
template <packable_range T>
|
||||
struct builtin_packer<T> {};
|
||||
struct builtin_packer<T> {
|
||||
};
|
||||
|
||||
} // namespace msgpack
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user