include/boost/capy/buffers/buffer_slice.hpp

100.0% Lines (2/2) 100.0% List of functions (2/3)
buffer_slice.hpp
f(x) Functions (3)
Line TLA Hits Source Code
1 //
2 // Copyright (c) 2026 Michael Vandeberg
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_BUFFERS_BUFFER_SLICE_HPP
11 #define BOOST_CAPY_BUFFERS_BUFFER_SLICE_HPP
12
13 #include <boost/capy/detail/config.hpp>
14 #include <boost/capy/buffers.hpp>
15 #include <boost/capy/detail/slice_impl.hpp>
16
17 #include <cstddef>
18 #include <limits>
19
20 namespace boost {
21 namespace capy {
22
23 /** Return a byte-range slice of a buffer sequence.
24
25 Constructs a view over a contiguous byte range of `seq`. The
26 slice exposes its current bytes via `data()` (a buffer sequence)
27 and supports incremental consumption via `remove_prefix(n)`.
28
29 @par Return Value
30 An object of unspecified type satisfying the @ref Slice concept.
31 Bind with `auto` and operate through the concept's members. When
32 `seq` models @ref MutableBufferSequence, the returned object
33 additionally models @ref MutableSlice.
34
35 @par Lifetime
36 The returned slice is associated with `seq` as its underlying
37 buffer sequence. `seq` — and the memory referenced by its buffer
38 descriptors — must remain valid for as long as the slice, or
39 any buffer sequence obtained from its `data()`, is in use.
40 Passing a temporary buffer sequence to `buffer_slice` produces
41 a dangling slice.
42
43 The buffer sequence returned by `data()` is independent of the
44 slice object: subsequent operations on the slice (mutation,
45 copy, move, destruction) do not invalidate an already-obtained
46 `data()` view. It remains valid for as long as `seq` is valid.
47
48 Iterators and buffer descriptors obtained through `data()`
49 follow the same invalidation rules as those of `seq`.
50
51 @param seq The underlying buffer sequence. Must outlive the
52 returned slice and any `data()` view obtained from it.
53
54 @param offset Number of bytes to skip from the start of `seq`.
55 Clamped to `buffer_size(seq)`.
56
57 @param length Maximum number of bytes the slice will expose,
58 starting at `offset`. Clamped to `buffer_size(seq) - offset`.
59 Defaults to the maximum value of `std::size_t`, i.e. "to end".
60
61 @par Example
62 @code
63 template< ReadStream Stream, MutableBufferSequence MB >
64 task< io_result< std::size_t > >
65 read_all( Stream& stream, MB buffers )
66 {
67 auto s = buffer_slice( buffers );
68 std::size_t const total_size = buffer_size( buffers );
69 std::size_t total = 0;
70 while( total < total_size )
71 {
72 auto [ec, n] = co_await stream.read_some( s.data() );
73 s.remove_prefix( n );
74 total += n;
75 if( ec )
76 co_return {ec, total};
77 }
78 co_return {{}, total};
79 }
80 @endcode
81
82 @see Slice, MutableSlice
83 */
84 template<class BufferSequence>
85 requires MutableBufferSequence<BufferSequence>
86 || ConstBufferSequence<BufferSequence>
87 auto
88 4370x buffer_slice(
89 BufferSequence const& seq,
90 std::size_t offset = 0,
91 std::size_t length =
92 (std::numeric_limits<std::size_t>::max)()) noexcept
93 {
94 4370x return detail::slice_impl<BufferSequence>(seq, offset, length);
95 }
96
97 /** Deleted overload that rejects rvalue arguments at compile time.
98
99 Because the returned slice's validity depends on the underlying
100 buffer sequence remaining alive, calling `buffer_slice` with a
101 temporary buffer sequence would produce an immediately dangling
102 slice. This overload makes such calls ill-formed, surfacing the
103 lifetime error at compile time rather than as runtime UB.
104
105 To slice a buffer sequence produced as a temporary, hoist it
106 into a named variable first:
107
108 @code
109 auto bufs = some_dynamic_buffer.data(); // named, lives in scope
110 auto s = buffer_slice( bufs ); // OK
111 @endcode
112
113 @param seq An rvalue buffer sequence (`const&&`). Binding the
114 slice to a temporary would dangle, so this overload is
115 deleted to reject such calls at compile time.
116
117 @param offset Number of bytes to skip from the start of `seq`.
118
119 @param length Maximum number of bytes the slice would expose,
120 starting at `offset`.
121 */
122 template<class BufferSequence>
123 requires MutableBufferSequence<BufferSequence>
124 || ConstBufferSequence<BufferSequence>
125 auto
126 buffer_slice(
127 BufferSequence const&& seq,
128 std::size_t offset = 0,
129 std::size_t length =
130 (std::numeric_limits<std::size_t>::max)()) = delete;
131
132 } // namespace capy
133 } // namespace boost
134
135 #endif
136