more tests, allow signed int -> positive_fixint
This commit is contained in:
parent
8f4ac703f4
commit
e48ba60c68
@ -94,9 +94,7 @@ struct builtin_packer<bool> : builtin_packer_base {
|
||||
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;
|
||||
if (value < 128) return 0;
|
||||
auto bytes_needed =
|
||||
static_cast<std::uint64_t>((std::bit_width(value) + 7) >> 3);
|
||||
return std::bit_ceil(bytes_needed);
|
||||
@ -121,8 +119,8 @@ struct builtin_packer<T> : builtin_packer_base {
|
||||
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;
|
||||
// Probably a better way to do this; fixints
|
||||
if (value < 128 && value >= -32) return 0;
|
||||
auto underlying = static_cast<std::uint64_t>(value);
|
||||
|
||||
// save a branch; these should be cheap on modern hardware.
|
||||
|
||||
@ -21,8 +21,9 @@
|
||||
#ifndef msgpack_core_detail_packable_ranges_10d28c24498828c7
|
||||
#define msgpack_core_detail_packable_ranges_10d28c24498828c7
|
||||
|
||||
#include "parselink/msgpack/core/detail/packable_concepts.h"
|
||||
#include "parselink/msgpack/core/detail/builtin_packable_types.h"
|
||||
#include "parselink/msgpack/core/detail/packable_concepts.h"
|
||||
|
||||
#include <ranges>
|
||||
#include <tuple>
|
||||
|
||||
@ -31,8 +32,9 @@ namespace detail {
|
||||
|
||||
//
|
||||
template <typename T>
|
||||
concept packable_array = std::ranges::input_range<T>
|
||||
&& packable<std::ranges::range_value_t<T>>;
|
||||
concept packable_array =
|
||||
std::ranges::input_range<T> && !std::convertible_to<T, std::string_view>
|
||||
&& packable<std::ranges::range_value_t<T>>;
|
||||
|
||||
template <typename T>
|
||||
concept key_value_pairlike = requires(T t) {
|
||||
|
||||
@ -65,23 +65,18 @@ struct fmt::formatter<msgpack::array_desc> : fmt::formatter<std::string_view> {
|
||||
|
||||
namespace {
|
||||
|
||||
template <typename... Bytes>
|
||||
constexpr std::array<std::byte, sizeof...(Bytes)> make_bytes(Bytes&&... bytes) {
|
||||
return {static_cast<std::byte>(std::forward<Bytes>(bytes))...};
|
||||
}
|
||||
|
||||
constexpr auto equal(auto a, auto b) {
|
||||
return std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b));
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
consteval auto within() noexcept {
|
||||
return std::numeric_limits<T>::max() <= std::numeric_limits<U>::max();
|
||||
template <typename T>
|
||||
constexpr auto within(auto value) noexcept {
|
||||
return value >= std::numeric_limits<T>::min()
|
||||
&& value <= std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr auto verify_packed(auto const& packer, auto value) {
|
||||
std::array<std::byte, std::numeric_limits<T>::digits / 8> raw;
|
||||
std::byte marker_for;
|
||||
|
||||
template <std::integral T>
|
||||
constexpr auto verify_packed(auto const& packer, auto value) noexcept {
|
||||
std::array<std::byte, (std::numeric_limits<T>::digits + 7) / 8> raw;
|
||||
if (packer.tell() != 1 + raw.size()) return false;
|
||||
|
||||
auto packed = packer.subspan().subspan(1);
|
||||
@ -91,37 +86,72 @@ constexpr auto verify_packed(auto const& packer, auto value) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto check_unsigned() {
|
||||
return rc::check([] {
|
||||
auto check_signed() {
|
||||
return rc::check([](T value) {
|
||||
std::array<std::byte, 16> payload;
|
||||
msgpack::packer packer(payload);
|
||||
const auto value = *rc::gen::positive<T>();
|
||||
if (!packer.pack(value)) return false;
|
||||
|
||||
if (value < 0x80) {
|
||||
if (value < 128 && value >= -32) {
|
||||
// positive_fixint/negative_fixint
|
||||
return packer.tell() == 1
|
||||
&& payload[0] == static_cast<std::byte>(value);
|
||||
} else if (within<std::int8_t>(value)) {
|
||||
return payload[0] == msgpack::format::int8::marker
|
||||
&& verify_packed<std::int8_t>(packer, value);
|
||||
} else if (within<std::int16_t>(value)) {
|
||||
return payload[0] == msgpack::format::int16::marker
|
||||
&& verify_packed<std::int16_t>(packer, value);
|
||||
} else if (within<std::int32_t>(value)) {
|
||||
return payload[0] == msgpack::format::int32::marker
|
||||
&& verify_packed<std::int32_t>(packer, value);
|
||||
} else {
|
||||
return payload[0] == msgpack::format::int64::marker
|
||||
&& verify_packed<std::int64_t>(packer, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto check_unsigned() {
|
||||
return rc::check([](T value) {
|
||||
std::array<std::byte, 16> payload;
|
||||
msgpack::packer packer(payload);
|
||||
if (!packer.pack(value)) return false;
|
||||
|
||||
if (value < 128) {
|
||||
// positive_fixint
|
||||
return packer.tell() == 1
|
||||
&& payload[0] == static_cast<std::byte>(value);
|
||||
} else if (value <= std::numeric_limits<std::uint8_t>::max()) {
|
||||
// uint8
|
||||
return packer.tell() == 2 && payload[0] == std::byte{0xcc}
|
||||
&& T(payload[1]) == value;
|
||||
} else if (value <= std::numeric_limits<std::uint16_t>::max()) {
|
||||
// uint16
|
||||
return payload[0] == std::byte{0xcd}
|
||||
} else if (within<std::uint8_t>(value)) {
|
||||
return payload[0] == msgpack::format::uint8::marker
|
||||
&& verify_packed<std::uint8_t>(packer, value);
|
||||
} else if (within<std::uint16_t>(value)) {
|
||||
return payload[0] == msgpack::format::uint16::marker
|
||||
&& verify_packed<std::uint16_t>(packer, value);
|
||||
} else if (value <= std::numeric_limits<std::uint32_t>::max()) {
|
||||
// uint32
|
||||
return payload[0] == std::byte{0xce}
|
||||
} else if (within<std::uint32_t>(value)) {
|
||||
return payload[0] == msgpack::format::uint32::marker
|
||||
&& verify_packed<std::uint32_t>(packer, value);
|
||||
} else {
|
||||
// uint64
|
||||
return payload[0] == std::byte{0xcf}
|
||||
return payload[0] == msgpack::format::uint64::marker
|
||||
&& verify_packed<std::uint64_t>(packer, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <std::unsigned_integral LenType, typename StrType = std::string>
|
||||
auto check_string() {
|
||||
return rc::check([](LenType value) {
|
||||
auto str = *rc::gen::container<std::string>(
|
||||
value, rc::gen::character<char>());
|
||||
std::vector<std::byte> payload;
|
||||
payload.resize(value + 32);
|
||||
msgpack::packer packer(payload);
|
||||
if (!packer.pack(str)) return false;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
suite packer_single_format = [] {
|
||||
@ -167,42 +197,29 @@ suite packer_single_format = [] {
|
||||
"packer::pack<std::uint64_t>"_test = [] {
|
||||
expect(check_unsigned<std::uint64_t>());
|
||||
};
|
||||
|
||||
"packer::pack<std::int8_t>"_test = [] {
|
||||
expect(check_signed<std::int8_t>());
|
||||
};
|
||||
|
||||
"packer::pack<std::int16_t>"_test = [] {
|
||||
expect(check_signed<std::int16_t>());
|
||||
};
|
||||
|
||||
"packer::pack<std::int32_t>"_test = [] {
|
||||
expect(check_signed<std::int32_t>());
|
||||
};
|
||||
|
||||
"packer::pack<std::int64_t>"_test = [] {
|
||||
expect(check_signed<std::int64_t>());
|
||||
};
|
||||
|
||||
"packer::pack<std::string>"_test = [] {
|
||||
expect(check_string<std::uint8_t>());
|
||||
expect(check_string<std::uint16_t>());
|
||||
};
|
||||
};
|
||||
#if 0
|
||||
"packer::pack<bool>"_test = [] { expect(test_deduced<bool>()); };
|
||||
"packer::pack<nil>"_test = [] { expect(test_deduced<msgpack::nil>()); };
|
||||
"packer::pack<invalid>"_test = [] {
|
||||
expect(test_deduced<msgpack::invalid>());
|
||||
};
|
||||
|
||||
// Unsigned ints
|
||||
"packer::pack<std::uint8_t>"_test = [] {
|
||||
expect(test_deduced<std::uint8_t>());
|
||||
};
|
||||
"packer::pack<std::uint16_t>"_test = [] {
|
||||
expect(test_deduced<std::uint16_t>());
|
||||
};
|
||||
"packer::pack<std::uint32_t>"_test = [] {
|
||||
expect(test_deduced<std::uint32_t>());
|
||||
};
|
||||
"packer::pack<std::uint64_t>"_test = [] {
|
||||
expect(test_deduced<std::uint64_t>());
|
||||
};
|
||||
|
||||
// Signed ints
|
||||
"packer::pack<std::int8_t>"_test = [] {
|
||||
expect(test_deduced<std::int8_t>());
|
||||
};
|
||||
"packer::pack<std::int16_t>"_test = [] {
|
||||
expect(test_deduced<std::int16_t>());
|
||||
};
|
||||
"packer::pack<std::int32_t>"_test = [] {
|
||||
expect(test_deduced<std::int32_t>());
|
||||
};
|
||||
"packer::pack<std::int64_t>"_test = [] {
|
||||
expect(test_deduced<std::int64_t>());
|
||||
};
|
||||
|
||||
// Strings
|
||||
"packer::pack<std::string_view>"_test = [] {
|
||||
expect(test_deduced<std::string_view>());
|
||||
|
||||
Loading…
Reference in New Issue
Block a user