streambuf::data() returns a buffer sequence. So you can't be guaranteed to have string_view to map its full capacity, in general.
The basic_streambuf class is derived from std::streambuf to associate the streambuf's input and output sequences with one or more character arrays.
However, the docs go on to mention
The basic_streambuf class's public interface is intended to permit
the following implementation strategies:
- A single contiguous character array, which is reallocated as necessary to accommodate changes in the size of the character
sequence. This is the implementation approach currently used in
Asio.
- A sequence of one or more character arrays, where each array is of the same size. Additional character array objects are appended to the
sequence to accommodate changes in the size of the character sequence.
- A sequence of one or more character arrays of varying sizes. Additional character array objects are appended to the sequence to
accommodate changes in the size of the character sequence.
(highlighting added)
So, iff you asserted your assumption then you might get away with this for now:
assert(1 == buf_.data().size());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
However, once you use std::istream on the streambuf object, it will perform calls to basic_stream_buf::consume(), which doesn't explicitly document that it will not reallocate.
However, the DynamicBuffer_v1 concept that this models documents:
| x.consume(n) |
|
Removes n bytes from beginning of the input sequence. If n is greater than the size of the input sequence, the entire input sequence is removed. All constant or mutable buffer sequences previously obtained using data() or prepare() are invalidated. |
So, in order to follow library patterns, it seems best not depend on the string_view to stay valid after reading from the istream.
Note also that it would be best to limit scopes of the istream/ostream object:
boost::asio::streambuf buf_;
{
std::ostream out(&buf_);
int a = 1488;
out << a;
out << 33;
out << 100005l;
}
assert(1 == buf_.data().size());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
{
std::istream in(&buf_);
int g;
in >> g;
}
Or even:
int const a = 1488;
boost::asio::streambuf buf_;
std::ostream(&buf_) << a << 33 << 100005l;
assert(1 == buf_.data().size());
auto first = *buf_.data().begin();
std::basic_string_view<uint8_t> arr_( //
buffer_cast<const uint8_t*>(first), //
first.size());
int g;
std::istream(&buf_) >> g;