Line data Source code
1 : //
2 : // Copyright (c) 2025 Vinnie Falco (vinnie dot falco at gmail dot com)
3 : //
4 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 : //
7 : // Official repository: https://github.com/cppalliance/capy
8 : //
9 :
10 : #ifndef BOOST_CAPY_ANY_BUFREF_HPP
11 : #define BOOST_CAPY_ANY_BUFREF_HPP
12 :
13 : #include <boost/capy/detail/config.hpp>
14 : #include <boost/capy/buffers.hpp>
15 :
16 : #include <cstddef>
17 :
18 : namespace boost {
19 : namespace capy {
20 :
21 : /** A type-erased buffer sequence I/O parameter.
22 :
23 : This class provides a type-erased interface for iterating
24 : over buffer sequences without knowing the concrete type.
25 : It allows asynchronous operations to efficiently type-erase
26 : the buffer sequence parameter, avoiding the need to
27 : templatize the implementation.
28 :
29 : @par Example
30 : The following shows the minimal form of an awaitable, templated on the
31 : buffer sequence type, with only an `await_suspend` method. The example
32 : demonstrates that you can construct an `any_bufref` in the parameter
33 : list when calling a virtual interface; there is no need to create a
34 : separate variable if not desired.
35 :
36 : @code
37 : template<class Buffers>
38 : struct awaitable
39 : {
40 : Buffers b;
41 :
42 : void await_suspend( std::coroutine_handle<> )
43 : {
44 : my_virtual_engine_submit( any_bufref( b ) );
45 : }
46 : };
47 :
48 : // Example virtual interface accepting any_bufref
49 : void my_virtual_engine_submit( any_bufref p )
50 : {
51 : capy::mutable_buffer temp[8];
52 : std::size_t n = p.copy_to( temp, 8 );
53 : // ... handle the buffers ...
54 : }
55 : @endcode
56 : */
57 : class any_bufref
58 : {
59 : public:
60 : /** Construct from a const buffer sequence.
61 :
62 : @param bs The buffer sequence to adapt.
63 : */
64 : template<ConstBufferSequence BS>
65 : explicit
66 9 : any_bufref(BS const& bs) noexcept
67 9 : : bs_(&bs)
68 9 : , fn_(©_impl<BS>)
69 : {
70 9 : }
71 :
72 : /** Fill an array with buffers from the sequence.
73 :
74 : @param dest Pointer to array of mutable buffer descriptors.
75 : @param n Maximum number of buffers to copy.
76 :
77 : @return The number of buffers actually copied.
78 : */
79 : std::size_t
80 9 : copy_to(
81 : mutable_buffer* dest,
82 : std::size_t n) const noexcept
83 : {
84 9 : return fn_(bs_, dest, n);
85 : }
86 :
87 : private:
88 : template<ConstBufferSequence BS>
89 : static std::size_t
90 9 : copy_impl(
91 : void const* p,
92 : mutable_buffer* dest,
93 : std::size_t n)
94 : {
95 9 : auto const& bs = *static_cast<BS const*>(p);
96 9 : auto it = begin(bs);
97 9 : auto const end_it = end(bs);
98 :
99 9 : std::size_t i = 0;
100 : if constexpr (MutableBufferSequence<BS>)
101 : {
102 5 : for(; it != end_it && i < n; ++it, ++i)
103 3 : dest[i] = *it;
104 : }
105 : else
106 : {
107 22 : for(; it != end_it && i < n; ++it, ++i)
108 : {
109 15 : auto const& buf = *it;
110 30 : dest[i] = mutable_buffer(
111 : const_cast<char*>(
112 15 : static_cast<char const*>(buf.data())),
113 : buf.size());
114 : }
115 : }
116 9 : return i;
117 : }
118 :
119 : using fn_t = std::size_t(*)(void const*,
120 : mutable_buffer*, std::size_t);
121 :
122 : void const* bs_;
123 : fn_t fn_;
124 : };
125 :
126 : } // namespace capy
127 : } // namespace boost
128 :
129 : #endif
|