Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions include/msgpack23/msgpack23.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,22 @@ namespace msgpack23 {
std::copy(reinterpret_cast<B const * const>(value.data()),
reinterpret_cast<B const * const>(value.data() + value.size()), store_);
}

template<std::size_t E>
void pack_type(std::span<B const, E> const &value) {
if (value.size() < std::numeric_limits<std::uint8_t>::max()) {
emplace_constant(FormatConstants::bin8);
*store_++ = static_cast<B>(value.size());
} else if (value.size() < std::numeric_limits<std::uint16_t>::max()) {
emplace_combined(FormatConstants::bin16, static_cast<std::uint16_t>(value.size()));
} else if (value.size() < std::numeric_limits<std::uint32_t>::max()) {
emplace_combined(FormatConstants::bin32, static_cast<std::uint32_t>(value.size()));
} else {
throw std::length_error("Span is too long to be serialized.");
}
auto const *src = reinterpret_cast<B const *>(value.data());
std::copy(src, src + value.size(), store_);
}
};

template<typename Container>
Expand Down
36 changes: 36 additions & 0 deletions tests/span_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::uint8_t> original{};
for (std::size_t i = 0; i < GetParam(); ++i) {
original.emplace_back(static_cast<std::uint8_t>(i));
}
std::span<const std::uint8_t> input{original};

std::vector<std::uint8_t> data{};
msgpack23::Packer packer{std::back_insert_iterator(data)};
packer(input);

msgpack23::Unpacker unpacker{data};
std::vector<std::uint8_t> 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<std::uint8_t> original{};
for (std::size_t i = 0; i < GetParam(); ++i) {
original.emplace_back(static_cast<std::uint8_t>(i));
}

std::vector<std::uint8_t> from_vector{};
msgpack23::Packer{std::back_insert_iterator(from_vector)}(original);

std::vector<std::uint8_t> from_span{};
msgpack23::Packer{std::back_insert_iterator(from_span)}(
std::span<const std::uint8_t>{original});

EXPECT_EQ(from_span, from_vector);
}

constexpr std::size_t span_sizes[] = {
1,
std::numeric_limits<std::uint8_t>::max() - 1, // bin8 near-max
Expand Down