24#include <seastar/core/sstring.hh>
25#include <seastar/util/variant_utils.hh>
26#include <seastar/util/modules.hh>
36SEASTAR_MODULE_EXPORT_BEGIN
41 void write(
const char*,
size_t size) {
55template<
typename Iterator>
58template<
typename Iterator>
65 using has_with_stream = std::false_type;
68 char* begin() {
return _p; }
70 [[gnu::always_inline]]
71 void skip(
size_t size) {
73 throw std::out_of_range(
"serialization buffer overflow");
79 [[gnu::always_inline]]
82 throw std::out_of_range(
"serialization buffer overflow");
89 [[gnu::always_inline]]
90 void write(
const char* p,
size_t size) {
92 throw std::out_of_range(
"serialization buffer overflow");
94 std::copy_n(p, size, _p);
98 [[gnu::always_inline]]
99 void fill(
char c,
size_t size) {
101 throw std::out_of_range(
"serialization buffer overflow");
103 std::fill_n(_p, size, c);
107 [[gnu::always_inline]]
108 size_t size()
const {
119template<
typename Iterator>
129 template<
typename Func>
131 void for_each_fragment(
size_t size, Func&& func) {
133 throw std::out_of_range(
"serialization buffer overflow");
137 if (!_current.size()) {
138 _current =
simple(
reinterpret_cast<char*
>((*_it).get_write()), (*_it).size());
141 auto this_size = std::min(_current.size(), size);
142 func(_current.write_substream(this_size));
147 : _it(it), _current(bv), _size(size) { }
149 using has_with_stream = std::false_type;
150 using iterator_type = Iterator;
155 : _it(it), _size(size) {
158 void skip(
size_t size) {
159 for_each_fragment(size, [] (
auto) { });
163 throw std::out_of_range(
"serialization buffer overflow");
165 if (_current.size() >= size) {
167 return _current.write_substream(size);
173 void write(
const char* p,
size_t size) {
174 for_each_fragment(size, [&p] (
auto bv) {
175 std::copy_n(p, bv.size(), bv.begin());
179 void fill(
char c,
size_t size) {
180 for_each_fragment(size, [c] (
simple fragment) {
181 std::fill_n(fragment.begin(), fragment.size(), c);
184 size_t size()
const {
194template<
typename Iterator>
201 const bool _is_simple;
208 template<
typename StreamVisitor>
209 [[gnu::always_inline]]
210 decltype(
auto) with_stream(StreamVisitor&& visitor) {
211 if (__builtin_expect(_is_simple,
true)) {
212 return visitor(_simple);
214 return visitor(_fragmented);
217 template<
typename StreamVisitor>
218 [[gnu::always_inline]]
219 decltype(
auto) with_stream(StreamVisitor&& visitor)
const {
220 if (__builtin_expect(_is_simple,
true)) {
221 return visitor(_simple);
223 return visitor(_fragmented);
226 using has_with_stream = std::true_type;
227 using iterator_type = Iterator;
229 : _is_simple(
true), _simple() {}
231 : _is_simple(
true), _simple(std::move(
stream)) {}
233 : _is_simple(
false), _fragmented(std::move(
stream)) {}
235 [[gnu::always_inline]]
242 static_assert(std::is_nothrow_copy_constructible_v<fragmented>,
243 "seastar::memory_output_stream::fragmented should be copy constructible");
244 static_assert(std::is_nothrow_copy_constructible_v<simple>,
245 "seastar::memory_output_stream::simple should be copy constructible");
247 new (&_simple)
simple(other._simple);
253 [[gnu::always_inline]]
256 new (&_simple)
simple(std::move(other._simple));
262 [[gnu::always_inline]]
265 static_assert(std::is_nothrow_copy_constructible_v<memory_output_stream>,
266 "memory_output_stream copy constructor shouldn't throw");
267 if (
this != &other) {
274 [[gnu::always_inline]]
276 if (
this != &other) {
283 [[gnu::always_inline]]
288 _fragmented.~fragmented_type();
292 [[gnu::always_inline]]
293 void skip(
size_t size) {
294 with_stream([size] (
auto&
stream) {
299 [[gnu::always_inline]]
302 return stream.write_substream(size);
306 [[gnu::always_inline]]
307 void write(
const char* p,
size_t size) {
308 with_stream([p, size] (
auto&
stream) {
313 [[gnu::always_inline]]
314 void fill(
char c,
size_t size) {
315 with_stream([c, size] (
auto&
stream) {
320 [[gnu::always_inline]]
321 size_t size()
const {
322 return with_stream([] (
auto&
stream) {
333 const char* _p =
nullptr;
336 using has_with_stream = std::false_type;
340 const char* begin()
const {
return _p; }
342 [[gnu::always_inline]]
343 void skip(
size_t size) {
345 throw std::out_of_range(
"deserialization buffer underflow");
351 [[gnu::always_inline]]
352 simple read_substream(
size_t size) {
354 throw std::out_of_range(
"deserialization buffer underflow");
356 simple substream(_p, size);
361 [[gnu::always_inline]]
362 void read(
char* p,
size_t size) {
364 throw std::out_of_range(
"deserialization buffer underflow");
366 std::copy_n(_p, size, p);
370 template<
typename Output>
371 [[gnu::always_inline]]
372 void copy_to(Output& out)
const {
373 out.write(_p, _size);
376 [[gnu::always_inline]]
377 size_t size()
const {
382template<
typename Iterator>
391 template<
typename Func>
393 void for_each_fragment(
size_t size, Func&& func) {
395 throw std::out_of_range(
"deserialization buffer underflow");
399 if (!_current.size()) {
400 _current =
simple(
reinterpret_cast<const char*
>((*_it).begin()), (*_it).size());
403 auto this_size = std::min(_current.size(), size);
404 func(_current.read_substream(this_size));
409 : _it(it), _current(bv), _size(size) { }
412 using has_with_stream = std::false_type;
413 using iterator_type = Iterator;
415 : _it(it), _size(size) {
418 void skip(
size_t size) {
419 for_each_fragment(size, [] (
auto) { });
423 throw std::out_of_range(
"deserialization buffer underflow");
429 void read(
char* p,
size_t size) {
430 for_each_fragment(size, [&p] (
auto bv) {
431 p = std::copy_n(bv.begin(), bv.size(), p);
434 template<
typename Output>
435 void copy_to(Output& out) {
436 for_each_fragment(_size, [&out] (
auto bv) {
440 size_t size()
const {
444 const char* first_fragment_data()
const {
return _current.begin(); }
445 size_t first_fragment_size()
const {
return _current.size(); }
446 Iterator fragment_iterator()
const {
return _it; }
463template<
typename Iterator>
469 const bool _is_simple;
476 template<
typename StreamVisitor>
477 [[gnu::always_inline]]
478 decltype(
auto) with_stream(StreamVisitor&& visitor) {
479 if (__builtin_expect(_is_simple,
true)) {
480 return visitor(_simple);
482 return visitor(_fragmented);
485 template<
typename StreamVisitor>
486 [[gnu::always_inline]]
487 decltype(
auto) with_stream(StreamVisitor&& visitor)
const {
488 if (__builtin_expect(_is_simple,
true)) {
489 return visitor(_simple);
491 return visitor(_fragmented);
494 using has_with_stream = std::true_type;
495 using iterator_type = Iterator;
497 : _is_simple(
true), _simple(std::move(
stream)) {}
499 : _is_simple(
false), _fragmented(std::move(
stream)) {}
501 [[gnu::always_inline]]
508 static_assert(std::is_nothrow_copy_constructible_v<fragmented>,
509 "seastar::memory_input_stream::fragmented should be copy constructible");
510 static_assert(std::is_nothrow_copy_constructible_v<simple>,
511 "seastar::memory_input_stream::simple should be copy constructible");
513 new (&_simple)
simple(other._simple);
519 [[gnu::always_inline]]
522 new (&_simple)
simple(std::move(other._simple));
528 [[gnu::always_inline]]
531 static_assert(std::is_nothrow_copy_constructible_v<memory_input_stream>,
532 "memory_input_stream copy constructor shouldn't throw");
533 if (
this != &other) {
540 [[gnu::always_inline]]
542 if (
this != &other) {
549 [[gnu::always_inline]]
552 _simple.~simple_memory_input_stream();
554 _fragmented.~fragmented_type();
558 [[gnu::always_inline]]
559 void skip(
size_t size) {
560 with_stream([size] (
auto&
stream) {
565 [[gnu::always_inline]]
568 return stream.read_substream(size);
572 [[gnu::always_inline]]
573 void read(
char* p,
size_t size) {
574 with_stream([p, size] (
auto&
stream) {
579 template<
typename Output>
580 [[gnu::always_inline]]
581 void copy_to(Output& out) {
582 with_stream([&out] (
auto&
stream) {
587 [[gnu::always_inline]]
588 size_t size()
const {
589 return with_stream([] (
auto&
stream) {
594 template<
typename Stream,
typename StreamVisitor>
595 friend decltype(
auto) with_serialized_stream(Stream&
stream, StreamVisitor&& visitor);
598SEASTAR_MODULE_EXPORT_END
604template<
typename Iterator>
605inline fragmented_memory_input_stream<Iterator> fragmented_memory_output_stream<Iterator>::to_input_stream()
const {
606 return fragmented_memory_input_stream<Iterator>(_it, _current.to_input_stream(), _size);
609template<
typename Iterator>
610inline memory_input_stream<Iterator> memory_output_stream<Iterator>::to_input_stream()
const {
612 [] (
const simple_memory_output_stream& ostream) -> memory_input_stream<Iterator> {
613 return ostream.to_input_stream();
615 [] (
const fragmented_memory_output_stream<Iterator>& ostream) -> memory_input_stream<Iterator> {
616 return ostream.to_input_stream();
634SEASTAR_MODULE_EXPORT_BEGIN
635template<
typename Stream,
typename StreamVisitor,
typename = std::enable_if_t<Stream::has_with_stream::value>>
636[[gnu::always_inline]]
637 inline decltype(
auto)
638 with_serialized_stream(Stream& stream, StreamVisitor&& visitor) {
639 return stream.with_stream(std::forward<StreamVisitor>(visitor));
642template<
typename Stream,
typename StreamVisitor,
typename = std::enable_if_t<!Stream::has_with_stream::value>,
typename =
void>
643[[gnu::always_inline]]
644 inline decltype(
auto)
645 with_serialized_stream(Stream& stream, StreamVisitor&& visitor) {
646 return visitor(stream);
649using simple_input_stream = simple_memory_input_stream;
650using simple_output_stream = simple_memory_output_stream;
652SEASTAR_MODULE_EXPORT_END
Definition: simple-stream.hh:120
Definition: simple-stream.hh:38
Definition: simple-stream.hh:195
Definition: simple-stream.hh:61
auto make_visitor(Args &&... args)
Definition: variant_utils.hh:52
Seastar API namespace.
Definition: abort_on_ebadf.hh:26