100.00% Lines (2/2) 100.00% Functions (1/1)
TLA Baseline Branch
Line Hits Code Line Hits 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 + @par Parameters
  52 + @li `seq` The underlying buffer sequence. Must outlive the
  53 + returned slice and any `data()` view obtained from it.
  54 + @li `offset` Number of bytes to skip from the start of `seq`.
  55 + Clamped to `buffer_size(seq)`.
  56 + @li `length` Maximum number of bytes the slice will expose,
  57 + starting at `offset`. Clamped to `buffer_size(seq) - offset`.
  58 + Defaults to the maximum value of `std::size_t`, i.e. "to end".
  59 +
  60 + @par Example
  61 + @code
  62 + template< ReadStream Stream, MutableBufferSequence MB >
  63 + task< io_result< std::size_t > >
  64 + read_all( Stream& stream, MB buffers )
  65 + {
  66 + auto s = buffer_slice( buffers );
  67 + std::size_t const total_size = buffer_size( buffers );
  68 + std::size_t total = 0;
  69 + while( total < total_size )
  70 + {
  71 + auto [ec, n] = co_await stream.read_some( s.data() );
  72 + s.remove_prefix( n );
  73 + total += n;
  74 + if( ec )
  75 + co_return {ec, total};
  76 + }
  77 + co_return {{}, total};
  78 + }
  79 + @endcode
  80 +
  81 + @see Slice, MutableSlice
  82 + */
  83 + template<class BufferSequence>
  84 + requires MutableBufferSequence<BufferSequence>
  85 + || ConstBufferSequence<BufferSequence>
  86 + auto
HITGNC   87 + 4369 buffer_slice(
  88 + BufferSequence const& seq,
  89 + std::size_t offset = 0,
  90 + std::size_t length =
  91 + (std::numeric_limits<std::size_t>::max)()) noexcept
  92 + {
HITGNC   93 + 4369 return detail::slice_impl<BufferSequence>(seq, offset, length);
  94 + }
  95 +
  96 + /** Deleted overload that rejects rvalue arguments at compile time.
  97 +
  98 + Because the returned slice's validity depends on the underlying
  99 + buffer sequence remaining alive, calling `buffer_slice` with a
  100 + temporary buffer sequence would produce an immediately dangling
  101 + slice. This overload makes such calls ill-formed, surfacing the
  102 + lifetime error at compile time rather than as runtime UB.
  103 +
  104 + To slice a buffer sequence produced as a temporary, hoist it
  105 + into a named variable first:
  106 +
  107 + @code
  108 + auto bufs = some_dynamic_buffer.data(); // named, lives in scope
  109 + auto s = buffer_slice( bufs ); // OK
  110 + @endcode
  111 + */
  112 + template<class BufferSequence>
  113 + requires MutableBufferSequence<BufferSequence>
  114 + || ConstBufferSequence<BufferSequence>
  115 + auto
  116 + buffer_slice(
  117 + BufferSequence const&& seq,
  118 + std::size_t offset = 0,
  119 + std::size_t length =
  120 + (std::numeric_limits<std::size_t>::max)()) = delete;
  121 +
  122 + } // namespace capy
  123 + } // namespace boost
  124 +
  125 + #endif