31#include <flow/error/error.hpp>
32#include <boost/endian.hpp>
33#include <boost/integer.hpp>
47 size_t n_serialization_segments_or_none,
const Split_segments* split_segs)
49 using boost::endian::native_to_little;
50 using flow::error::Runtime_error;
56 =
decltype(std::declval<schema::detail::StructuredMessage::BodySerializationInfo::Reader>()
57 .getSplitSegmentsOrNull()[0]);
62 using split_seg_sz_t = boost::uint_t<std::numeric_limits<split_seg_t>::digits / 2>::exact;
63 static_assert((
sizeof(split_seg_sz_t) * 2) ==
sizeof(split_seg_t),
"Gotta be a bug in the last 2 statements.");
65 assert(err_code &&
"We are not public and are free to decide (and decided) not to have a throwing mode.");
74 auto msg_root = builder->getRoot<schema::detail::StructuredMessage>();
109 const bool inited_already = msg_root.hasAuthHeader();
110 const bool want_internal_else_user_msg = id_or_none == 0;
113 assert((!want_internal_else_user_msg) &&
"Contract is not to try to load internal msg into reused *builder.");
115 auto cur_body_serialization_info = msg_root.getBodySerializationInfo();
116 const size_t cur_n_split_segs = cur_body_serialization_info.hasSplitSegmentsOrNull()
117 ? cur_body_serialization_info.getSplitSegmentsOrNull().size()
119 if (cur_n_split_segs != (split_segs ? split_segs->size() :
size_t{0}))
130 auto capnp_uuid = inited_already ? msg_root.getAuthHeader().getSessionToken()
131 : msg_root.initAuthHeader().initSessionToken();
132 static_assert(std::remove_reference_t<
decltype(session_token)>::static_size() == 2 *
sizeof(uint64_t),
133 "World is broken: UUIDs expected to be 16 bytes!");
136 std::memcpy(&first8, session_token.data(),
sizeof(first8));
137 std::memcpy(&last8, session_token.data() +
sizeof(first8),
sizeof(last8));
138 capnp_uuid.setFirst8(native_to_little(first8));
139 capnp_uuid.setLast8(native_to_little(last8));
141 msg_root.setId(id_or_none);
142 msg_root.setOriginatingMessageIdOrNone(originating_msg_id_or_none);
144 if (want_internal_else_user_msg)
146 assert(internal_msg_builder_or_null &&
"Did not follow contract.");
147 assert((n_serialization_segments_or_none == 0) &&
"Did not follow contract.");
148 assert((!split_segs) &&
"Did not follow contract.");
150 *internal_msg_builder_or_null = msg_root.initInternalMessageBody();
158 assert((!internal_msg_builder_or_null) &&
"Did not follow contract.");
159 assert((n_serialization_segments_or_none != 0)
160 &&
"Did not follow contract: If serializing a user message, you have to have some segs for it.");
162 auto body_serialization_info = inited_already ? msg_root.getBodySerializationInfo()
163 : msg_root.initBodySerializationInfo();
164 body_serialization_info.setNumBodySerializationSegments(n_serialization_segments_or_none);
167 const auto n_split_segs = split_segs->size();
168 assert((n_split_segs != 0) &&
"By convention if no split_segs then pass-in null.");
170 auto split_segs_list = inited_already ? body_serialization_info.getSplitSegmentsOrNull()
171 : body_serialization_info.initSplitSegmentsOrNull(n_split_segs);
172 for (
size_t idx = 0; idx != n_split_segs; ++idx)
174 const auto& split_seg = (*split_segs)[idx];
176 if ((split_seg.m_start_idx > std::numeric_limits<split_seg_sz_t>::max())
178 (split_seg.m_n_cont_subsegs > std::numeric_limits<split_seg_sz_t>::max()))
189 split_segs_list.set(idx,
190 static_cast<split_seg_t
>(split_seg.m_start_idx)
191 | (
static_cast<split_seg_t
>(split_seg.m_n_cont_subsegs)
192 << (4 *
sizeof(split_seg_t))));
200 catch (
const Runtime_error& exc)
Simple utility: a capnp MessageBuilder operating over a single, contiguous, user-supplied area in vir...
@ S_INVALID_ARGUMENT
User called an API with 1 or more arguments against the API spec.
@ S_SERIALIZE_FAILED_SPLIT_ENCODING_TOO_BIG
The combination of serialized structured-message size and large individual leaves (list/blob/string) ...
@ S_SERIALIZE_FAILED_SPLIT_SEGS_TOO_MANY
The serialized structured message consists of so many large individual leaves (list/blob/string),...
Builder< ipc::shm::classic::Pool_arena > Builder
Convenience alias: transport::struc::shm::Builder that works with boost.ipc.shm pools from ipc::shm::...
Sub-module of Flow-IPC module ipc::transport providing transmission of structured messages specifical...
std::vector< Split_segment > Split_segments
A simple data structure describing the segments (if any) in a Segment_bufs (or similar) structure whi...
boost::uuids::uuid Session_token
A type used by struc::Channel for internal safety/security/auth needs.
bool load_mdt(Capped_sz_capnp_message_builder *builder, schema::detail::StructuredMessage::InternalMessageBody::Builder *internal_msg_builder_or_null, Error_code *err_code, const Session_token &session_token, msg_id_t originating_msg_id_or_none, msg_id_t id_or_none, size_t n_serialization_segments_or_none, const Split_segments *split_segs)
Given user- or internal-message-describing metadata values as arguments, loads (via the provided capn...
uint64_t msg_id_t
Message ID uniquely identifying outgoing message (Msg_out, among all other Msg_outs),...
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.