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