1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
// This file is part of CAF, the C++ Actor Framework. See the file LICENSE in
// the main distribution directory for license terms and copyright or visit
// https://github.com/actor-framework/actor-framework/blob/master/LICENSE.
#pragma once
#include <vector>
#include "caf/detail/core_export.hpp"
#include "caf/detail/implicit_conversions.hpp"
#include "caf/detail/message_builder_element.hpp"
#include "caf/detail/padded_size.hpp"
#include "caf/detail/type_id_list_builder.hpp"
#include "caf/fwd.hpp"
#include "caf/message.hpp"
namespace caf {
/// Provides a convenient interface for creating `message` objects
/// from a series of values using the member function `append`.
class CAF_CORE_EXPORT message_builder {
public:
friend class message;
message_builder() = default;
message_builder(const message_builder&) = delete;
message_builder& operator=(const message_builder&) = delete;
/// Creates a new instance and immediately calls `append(first, last)`.
template <class Iter>
message_builder(Iter first, Iter last) {
append(first, last);
}
/// Appends all values in range [first, last).
template <class Iter>
message_builder& append(Iter first, Iter last) {
for (; first != last; ++first)
append(*first);
return *this;
}
/// Adds `x` to the elements of the buffer.
template <class T>
message_builder& append(T&& x) {
using value_type = detail::strip_and_convert_t<T>;
static_assert(detail::sendable<value_type>);
using wrapper_type = detail::message_builder_element_impl<value_type>;
storage_size_ += detail::padded_size_v<value_type>;
types_.push_back(type_id_v<value_type>);
elements_.emplace_back(std::make_unique<wrapper_type>(std::forward<T>(x)));
return *this;
}
/// Adds elements `n` elements from `msg` to the buffer, starting at index
/// `first`.
/// @note Always appends *copies* of the elements.
message_builder& append_from(const caf::message& msg, size_t first,
size_t n = 1);
template <class... Ts>
message_builder& append_all(Ts&&... xs) {
(append(std::forward<Ts>(xs)), ...);
return *this;
}
template <class Tuple, size_t... Is>
message_builder& append_tuple(Tuple& xs, std::index_sequence<Is...>) {
(append(std::get<Is>(xs)), ...);
return *this;
}
template <class... Ts>
message_builder& append_tuple(std::tuple<Ts...> xs) {
return append_tuple(std::integral_constant<size_t, 0>{},
std::integral_constant<size_t, sizeof...(Ts)>{}, xs);
}
/// Converts the buffer to an actual message object without
/// invalidating this message builder (nor clearing it).
message to_message() const;
/// Converts the buffer to an actual message object and transfers
/// ownership of the data to it, leaving this object in an invalid state.
/// @warning Calling *any* member function on this object afterwards
/// is undefined behavior.
message move_to_message();
/// Removes all elements from the buffer.
void clear() noexcept;
/// Returns whether the buffer is empty.
bool empty() const noexcept {
return elements_.empty();
}
/// Returns the number of elements in the buffer.
size_t size() const noexcept {
return elements_.size();
}
private:
size_t storage_size_ = 0;
detail::type_id_list_builder types_;
std::vector<detail::message_builder_element_ptr> elements_;
};
} // namespace caf
|