include/boost/capy/asio/buffers.hpp

100.0% Lines (29/29) 96.4% List of functions (27/28)
buffers.hpp
f(x) Functions (28)
Function Calls Lines Blocks
boost::capy::asio_const_buffer::asio_const_buffer(boost::capy::const_buffer) :62 2x 100.0% 100.0% boost::capy::asio_mutable_buffer::asio_mutable_buffer(boost::capy::mutable_buffer) :99 2x 100.0% 100.0% boost::capy::detail::asio_buffer_transformer_t::operator()(boost::capy::mutable_buffer const&) const :137 2x 100.0% 100.0% boost::capy::detail::asio_buffer_transformer_t::operator()(boost::capy::const_buffer const&) const :142 2x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::const_buffer const*, std::span<boost::capy::const_buffer const, 18446744073709551615ul> > >::asio_buffer_iterator(__gnu_cxx::__normal_iterator<boost::capy::const_buffer const*, std::span<boost::capy::const_buffer const, 18446744073709551615ul> >) :175 4x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer const*, std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> > >::asio_buffer_iterator(__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer const*, std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> >) :175 4x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::const_buffer const*>::asio_buffer_iterator(boost::asio::const_buffer const*) :175 6x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::mutable_buffer const*>::asio_buffer_iterator(boost::asio::mutable_buffer const*) :175 6x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::const_buffer const*, std::span<boost::capy::const_buffer const, 18446744073709551615ul> > >::operator*() const :186 2x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer const*, std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> > >::operator*() const :186 2x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::const_buffer const*>::operator*() const :186 3x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::mutable_buffer const*>::operator*() const :186 3x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::const_buffer const*, std::span<boost::capy::const_buffer const, 18446744073709551615ul> > >::operator++() :192 1x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer const*, std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> > >::operator++() :192 1x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::const_buffer const*>::operator++() :192 2x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::mutable_buffer const*>::operator++() :192 0 0.0% 0.0% boost::capy::detail::asio_buffer_iterator<boost::asio::const_buffer const*>::operator++(int) :199 1x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::mutable_buffer const*>::operator++(int) :199 2x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::const_buffer const*, std::span<boost::capy::const_buffer const, 18446744073709551615ul> > >::operator!=(boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::const_buffer const*, std::span<boost::capy::const_buffer const, 18446744073709551615ul> > > const&) const :228 3x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer const*, std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> > >::operator!=(boost::capy::detail::asio_buffer_iterator<__gnu_cxx::__normal_iterator<boost::capy::mutable_buffer const*, std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> > > const&) const :228 3x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::const_buffer const*>::operator!=(boost::capy::detail::asio_buffer_iterator<boost::asio::const_buffer const*> const&) const :228 4x 100.0% 100.0% boost::capy::detail::asio_buffer_iterator<boost::asio::mutable_buffer const*>::operator!=(boost::capy::detail::asio_buffer_iterator<boost::asio::mutable_buffer const*> const&) const :228 3x 100.0% 100.0% boost::capy::detail::asio_buffer_range<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >::asio_buffer_range(std::span<boost::capy::const_buffer const, 18446744073709551615ul>) :268 1x 100.0% 100.0% boost::capy::detail::asio_buffer_range<std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> >::asio_buffer_range(std::span<boost::capy::mutable_buffer const, 18446744073709551615ul>) :268 1x 100.0% 100.0% boost::capy::detail::asio_buffer_range<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >::begin() const :279 2x 100.0% 100.0% boost::capy::detail::asio_buffer_range<std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> >::begin() const :279 2x 100.0% 100.0% boost::capy::detail::asio_buffer_range<std::span<boost::capy::const_buffer const, 18446744073709551615ul> >::end() const :285 2x 100.0% 100.0% boost::capy::detail::asio_buffer_range<std::span<boost::capy::mutable_buffer const, 18446744073709551615ul> >::end() const :285 2x 100.0% 100.0%
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.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_ASIO_BUFFERS_HPP
11 #define BOOST_CAPY_ASIO_BUFFERS_HPP
12
13 #include <boost/capy/buffers.hpp>
14 #include <array>
15 #include <concepts>
16 #include <utility>
17
18 namespace asio
19 {
20
21 class mutable_buffer;
22 class const_buffer;
23
24 }
25
26 namespace boost::asio
27 {
28
29 class mutable_buffer;
30 class const_buffer;
31
32 }
33
34 namespace boost::capy
35 {
36
37 /** A const buffer type compatible with both capy and Asio.
38
39 Extends capy's `const_buffer` with implicit conversion operators
40 to both standalone Asio (`::asio::const_buffer`) and Boost.Asio
41 (`boost::asio::const_buffer`) buffer types.
42
43 This allows seamless use of capy buffers with Asio I/O operations
44 without explicit conversion.
45
46 @par Example
47 @code
48 capy::asio_const_buffer buf(data, size);
49
50 // Works directly with Asio operations
51 co_await socket.async_write_some(buf, capy::as_io_awaitable);
52 @endcode
53
54 @see asio_mutable_buffer, as_asio_buffer_sequence
55 */
56 struct asio_const_buffer : const_buffer
57 {
58 using const_buffer::const_buffer;
59 using const_buffer::operator=;
60
61 /// Construct from a capy const_buffer.
62 2x asio_const_buffer(const_buffer cb) : const_buffer(cb) {}
63
64 /// Convert to standalone Asio const_buffer.
65 inline
66 operator ::asio::const_buffer() const;
67
68 /// Convert to Boost.Asio const_buffer.
69 inline
70 operator boost::asio::const_buffer() const;
71 };
72
73 /** A mutable buffer type compatible with both capy and Asio.
74
75 Extends capy's `mutable_buffer` with implicit conversion operators
76 to both standalone Asio and Boost.Asio buffer types. Supports
77 conversion to both mutable and const buffer types.
78
79 This allows seamless use of capy buffers with Asio I/O operations
80 without explicit conversion.
81
82 @par Example
83 @code
84 char data[1024];
85 capy::asio_mutable_buffer buf(data, sizeof(data));
86
87 // Works directly with Asio read operations
88 auto [ec, n] = co_await socket.async_read_some(buf, capy::as_io_awaitable);
89 @endcode
90
91 @see asio_const_buffer, as_asio_buffer_sequence
92 */
93 struct asio_mutable_buffer : mutable_buffer
94 {
95 using mutable_buffer::mutable_buffer;
96 using mutable_buffer::operator=;
97
98 /// Construct from a capy mutable_buffer.
99 2x asio_mutable_buffer(mutable_buffer mb) : mutable_buffer(mb) {}
100
101 /// Convert to standalone Asio mutable_buffer.
102 inline
103 operator ::asio::mutable_buffer() const;
104
105 /// Convert to Boost.Asio mutable_buffer.
106 inline
107 operator boost::asio::mutable_buffer() const;
108
109 /// Convert to standalone Asio const_buffer.
110 inline
111 operator ::asio::const_buffer() const;
112
113 /// Convert to Boost.Asio const_buffer.
114 inline
115 operator boost::asio::const_buffer() const;
116 };
117
118
119 namespace detail
120 {
121
122 struct asio_buffer_transformer_t
123 {
124 inline
125 asio_mutable_buffer operator()(const boost::asio::mutable_buffer &mb) const noexcept;
126
127 inline
128 asio_const_buffer operator()(const boost::asio::const_buffer &cb) const noexcept;
129
130 inline
131 asio_mutable_buffer operator()(const ::asio::mutable_buffer &mb) const noexcept;
132
133 inline
134 asio_const_buffer operator()(const ::asio::const_buffer &cb) const noexcept;
135
136
137 2x asio_mutable_buffer operator()(const mutable_buffer &mb) const noexcept
138 {
139 2x return mb;
140 }
141
142 2x asio_const_buffer operator()(const const_buffer &cb) const noexcept
143 {
144 2x return cb;
145 }
146
147 asio_buffer_transformer_t() noexcept = default;
148 asio_buffer_transformer_t(const asio_buffer_transformer_t &) noexcept = default;
149 };
150
151 constexpr static asio_buffer_transformer_t asio_buffer_transformer;
152
153 /** A bidirectional iterator that transforms buffer types using asio_buffer_transformer.
154 *
155 * Wraps an underlying bidirectional iterator and applies asio_buffer_transformer
156 * to each dereferenced value, converting between Asio buffer types and capy
157 * asio_const_buffer/asio_mutable_buffer types.
158 *
159 * @tparam Iterator The underlying bidirectional iterator type
160 */
161 template<typename Iterator>
162 class asio_buffer_iterator
163 {
164 public:
165 using iterator_type = Iterator;
166 using iterator_category = std::bidirectional_iterator_tag;
167 using difference_type = typename std::iterator_traits<Iterator>::difference_type;
168 using underlying_value = typename std::iterator_traits<Iterator>::value_type;
169 using value_type = decltype(asio_buffer_transformer(std::declval<underlying_value>()));
170 using reference = value_type;
171 using pointer = void;
172
173 asio_buffer_iterator() = default;
174
175 20x explicit asio_buffer_iterator(Iterator it)
176 noexcept(std::is_nothrow_move_constructible_v<Iterator>)
177 20x : it_(std::move(it))
178 {
179 20x }
180
181 asio_buffer_iterator(const asio_buffer_iterator&) = default;
182 asio_buffer_iterator(asio_buffer_iterator&&) = default;
183 asio_buffer_iterator& operator=(const asio_buffer_iterator&) = default;
184 asio_buffer_iterator& operator=(asio_buffer_iterator&&) = default;
185
186 10x reference operator*() const
187 noexcept(noexcept(asio_buffer_transformer(*std::declval<Iterator>())))
188 {
189 10x return asio_buffer_transformer(*it_);
190 }
191
192 4x asio_buffer_iterator& operator++()
193 noexcept(noexcept(++std::declval<Iterator&>()))
194 {
195 4x ++it_;
196 4x return *this;
197 }
198
199 3x asio_buffer_iterator operator++(int)
200 noexcept(noexcept(std::declval<Iterator&>()++))
201 {
202 3x asio_buffer_iterator tmp(*this);
203 3x ++it_;
204 3x return tmp;
205 }
206
207 asio_buffer_iterator& operator--()
208 noexcept(noexcept(--std::declval<Iterator&>()))
209 {
210 --it_;
211 return *this;
212 }
213
214 asio_buffer_iterator operator--(int)
215 noexcept(noexcept(std::declval<Iterator&>()--))
216 {
217 asio_buffer_iterator tmp(*this);
218 --it_;
219 return tmp;
220 }
221
222 bool operator==(const asio_buffer_iterator& other) const
223 noexcept(noexcept(std::declval<Iterator>() == std::declval<Iterator>()))
224 {
225 return it_ == other.it_;
226 }
227
228 13x bool operator!=(const asio_buffer_iterator& other) const
229 noexcept(noexcept(std::declval<Iterator>() != std::declval<Iterator>()))
230 {
231 13x return it_ != other.it_;
232 }
233
234 /// Returns the underlying iterator.
235 Iterator base() const noexcept(std::is_nothrow_copy_constructible_v<Iterator>)
236 {
237 return it_;
238 }
239
240 private:
241 Iterator it_{};
242 };
243
244 // Deduction guide
245 template<typename Iterator>
246 asio_buffer_iterator(Iterator) -> asio_buffer_iterator<Iterator>;
247
248
249 /** A bidirectional range that transforms buffer sequences using asio_buffer_transformer.
250 *
251 * Wraps a buffer sequence and provides begin/end iterators that transform
252 * buffer elements via asio_buffer_transformer. Satisfies the requirements
253 * of std::ranges::bidirectional_range.
254 *
255 * @tparam Sequence The underlying buffer sequence type
256 */
257 template<typename Sequence>
258 class asio_buffer_range
259 {
260 public:
261 using sequence_type = Sequence;
262 using iterator = asio_buffer_iterator<
263 decltype(std::ranges::begin(std::declval<const Sequence&>()))>;
264 using const_iterator = iterator;
265
266 asio_buffer_range() = default;
267
268 2x explicit asio_buffer_range(Sequence seq)
269 noexcept(std::is_nothrow_move_constructible_v<Sequence>)
270 2x : seq_(std::move(seq))
271 {
272 2x }
273
274 asio_buffer_range(const asio_buffer_range&) = default;
275 asio_buffer_range(asio_buffer_range&&) = default;
276 asio_buffer_range& operator=(const asio_buffer_range&) = default;
277 asio_buffer_range& operator=(asio_buffer_range&&) = default;
278
279 4x iterator begin() const
280 noexcept(noexcept(std::ranges::begin(std::declval<const Sequence&>())))
281 {
282 4x return iterator(std::ranges::begin(seq_));
283 }
284
285 4x iterator end() const
286 noexcept(noexcept(std::ranges::end(std::declval<const Sequence&>())))
287 {
288 4x return iterator(std::ranges::end(seq_));
289 }
290
291 /// Returns true if the range is empty.
292 bool empty() const
293 noexcept(noexcept(std::ranges::empty(std::declval<const Sequence&>())))
294 {
295 return std::ranges::empty(seq_);
296 }
297
298 /// Returns the underlying sequence.
299 const Sequence& base() const noexcept { return seq_; }
300
301 private:
302 Sequence seq_{};
303 };
304
305 // Deduction guide
306 template<typename Sequence>
307 asio_buffer_range(Sequence) -> asio_buffer_range<Sequence>;
308
309 }
310
311
312 /** @defgroup as_asio_buffer_sequence as_asio_buffer_sequence
313
314 Bidirectional conversion between Asio and capy buffer sequences.
315
316 The `as_asio_buffer_sequence` function provides seamless conversion
317 in both directions:
318
319 - **Capy to Asio**: Convert capy buffer sequences for use with Asio
320 I/O operations. The returned range satisfies Asio's
321 `MutableBufferSequence` or `ConstBufferSequence` requirements.
322
323 - **Asio to Capy**: Convert Asio buffer sequences for use with capy's
324 buffer concepts. The returned range satisfies capy's
325 `MutableBufferSequence` or `ConstBufferSequence` concepts.
326
327 @par Example: Capy to Asio
328 @code
329 capy::mutable_buffer_pair buffers = ...;
330 auto seq = capy::as_asio_buffer_sequence(buffers);
331 co_await socket.async_read_some(seq, capy::as_io_awaitable);
332 @endcode
333
334 @par Example: Asio to Capy
335 @code
336 std::vector<boost::asio::mutable_buffer> asio_bufs = ...;
337 auto seq = capy::as_asio_buffer_sequence(asio_bufs);
338 std::size_t total = capy::buffer_size(seq); // Use capy algorithms
339 @endcode
340
341 @{
342 */
343
344 /** Pass through a range already containing asio_const_buffer elements.
345
346 @param rng A bidirectional range of asio_const_buffer
347 @return The range forwarded unchanged
348 */
349 template<std::ranges::bidirectional_range<> Range>
350 requires std::same_as<std::ranges::range_value_t<Range>, asio_const_buffer>
351 auto as_asio_buffer_sequence(Range && rng)
352 {
353 return std::forward<Range>(rng);
354 }
355
356 /** Pass through a range already containing asio_mutable_buffer elements.
357
358 @param rng A bidirectional range of asio_mutable_buffer
359 @return The range forwarded unchanged
360 */
361 template<std::ranges::bidirectional_range<> Range>
362 requires std::same_as<std::ranges::range_value_t<Range>, asio_mutable_buffer>
363 auto as_asio_buffer_sequence(Range && rng)
364 {
365 return std::forward<Range>(rng);
366 }
367
368 /** Convert a single asio_mutable_buffer to a buffer sequence.
369
370 @param mb The mutable buffer
371 @return A single-element array containing the buffer
372 */
373 inline
374 auto as_asio_buffer_sequence(asio_mutable_buffer mb)
375 {
376 return std::array<asio_mutable_buffer, 1u>{mb};
377 }
378
379 /** Convert a single asio_const_buffer to a buffer sequence.
380
381 @param cb The const buffer
382 @return A single-element array containing the buffer
383 */
384 inline
385 auto as_asio_buffer_sequence(asio_const_buffer cb)
386 {
387 return std::array<asio_const_buffer, 1u>{cb};
388 }
389
390 /** Convert a single capy mutable_buffer to a buffer sequence.
391
392 @param mb The mutable buffer
393 @return A single-element array containing an asio_mutable_buffer
394 */
395 inline
396 auto as_asio_buffer_sequence(mutable_buffer mb)
397 {
398 return std::array<asio_mutable_buffer, 1u>{mb};
399 }
400
401 /** Convert a buffer type that might support both mutable & const buffer
402 to an asio buffer sequence.
403
404 @param buf The const buffer
405 @return A single-element array containing an asio_mutable_buffer
406
407 */
408 template<std::convertible_to<mutable_buffer> Buffer>
409 inline
410 auto as_asio_buffer_sequence(const Buffer & buf)
411 {
412 return as_asio_buffer_sequence(static_cast<mutable_buffer>(buf));
413 }
414
415 /** Convert a single capy const_buffer to a buffer sequence.
416 @param cb The const buffer
417 @return A single-element array containing an asio_const_buffer
418
419 */
420 inline
421 auto as_asio_buffer_sequence(const_buffer cb)
422 {
423 return std::array<asio_const_buffer, 1u>{cb};
424 }
425
426 /** Convert any buffer sequence for bidirectional Asio/capy compatibility.
427
428 Wraps the buffer sequence in a transforming range that converts
429 each buffer element to asio_const_buffer or asio_mutable_buffer.
430 The returned range satisfies both Asio's buffer sequence requirements
431 and capy's buffer sequence concepts.
432
433 This overload handles:
434 - Capy buffer sequences (for use with Asio operations)
435 - Asio buffer sequences (for use with capy concepts/algorithms)
436
437 @param seq The buffer sequence to convert
438 @return A transforming range over the buffer sequence
439 */
440 template<ConstBufferSequence Seq>
441 requires (!std::convertible_to<Seq, const_buffer> && !std::convertible_to<Seq, mutable_buffer>)
442 inline
443 2x auto as_asio_buffer_sequence(const Seq & seq)
444 {
445 2x return detail::asio_buffer_range(seq);
446 }
447
448 /** @} */
449
450 }
451
452
453 #endif // BOOST_CAPY_ASIO_BUFFERS_HPP
454
455