diff --git a/include/parselink/msgpack/core/detail/builtin_packable_types.h b/include/parselink/msgpack/core/detail/builtin_packable_types.h index acd591c..612d42a 100644 --- a/include/parselink/msgpack/core/detail/builtin_packable_types.h +++ b/include/parselink/msgpack/core/detail/builtin_packable_types.h @@ -94,9 +94,7 @@ struct builtin_packer : builtin_packer_base { template struct builtin_packer : builtin_packer_base { static constexpr std::size_t rep_size(std::uint64_t value) noexcept { - constexpr auto fixint_size = - static_cast(format::positive_fixint::mask); - if (value <= fixint_size) return 0; + if (value < 128) return 0; auto bytes_needed = static_cast((std::bit_width(value) + 7) >> 3); return std::bit_ceil(bytes_needed); @@ -121,8 +119,8 @@ struct builtin_packer : builtin_packer_base { template struct builtin_packer : 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(value); // save a branch; these should be cheap on modern hardware. diff --git a/include/parselink/msgpack/core/detail/packable_ranges.h b/include/parselink/msgpack/core/detail/packable_ranges.h index 75115b1..92b33df 100644 --- a/include/parselink/msgpack/core/detail/packable_ranges.h +++ b/include/parselink/msgpack/core/detail/packable_ranges.h @@ -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 #include @@ -31,8 +32,9 @@ namespace detail { // template -concept packable_array = std::ranges::input_range - && packable>; +concept packable_array = + std::ranges::input_range && !std::convertible_to + && packable>; template concept key_value_pairlike = requires(T t) { diff --git a/tests/msgpack/test_packer_rc.cpp b/tests/msgpack/test_packer_rc.cpp index 1f31d4e..f399ad5 100644 --- a/tests/msgpack/test_packer_rc.cpp +++ b/tests/msgpack/test_packer_rc.cpp @@ -65,23 +65,18 @@ struct fmt::formatter : fmt::formatter { namespace { -template -constexpr std::array make_bytes(Bytes&&... bytes) { - return {static_cast(std::forward(bytes))...}; -} - -constexpr auto equal(auto a, auto b) { - return std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b)); -} - -template -consteval auto within() noexcept { - return std::numeric_limits::max() <= std::numeric_limits::max(); +template +constexpr auto within(auto value) noexcept { + return value >= std::numeric_limits::min() + && value <= std::numeric_limits::max(); } template -constexpr auto verify_packed(auto const& packer, auto value) { - std::array::digits / 8> raw; +std::byte marker_for; + +template +constexpr auto verify_packed(auto const& packer, auto value) noexcept { + std::array::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 -auto check_unsigned() { - return rc::check([] { +auto check_signed() { + return rc::check([](T value) { std::array payload; msgpack::packer packer(payload); - const auto value = *rc::gen::positive(); 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(value); + } else if (within(value)) { + return payload[0] == msgpack::format::int8::marker + && verify_packed(packer, value); + } else if (within(value)) { + return payload[0] == msgpack::format::int16::marker + && verify_packed(packer, value); + } else if (within(value)) { + return payload[0] == msgpack::format::int32::marker + && verify_packed(packer, value); + } else { + return payload[0] == msgpack::format::int64::marker + && verify_packed(packer, value); + } + }); +} + +template +auto check_unsigned() { + return rc::check([](T value) { + std::array payload; + msgpack::packer packer(payload); + if (!packer.pack(value)) return false; + + if (value < 128) { // positive_fixint return packer.tell() == 1 && payload[0] == static_cast(value); - } else if (value <= std::numeric_limits::max()) { - // uint8 - return packer.tell() == 2 && payload[0] == std::byte{0xcc} - && T(payload[1]) == value; - } else if (value <= std::numeric_limits::max()) { - // uint16 - return payload[0] == std::byte{0xcd} + } else if (within(value)) { + return payload[0] == msgpack::format::uint8::marker + && verify_packed(packer, value); + } else if (within(value)) { + return payload[0] == msgpack::format::uint16::marker && verify_packed(packer, value); - } else if (value <= std::numeric_limits::max()) { - // uint32 - return payload[0] == std::byte{0xce} + } else if (within(value)) { + return payload[0] == msgpack::format::uint32::marker && verify_packed(packer, value); } else { - // uint64 - return payload[0] == std::byte{0xcf} + return payload[0] == msgpack::format::uint64::marker && verify_packed(packer, value); } }); } +template +auto check_string() { + return rc::check([](LenType value) { + auto str = *rc::gen::container( + value, rc::gen::character()); + std::vector 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"_test = [] { expect(check_unsigned()); }; + + "packer::pack"_test = [] { + expect(check_signed()); + }; + + "packer::pack"_test = [] { + expect(check_signed()); + }; + + "packer::pack"_test = [] { + expect(check_signed()); + }; + + "packer::pack"_test = [] { + expect(check_signed()); + }; + + "packer::pack"_test = [] { + expect(check_string()); + expect(check_string()); + }; }; #if 0 -"packer::pack"_test = [] { expect(test_deduced()); }; - "packer::pack"_test = [] { expect(test_deduced()); }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - - // Unsigned ints - "packer::pack"_test = [] { - expect(test_deduced()); - }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - - // Signed ints - "packer::pack"_test = [] { - expect(test_deduced()); - }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - "packer::pack"_test = [] { - expect(test_deduced()); - }; - // Strings "packer::pack"_test = [] { expect(test_deduced());