diff --git a/include/boost/capy/read_until.hpp b/include/boost/capy/read_until.hpp index ab9965580..4a0e39313 100644 --- a/include/boost/capy/read_until.hpp +++ b/include/boost/capy/read_until.hpp @@ -180,7 +180,7 @@ struct read_until_awaitable await_suspend(std::coroutine_handle<> h, io_env const* env) { inner_.emplace(read_until_match_impl( - *stream_, buffers(), match_, initial_amount_)); + *stream_, buffers(), std::move(match_), initial_amount_)); return inner_->await_suspend(h, env); } diff --git a/test/unit/read_until.cpp b/test/unit/read_until.cpp index 56e87c6a9..8c70212e8 100644 --- a/test/unit/read_until.cpp +++ b/test/unit/read_until.cpp @@ -19,9 +19,11 @@ #include "test_suite.hpp" #include +#include #include #include #include +#include namespace boost { namespace capy { @@ -451,6 +453,52 @@ struct read_until_test })); } + void + testMoveOnlyMatcher() + { + struct move_only_matcher + { + std::unique_ptr delim; + + explicit move_only_matcher(std::string d) + : delim(std::make_unique(std::move(d))) + { + } + + std::size_t + operator()( + std::string_view data, + std::size_t* hint) const + { + auto pos = data.find(*delim); + if(pos != std::string_view::npos) + return pos + delim->size(); + if(hint) + *hint = delim->size() > 1 ? delim->size() - 1 : 0; + return std::string_view::npos; + } + }; + + static_assert(MatchCondition); + static_assert(! std::is_copy_constructible_v); + + // Chunked reads route the matcher through await_suspend, which + // moves rather than copies it. + BOOST_TEST(test::fuse().armed([](test::fuse& f) -> task + { + test::read_stream rs(f, 4); + rs.provide("hello\r\nworld"); + + std::string data; + auto [ec, n] = co_await read_until( + rs, dynamic_buffer(data), move_only_matcher("\r\n")); + if(ec) + co_return; + + BOOST_TEST_EQ(n, 7u); // "hello\r\n" + })); + } + //---------------------------------------------------------- void @@ -486,6 +534,7 @@ struct read_until_test testErrorConditions(); testPrefilledBuffer(); testMatchCondition(); + testMoveOnlyMatcher(); testMatchHelpers(); } };