From 55c715915cb6c9a30929948a11e861798057dd36 Mon Sep 17 00:00:00 2001 From: Vasily Chekalkin Date: Fri, 6 Mar 2026 09:22:51 +1100 Subject: [PATCH] Add std::span packing support and extend span tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add pack_type overload for std::span that serialises as msgpack bin8/bin16/bin32 - Add packSpanRoundTrip: pack span → unpack vector, compare bytes - Add packSpanMatchesVector: packed bytes from span == from equivalent vector Co-Authored-By: Claude Sonnet 4.6 --- include/msgpack23/msgpack23.h | 16 ++++++++++++++++ tests/span_tests.cpp | 36 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/include/msgpack23/msgpack23.h b/include/msgpack23/msgpack23.h index f507ac1..0ba7b22 100644 --- a/include/msgpack23/msgpack23.h +++ b/include/msgpack23/msgpack23.h @@ -476,6 +476,22 @@ namespace msgpack23 { std::copy(reinterpret_cast(value.data()), reinterpret_cast(value.data() + value.size()), store_); } + + template + void pack_type(std::span const &value) { + if (value.size() < std::numeric_limits::max()) { + emplace_constant(FormatConstants::bin8); + *store_++ = static_cast(value.size()); + } else if (value.size() < std::numeric_limits::max()) { + emplace_combined(FormatConstants::bin16, static_cast(value.size())); + } else if (value.size() < std::numeric_limits::max()) { + emplace_combined(FormatConstants::bin32, static_cast(value.size())); + } else { + throw std::length_error("Span is too long to be serialized."); + } + auto const *src = reinterpret_cast(value.data()); + std::copy(src, src + value.size(), store_); + } }; template diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 5449d19..d8b42d5 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -41,6 +41,42 @@ namespace { EXPECT_LE(actual.data() + actual.size(), data.data() + data.size()); } + // Packing a span: pack span → unpack vector, compare bytes. + TEST_P(msgpack23_span, packSpanRoundTrip) { + std::vector original{}; + for (std::size_t i = 0; i < GetParam(); ++i) { + original.emplace_back(static_cast(i)); + } + std::span input{original}; + + std::vector data{}; + msgpack23::Packer packer{std::back_insert_iterator(data)}; + packer(input); + + msgpack23::Unpacker unpacker{data}; + std::vector actual{}; + unpacker(actual); + + EXPECT_EQ(actual, original); + } + + // Packing a span produces identical bytes to packing the equivalent vector. + TEST_P(msgpack23_span, packSpanMatchesVector) { + std::vector original{}; + for (std::size_t i = 0; i < GetParam(); ++i) { + original.emplace_back(static_cast(i)); + } + + std::vector from_vector{}; + msgpack23::Packer{std::back_insert_iterator(from_vector)}(original); + + std::vector from_span{}; + msgpack23::Packer{std::back_insert_iterator(from_span)}( + std::span{original}); + + EXPECT_EQ(from_span, from_vector); + } + constexpr std::size_t span_sizes[] = { 1, std::numeric_limits::max() - 1, // bin8 near-max