Skip to content

Add zero-copy unpack_type overload for std::span<B const>#7

Merged
rwindegger merged 1 commit intorwindegger:mainfrom
Neara-Software:bacek/span-unpack
Mar 4, 2026
Merged

Add zero-copy unpack_type overload for std::span<B const>#7
rwindegger merged 1 commit intorwindegger:mainfrom
Neara-Software:bacek/span-unpack

Conversation

@bacek
Copy link
Contributor

@bacek bacek commented Mar 3, 2026

Problem

The existing binary unpack path copies data into std::vector:

value.assign(src, src + bin_size);  // always allocates + copies

For callers that only need to read the binary payload (e.g. pass it to a parser like GEOS WKBReader), this allocation is pure waste — the data is already contiguous in the Unpacker's internal buffer.

Solution

Add a second unpack_type overload that resolves when the caller declares their argument as std::span:

template<std::size_t E>
void unpack_type(std::span<B const, E> &value) {
    // ... read header to get bin_size ...
    value = data_.subspan(position_, bin_size);  // zero-copy view
    increment(bin_size);
}

data_.subspan() returns a non-owning view into the Unpacker's own buffer, so no allocation or memcpy occurs. The span remains valid for the lifetime of the Unpacker (i.e. for the duration of the unpack call chain), which is sufficient for immediate-use patterns like deserialise → parse → discard.

Safety

  • Bounds are checked identically to the vector overload (position_ + bin_size

    data_.size() throws std::out_of_range).

  • The returned span is const-qualified (B const), preventing accidental writes back into the source buffer.
  • Callers that need to own the data should continue using std::vector.

Backwards compatibility

Fully additive — existing code using std::vector is unaffected. The new overload is only selected when the target variable is declared as std::span.

## Problem

The existing binary unpack path copies data into std::vector<B>:

    value.assign(src, src + bin_size);  // always allocates + copies

For callers that only need to read the binary payload (e.g. pass it to a
parser like GEOS WKBReader), this allocation is pure waste — the data is
already contiguous in the Unpacker's internal buffer.

## Solution

Add a second unpack_type overload that resolves when the caller declares
their argument as std::span<B const>:

    template<std::size_t E>
    void unpack_type(std::span<B const, E> &value) {
        // ... read header to get bin_size ...
        value = data_.subspan(position_, bin_size);  // zero-copy view
        increment(bin_size);
    }

data_.subspan() returns a non-owning view into the Unpacker's own buffer,
so no allocation or memcpy occurs. The span remains valid for the lifetime
of the Unpacker (i.e. for the duration of the unpack call chain), which
is sufficient for immediate-use patterns like deserialise → parse → discard.

## Safety

- Bounds are checked identically to the vector overload (position_ + bin_size
  > data_.size() throws std::out_of_range).
- The returned span is const-qualified (B const), preventing accidental writes
  back into the source buffer.
- Callers that need to own the data should continue using std::vector<B>.

## Backwards compatibility

Fully additive — existing code using std::vector<B> is unaffected. The new
overload is only selected when the target variable is declared as std::span.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@codecov-commenter
Copy link

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.90%. Comparing base (b35e800) to head (a1b7c5a).

Files with missing lines Patch % Lines
include/msgpack23/msgpack23.h 75.00% 2 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@            Coverage Diff             @@
##             main       #7      +/-   ##
==========================================
+ Coverage   93.16%   93.90%   +0.74%     
==========================================
  Files           1        1              
  Lines         468      476       +8     
==========================================
+ Hits          436      447      +11     
+ Misses         32       29       -3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@rwindegger rwindegger merged commit 6639136 into rwindegger:main Mar 4, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants