Skip to content

Remove corosio read/write in favor of capy equivalents#91

Merged
sgerbino merged 1 commit into
cppalliance:developfrom
sgerbino:pr/clean-project
Jan 29, 2026
Merged

Remove corosio read/write in favor of capy equivalents#91
sgerbino merged 1 commit into
cppalliance:developfrom
sgerbino:pr/clean-project

Conversation

@sgerbino

@sgerbino sgerbino commented Jan 28, 2026

Copy link
Copy Markdown
Collaborator

The corosio::read and corosio::write functions duplicated functionality already provided by the capy library. Remove these implementations and migrate all usages to the capy equivalents.

Deleted:

  • include/boost/corosio/read.hpp
  • include/boost/corosio/write.hpp
  • include/boost/corosio/detail/unique_ptr.hpp
  • test/unit/read.cpp
  • test/unit/write.cpp

Modified:

  • include/boost/corosio.hpp: Remove read.hpp/write.hpp includes, add acceptor.hpp
  • example/client/http_client.cpp: Use capy::read/write with string_dynamic_buffer, preserve EOF handling
  • example/https-client/https_client.cpp: Use capy::read/write with string_dynamic_buffer, preserve EOF handling
  • test/unit/socket.cpp: Use capy::string_dynamic_buffer for dynamic reads

Summary by CodeRabbit

  • Refactor
    • Deprecated read and write APIs; examples now use capy equivalents.
    • Removed internal utility helpers from detail namespace.
    • Reorganized public header includes and dependencies.

✏️ Tip: You can customize this high-level summary in your review settings.

The corosio::read and corosio::write functions duplicated functionality
already provided by the capy library. Remove these implementations and
migrate all usages to the capy equivalents.

Deleted:
- include/boost/corosio/read.hpp
- include/boost/corosio/write.hpp
- include/boost/corosio/detail/unique_ptr.hpp
- test/unit/read.cpp
- test/unit/write.cpp

Modified:
- include/boost/corosio.hpp: Remove read.hpp/write.hpp includes, add
  acceptor.hpp
- example/client/http_client.cpp: Use capy::read/write with
  string_dynamic_buffer, preserve EOF handling
- example/https-client/https_client.cpp: Use capy::read/write with
  string_dynamic_buffer, preserve EOF handling
- test/unit/socket.cpp: Use capy::string_dynamic_buffer for dynamic
  reads
@coderabbitai

coderabbitai Bot commented Jan 28, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This PR removes core I/O utilities (read.hpp, write.hpp) and a helper utility (unique_ptr.hpp) from the corosio library while migrating example code to use equivalent capy APIs. The main corosio header is updated to reflect these removals.

Changes

Cohort / File(s) Summary
Example Updates
example/client/http_client.cpp, example/https-client/https_client.cpp
Migrated from corosio::read/corosio::write to capy::read/capy::write; updated includes to reference capy headers; adjusted buffer handling to use capy::string_dynamic_buffer wrapping for read operations.
Header Cleanup
include/boost/corosio.hpp
Removed includes for read.hpp, write.hpp, and io_result.hpp; added include for acceptor.hpp.
Removed Utilities
include/boost/corosio/detail/unique_ptr.hpp
Deleted entire file containing unique_ptr type alias and make_unique factory function template (50 lines removed).
Removed I/O APIs
include/boost/corosio/read.hpp, include/boost/corosio/write.hpp
Deleted complete I/O implementations: read() templated function for mutable buffer sequences and string specialization (209 lines); write() templated function for const buffer sequences (94 lines). Both supported cancellation via stop tokens.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Farewell, old read and write so true,
Capy's APIs shall carry you through,
Unique pointers fade to memory's haze,
While corosio adapts to modern ways!

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: removing corosio read/write implementations and migrating to capy equivalents, which is the primary objective.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jan 28, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.39%. Comparing base (a71890b) to head (7d9cd85).
⚠️ Report is 1 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop      #91      +/-   ##
===========================================
- Coverage    81.42%   81.39%   -0.03%     
===========================================
  Files           54       52       -2     
  Lines         4489     4483       -6     
===========================================
- Hits          3655     3649       -6     
  Misses         834      834              

Continue to review full report in Codecov by Sentry.

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

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

@cppalliance-bot

Copy link
Copy Markdown

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

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

2026-01-28 23:13:21 UTC

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@example/client/http_client.cpp`:
- Around line 45-49: The EOF check after the co_await capy::read call is using
capy::error::eof which is wrong; change the comparison to use capy::cond::eof
(i.e., compare ec against capy::cond::eof) so EOF from capy::read on the stream
is treated as a normal condition and only other errors cause throw
boost::system::system_error(ec); locate the check around the capy::read call and
capy::string_dynamic_buffer(&response) and update the conditional accordingly.

In `@example/https-client/https_client.cpp`:
- Around line 47-51: The code checks for EOF using the non-portable
capy::error::eof after calling capy::read on stream (into response); change the
EOF check to use the portable condition code capy::cond::eof (i.e., compare ec
to capy::cond::eof instead of capy::error::eof) so the read error handling in
the co_await capy::read(...) block follows the recommended pattern.
🧹 Nitpick comments (2)
example/client/http_client.cpp (1)

10-22: Add a brief file-level overview block comment after includes.

This file has non-trivial coroutine flow, so add a /* */ overview after the includes to aid maintainers.

Proposed change
 `#include` <string>
 `#include` <string_view>
 
+/*
+ * Overview: connects to a server, sends an HTTP GET request via capy::write,
+ * reads the full response into a string via capy::read until EOF, and prints it.
+ */
+
 namespace corosio = boost::corosio;
 namespace capy = boost::capy;

As per coding guidelines, Files containing non-trivial implementation logic should include a /* */ block comment after the includes that provides a high-level overview of how the implementation works.

example/https-client/https_client.cpp (1)

10-25: Add a brief file-level overview block comment after includes.

This file has non-trivial coroutine/TLS flow, so add a /* */ overview after the includes for maintainers.

Proposed change
 `#include` <string>
 `#include` <string_view>
 
+/*
+ * Overview: establishes a TLS connection, sends an HTTPS GET via capy::write,
+ * reads the full response via capy::read until EOF, and prints it.
+ */
+
 namespace corosio = boost::corosio;
 namespace capy = boost::capy;

As per coding guidelines, Files containing non-trivial implementation logic should include a /* */ block comment after the includes that provides a high-level overview of how the implementation works.

Comment on lines +45 to 49
auto [ec, n] = co_await capy::read(
stream, capy::string_dynamic_buffer(&response));
// EOF is expected when server closes connection
if (ec && ec != capy::error::eof)
throw boost::system::system_error(ec);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find capy header files related to read operations
fd -a 'read\.(hpp|h)' include/

# Also search for error and cond definitions
fd -a 'error\.(hpp|h)' include/ | head -5
fd -a 'cond\.(hpp|h)' include/ | head -5

# Find all files with capy namespace
fd -a '\.(hpp|h)$' include/ | xargs grep -l 'capy::read' | head -5

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Search for EOF error definitions
rg -n 'eof' include/ -t cpp -t hpp --max-count=30

Repository: cppalliance/corosio

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Look for usage patterns in the http_client example
cat -n example/client/http_client.cpp | head -100

Repository: cppalliance/corosio

Length of output: 3554


🏁 Script executed:

#!/bin/bash
# Search for socket read operations and how they handle EOF
rg -n 'socket.*read|read.*socket' example/ -t cpp -A 5 | head -50

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Search for eof in all include files without type restriction
find include -type f | xargs grep -n "eof" 2>/dev/null | head -50

Repository: cppalliance/corosio

Length of output: 541


🏁 Script executed:

#!/bin/bash
# Look for error and cond namespaces/definitions
find include -type f | xargs grep -n "error::eof\|cond::eof" 2>/dev/null

Repository: cppalliance/corosio

Length of output: 456


🏁 Script executed:

#!/bin/bash
# Find capy directory structure
find include -name "capy" -type d
find include -path "*capy*" -name "*.hpp" -o -name "*.h" | head -20

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Look for how EOF is defined
rg "namespace.*error|namespace.*cond" include/ 2>/dev/null
rg "enum.*eof|constexpr.*eof|inline.*eof" include/ 2>/dev/null | head -30

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check socket.hpp context around EOF handling
sed -n '350,370p' include/boost/corosio/socket.hpp

Repository: cppalliance/corosio

Length of output: 765


🏁 Script executed:

#!/bin/bash
# Check io_stream.hpp context around EOF handling
sed -n '40,60p' include/boost/corosio/io_stream.hpp

Repository: cppalliance/corosio

Length of output: 1014


🏁 Script executed:

#!/bin/bash
# Search for any usage of error::eof in the codebase to see if it's used anywhere
rg "error::eof" . --type-list 2>/dev/null | grep -v ".git"

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check if capy::error and capy::cond are different entities
rg "namespace error|namespace cond" include/boost/capy/ 2>/dev/null
find include/boost/capy -name "*.h" -o -name "*.hpp" 2>/dev/null | xargs grep -l "eof" 2>/dev/null

Repository: cppalliance/corosio

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Check the read operation in capy to understand its return error codes
find include/boost/capy -type f | xargs grep -B 5 -A 10 "read(" 2>/dev/null | head -80

Repository: cppalliance/corosio

Length of output: 116


🏁 Script executed:

#!/bin/bash
# Verify that capy::error::eof does not exist or is not the right category
rg "error::" include/boost/capy -A 2 -B 2 2>/dev/null | head -40

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Check the overall include structure
ls -la include/boost/ | head -20
find include -type d | head -20

Repository: cppalliance/corosio

Length of output: 413


🏁 Script executed:

#!/bin/bash
# Find where capy might be located
rg "namespace capy|include.*capy" include/ | head -20

Repository: cppalliance/corosio

Length of output: 1576


🏁 Script executed:

#!/bin/bash
# Check if capy is a submodule or external dependency
cat .gitmodules 2>/dev/null || echo "No gitmodules file"
ls -la | grep -i submodule

Repository: cppalliance/corosio

Length of output: 81


🏁 Script executed:

#!/bin/bash
# Look for any other usage of capy::error in the codebase to understand error handling patterns
rg "capy::error" include/boost/corosio --type-list 2>/dev/null || rg "capy::error" include/boost/corosio -A 2 -B 2

Repository: cppalliance/corosio

Length of output: 3181


🏁 Script executed:

#!/bin/bash
# Double-check the http_client.cpp to see if the error is really error::eof
sed -n '40,55p' example/client/http_client.cpp | cat -n

Repository: cppalliance/corosio

Length of output: 724


Use capy::cond::eof for EOF comparison instead of capy::error::eof.

The socket documentation specifies that read operations signal EOF via capy::cond::eof, not capy::error::eof. The current check using capy::error::eof will incorrectly treat EOF as an error condition.

Recommended fix
-    if (ec && ec != capy::error::eof)
+    if (ec && ec != capy::cond::eof)
         throw boost::system::system_error(ec);
🧰 Tools
🪛 Cppcheck (2.19.0)

[error] 49-49: Found an exit path from function with non-void return type that has missing return statement

(missingReturn)

🤖 Prompt for AI Agents
In `@example/client/http_client.cpp` around lines 45 - 49, The EOF check after the
co_await capy::read call is using capy::error::eof which is wrong; change the
comparison to use capy::cond::eof (i.e., compare ec against capy::cond::eof) so
EOF from capy::read on the stream is treated as a normal condition and only
other errors cause throw boost::system::system_error(ec); locate the check
around the capy::read call and capy::string_dynamic_buffer(&response) and update
the conditional accordingly.

Comment on lines +47 to 51
auto [ec, n] = co_await capy::read(
stream, capy::string_dynamic_buffer(&response));
// EOF is expected when server closes connection
if (ec && ec != capy::error::eof)
throw boost::system::system_error(ec);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find capy error/cond definitions
find . -type f -name "*.hpp" -o -name "*.h" | xargs grep -l "cond::eof\|error::eof" 2>/dev/null | head -20

Repository: cppalliance/corosio

Length of output: 329


🏁 Script executed:

#!/bin/bash
# Search for capy includes and read function
find . -type f \( -name "*.hpp" -o -name "*.h" \) | xargs grep -l "capy::" | head -20

Repository: cppalliance/corosio

Length of output: 890


🏁 Script executed:

#!/bin/bash
# Look at the actual file to understand context
cat -n example/https-client/https_client.cpp | sed -n '40,60p'

Repository: cppalliance/corosio

Length of output: 894


🏁 Script executed:

#!/bin/bash
# Search for capy namespace definitions and error codes
rg -n "namespace capy|cond::eof|error::eof" --type-list

Repository: cppalliance/corosio

Length of output: 452


🏁 Script executed:

#!/bin/bash
# Find all files in include/boost with capy or similar structures
fd -t f "\.hpp$|\.h$" . | grep -i capy | head -20

Repository: cppalliance/corosio

Length of output: 45


🏁 Script executed:

#!/bin/bash
# Search for error::eof and cond::eof definitions
rg -n "error::eof|cond::eof" include/ --type cpp --type hpp

Repository: cppalliance/corosio

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Look for capy namespace definition
rg -n "namespace capy" include/ --type cpp --type hpp

Repository: cppalliance/corosio

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Check the io_stream header for read function
cat -n include/boost/corosio/io_stream.hpp | head -150

Repository: cppalliance/corosio

Length of output: 6267


🏁 Script executed:

#!/bin/bash
# Look for error code definitions
rg -n "enum.*eof|error.*eof|cond.*eof" include/ --type cpp --type hpp

Repository: cppalliance/corosio

Length of output: 90


🏁 Script executed:

#!/bin/bash
# Search for all uses of capy::read in the codebase
rg -n "capy::read" . --type-list cpp

Repository: cppalliance/corosio

Length of output: 452


🏁 Script executed:

#!/bin/bash
# Remove the --type flag and just search
rg -n "capy::read"

Repository: cppalliance/corosio

Length of output: 1000


🏁 Script executed:

#!/bin/bash
# Search for capy::error references
rg -n "capy::error::eof|capy::cond::eof" .

Repository: cppalliance/corosio

Length of output: 3834


🏁 Script executed:

#!/bin/bash
# Look for the capy library error definitions
rg -n "cond::" include/boost/corosio/ | head -30

Repository: cppalliance/corosio

Length of output: 1591


🏁 Script executed:

#!/bin/bash
# Check if there's a capy documentation or error_code header
find . -name "*.hpp" -o -name "*.h" | xargs grep -l "cond::eof" 2>/dev/null

Repository: cppalliance/corosio

Length of output: 166


🏁 Script executed:

#!/bin/bash
# Look at socket.hpp around line 356 for shutdown documentation
cat -n include/boost/corosio/socket.hpp | sed -n '340,380p'

Repository: cppalliance/corosio

Length of output: 2000


🏁 Script executed:

#!/bin/bash
# Check test/unit/socket.cpp to see how EOF is tested in different contexts
cat -n test/unit/socket.cpp | sed -n '850,860p'

Repository: cppalliance/corosio

Length of output: 579


🏁 Script executed:

#!/bin/bash
# Check the test at line 891 to see the context
cat -n test/unit/socket.cpp | sed -n '885,895p'

Repository: cppalliance/corosio

Length of output: 519


🏁 Script executed:

#!/bin/bash
# Look at the capy library integration or error code definitions
rg -n "error::eof|cond::eof" include/boost/corosio/socket.hpp -A 3 -B 3

Repository: cppalliance/corosio

Length of output: 553


Use the portable EOF condition code.

The documented pattern for checking EOF after read operations is capy::cond::eof, not capy::error::eof. The socket and io_stream headers explicitly recommend using the portable condition code:

-    if (ec && ec != capy::error::eof)
+    if (ec && ec != capy::cond::eof)
         throw boost::system::system_error(ec);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
auto [ec, n] = co_await capy::read(
stream, capy::string_dynamic_buffer(&response));
// EOF is expected when server closes connection
if (ec && ec != capy::error::eof)
throw boost::system::system_error(ec);
auto [ec, n] = co_await capy::read(
stream, capy::string_dynamic_buffer(&response));
// EOF is expected when server closes connection
if (ec && ec != capy::cond::eof)
throw boost::system::system_error(ec);
🧰 Tools
🪛 Cppcheck (2.19.0)

[error] 51-51: Found an exit path from function with non-void return type that has missing return statement

(missingReturn)

🤖 Prompt for AI Agents
In `@example/https-client/https_client.cpp` around lines 47 - 51, The code checks
for EOF using the non-portable capy::error::eof after calling capy::read on
stream (into response); change the EOF check to use the portable condition code
capy::cond::eof (i.e., compare ec to capy::cond::eof instead of
capy::error::eof) so the read error handling in the co_await capy::read(...)
block follows the recommended pattern.

@sgerbino sgerbino merged commit c0b30ef into cppalliance:develop Jan 29, 2026
46 of 48 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Beast2 Jan 29, 2026
@sgerbino sgerbino deleted the pr/clean-project branch January 29, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants