Skip to content

fix(read): handle dynamic-buffer max_size without throwing (#318)#340

Open
mvandeberg wants to merge 1 commit into
cppalliance:develop-2from
mvandeberg:pr/318-read-until-max-size
Open

fix(read): handle dynamic-buffer max_size without throwing (#318)#340
mvandeberg wants to merge 1 commit into
cppalliance:develop-2from
mvandeberg:pr/318-read-until-max-size

Conversation

@mvandeberg

Copy link
Copy Markdown
Contributor

The read dynamic-buffer overloads passed the (grown) amount straight to dynbuf.prepare(), so when it exceeded the remaining capacity (e.g. the default initial_amount of 2048 into a bounded buffer) prepare() threw std::invalid_argument / std::length_error. This was inconsistent with read_until, which already clamps.

Clamp the prepared amount to max_size() - size() and treat reaching max_size() as a successful completion. The existing eof-as-success semantics are unchanged, and read_until keeps returning error::not_found at max_size().

The clamp targets the contract that prepare(n) accepts any n with size() + n <= max_size(): string/vector grow and circular wraps to honor it. A fixed-capacity buffer may, but need not, compact; a non-compacting flat_dynamic_buffer reused after a partial consume has capacity() < max_size() - size(), so prepare throws. This is documented as a limitation — such buffers must be passed without a consumed prefix. Clamping to capacity() instead is not viable: it spins growable buffers.

Also floor the prepared amount to 1 so initial_amount == 0 cannot spin, and factor the clamp into detail::read_prepare_amount so the two overloads cannot drift.

Tests cover bounded string/circular/flat buffers, the flat consumed-prefix throw, and buffer contents.

Closes #318

…ce#318)

The read dynamic-buffer overloads passed the (grown) amount straight to
dynbuf.prepare(), so when it exceeded the remaining capacity (e.g. the
default initial_amount of 2048 into a bounded buffer) prepare() threw
std::invalid_argument / std::length_error. This was inconsistent with
read_until, which already clamps.

Clamp the prepared amount to max_size() - size() and treat reaching
max_size() as a successful completion. The existing eof-as-success
semantics are unchanged, and read_until keeps returning error::not_found
at max_size().

The clamp targets the contract that prepare(n) accepts any n with
size() + n <= max_size(): string/vector grow and circular wraps to honor
it. A fixed-capacity buffer may, but need not, compact; a non-compacting
flat_dynamic_buffer reused after a partial consume has
capacity() < max_size() - size(), so prepare throws. This is documented
as a limitation — such buffers must be passed without a consumed prefix.
Clamping to capacity() instead is not viable: it spins growable buffers.

Also floor the prepared amount to 1 so initial_amount == 0 cannot spin,
and factor the clamp into detail::read_prepare_amount so the two
overloads cannot drift.

Tests cover bounded string/circular/flat buffers, the flat consumed-prefix
throw, and buffer contents.
@cppalliance-bot

Copy link
Copy Markdown

An automated preview of the documentation is available at https://340.capy.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-06-25 20:28:05 UTC

@codecov

codecov Bot commented Jun 25, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (develop-2@1559c4f). Learn more about missing BASE report.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff              @@
##             develop-2     #340   +/-   ##
============================================
  Coverage             ?   98.39%           
============================================
  Files                ?       83           
  Lines                ?     4237           
  Branches             ?        0           
============================================
  Hits                 ?     4169           
  Misses               ?       68           
  Partials             ?        0           
Flag Coverage Δ
linux 98.39% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 1559c4f...902a66f. Read the comment docs.

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

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.

2 participants