Skip to content

Commit aac15b8

Browse files
bacekclaude
andauthored
Add std::span packing support and extend span tests (#8)
- Add pack_type overload for std::span<B const, E> 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 <noreply@anthropic.com>
1 parent 6639136 commit aac15b8

2 files changed

Lines changed: 52 additions & 0 deletions

File tree

include/msgpack23/msgpack23.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,22 @@ namespace msgpack23 {
476476
std::copy(reinterpret_cast<B const * const>(value.data()),
477477
reinterpret_cast<B const * const>(value.data() + value.size()), store_);
478478
}
479+
480+
template<std::size_t E>
481+
void pack_type(std::span<B const, E> const &value) {
482+
if (value.size() < std::numeric_limits<std::uint8_t>::max()) {
483+
emplace_constant(FormatConstants::bin8);
484+
*store_++ = static_cast<B>(value.size());
485+
} else if (value.size() < std::numeric_limits<std::uint16_t>::max()) {
486+
emplace_combined(FormatConstants::bin16, static_cast<std::uint16_t>(value.size()));
487+
} else if (value.size() < std::numeric_limits<std::uint32_t>::max()) {
488+
emplace_combined(FormatConstants::bin32, static_cast<std::uint32_t>(value.size()));
489+
} else {
490+
throw std::length_error("Span is too long to be serialized.");
491+
}
492+
auto const *src = reinterpret_cast<B const *>(value.data());
493+
std::copy(src, src + value.size(), store_);
494+
}
479495
};
480496

481497
template<typename Container>

tests/span_tests.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,42 @@ namespace {
4141
EXPECT_LE(actual.data() + actual.size(), data.data() + data.size());
4242
}
4343

44+
// Packing a span: pack span → unpack vector, compare bytes.
45+
TEST_P(msgpack23_span, packSpanRoundTrip) {
46+
std::vector<std::uint8_t> original{};
47+
for (std::size_t i = 0; i < GetParam(); ++i) {
48+
original.emplace_back(static_cast<std::uint8_t>(i));
49+
}
50+
std::span<const std::uint8_t> input{original};
51+
52+
std::vector<std::uint8_t> data{};
53+
msgpack23::Packer packer{std::back_insert_iterator(data)};
54+
packer(input);
55+
56+
msgpack23::Unpacker unpacker{data};
57+
std::vector<std::uint8_t> actual{};
58+
unpacker(actual);
59+
60+
EXPECT_EQ(actual, original);
61+
}
62+
63+
// Packing a span produces identical bytes to packing the equivalent vector.
64+
TEST_P(msgpack23_span, packSpanMatchesVector) {
65+
std::vector<std::uint8_t> original{};
66+
for (std::size_t i = 0; i < GetParam(); ++i) {
67+
original.emplace_back(static_cast<std::uint8_t>(i));
68+
}
69+
70+
std::vector<std::uint8_t> from_vector{};
71+
msgpack23::Packer{std::back_insert_iterator(from_vector)}(original);
72+
73+
std::vector<std::uint8_t> from_span{};
74+
msgpack23::Packer{std::back_insert_iterator(from_span)}(
75+
std::span<const std::uint8_t>{original});
76+
77+
EXPECT_EQ(from_span, from_vector);
78+
}
79+
4480
constexpr std::size_t span_sizes[] = {
4581
1,
4682
std::numeric_limits<std::uint8_t>::max() - 1, // bin8 near-max

0 commit comments

Comments
 (0)