49class MsgSizeLayer :
public comms::frame::details::MsgSizeLayerBase<TField, TNextLayer, TOptions...>
51 using BaseImpl = comms::frame::details::MsgSizeLayerBase<TField, TNextLayer, TOptions...>;
52 using ParsedOptionsInternal = details::MsgSizeLayerOptionsParser<TOptions...>;
56 using Field =
typename BaseImpl::Field;
78 static constexpr
bool hasExtendingClass()
80 return ParsedOptionsInternal::HasExtendingClass;
84 static constexpr std::size_t doFieldLength()
86 return BaseImpl::doFieldLength();
89 template <
typename TMsg>
90 constexpr std::size_t doFieldLength(
const TMsg& msg)
const
92 return fieldLengthInternal(msg, LengthTag<>());
128 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
134 TNextLayerReader&& nextLayerReader,
135 TExtraValues... extraValues)
137 using IterType =
typename std::decay<
decltype(iter)>::type;
138 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
140 std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
141 "Current implementation of MsgSizeLayer requires iterator used for reading to be random-access one.");
144 auto* msgPtr = BaseImpl::toMsgPtr(msg);
145 auto& thisObj = BaseImpl::thisLayer();
146 auto es = thisObj.doReadField(msgPtr, field, iter, size);
147 if (es == ErrorStatus::NotEnoughData) {
148 BaseImpl::updateMissingSize(field, size, extraValues...);
151 if (es != ErrorStatus::Success) {
155 auto fromIter = iter;
156 auto readFieldLength =
static_cast<std::size_t
>(std::distance(begIter, iter));
157 std::size_t actualRemainingSize = (size - readFieldLength);
158 std::size_t requiredRemainingSize = thisObj.getRemainingSizeFromField(field);
160 if (actualRemainingSize < requiredRemainingSize) {
161 BaseImpl::setMissingSize(requiredRemainingSize - actualRemainingSize, extraValues...);
162 return ErrorStatus::NotEnoughData;
165 thisObj.beforeRead(field, msgPtr);
166 es = nextLayerReader.read(msg, iter, requiredRemainingSize, extraValues...);
167 if (es == ErrorStatus::NotEnoughData) {
168 BaseImpl::resetMsg(msg);
169 return ErrorStatus::ProtocolError;
172 if (es != ErrorStatus::ProtocolError) {
174 std::advance(iter, requiredRemainingSize);
178 static_cast<std::size_t
>(std::distance(fromIter, iter));
179 if (consumed < requiredRemainingSize) {
180 auto diff = requiredRemainingSize - consumed;
181 std::advance(iter, diff);
205 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
211 TNextLayerWriter&& nextLayerWriter)
const
213 using MsgType =
typename std::decay<
decltype(msg)>::type;
214 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), MsgLengthTag<MsgType>());
226 template <
typename TIter,
typename TNextLayerUpdater>
231 TNextLayerUpdater&& nextLayerUpdater)
const
233 using LocalMsgPtr =
typename BaseImpl::MsgPtr;
234 using ConstNullptrType =
235 typename details::MsgSizeLayerConstNullPtrCastHelper<
236 !std::is_void<LocalMsgPtr>::value
237 >::template Type<LocalMsgPtr>;
238 auto noMsgPtr =
static_cast<ConstNullptrType
>(
nullptr);
239 return doUpdateInternal(noMsgPtr, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), NoMsgTypeTag<>());
251 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
257 TNextLayerUpdater&& nextLayerUpdater)
const
259 return doUpdateInternal(&msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), ValidMsgTypeTag<>());
268 return static_cast<std::size_t
>(field.getValue());
279 template <
typename TMsg>
282 static_cast<void>(field);
283 static_cast<void>(msg);
294 template <
typename TMsg>
297 static_cast<void>(msg);
298 field.setValue(size);
302 template <
typename... TParams>
303 using FixedLengthTag =
typename BaseImpl::template FixedLengthTag<TParams...>;
305 template <
typename...TParams>
306 using VarLengthTag =
typename BaseImpl::template VarLengthTag<TParams...>;
308 template <
typename... TParams>
309 using LengthTag =
typename BaseImpl::template LengthTag<TParams...>;
311 template <
typename... TParams>
312 using MsgHasLengthTag = comms::details::tag::Tag3<>;
314 template <
typename... TParams>
315 using MsgNoLengthTag = comms::details::tag::Tag4<>;
317 template <
typename... TParams>
318 using ValidMsgTypeTag = comms::details::tag::Tag5<>;
320 template <
typename... TParams>
321 using NoMsgTypeTag = comms::details::tag::Tag6<>;
323 template<
typename TMsg>
325 typename comms::util::LazyShallowConditional<
326 details::FrameLayerHasFieldsImpl<TMsg>::Value || TMsg::hasLength()
332 template <
typename TMsg,
typename TIter,
typename TWriter>
338 TWriter&& nextLayerWriter)
const
340 std::size_t lenValue = BaseImpl::nextLayer().length(msg);
341 auto& thisObj = BaseImpl::thisLayer();
343 thisObj.prepareFieldForWrite(lenValue, &msg, field);
344 auto es = thisObj.doWriteField(&msg, field, iter, size);
345 if (es != ErrorStatus::Success) {
350 return nextLayerWriter.write(msg, iter, size - field.length());
353 template <
typename TMsg,
typename TIter,
typename TWriter>
354 ErrorStatus writeInternalRandomAccess(
359 TWriter&& nextLayerWriter)
const
361 auto valueIter = iter;
362 auto& thisObj = BaseImpl::thisLayer();
363 thisObj.prepareFieldForWrite(0U, &msg, field);
364 auto es = thisObj.doWriteField(&msg, field, iter, size);
365 if (es != ErrorStatus::Success) {
369 auto dataIter = iter;
371 auto sizeLen = field.length();
372 es = nextLayerWriter.write(msg, iter, size - sizeLen);
373 if (es != ErrorStatus::Success) {
377 auto dist =
static_cast<std::size_t
>(std::distance(dataIter, iter));
378 thisObj.prepareFieldForWrite(dist, &msg, field);
380 return thisObj.doWriteField(&msg, field, valueIter, sizeLen);
383 template <
typename TMsg,
typename TIter,
typename TWriter>
389 TWriter&& nextLayerWriter)
const
391 auto& thisObj = BaseImpl::thisLayer();
392 thisObj.prepareFieldForWrite(0U, &msg, field);
393 auto es = thisObj.doWriteField(&msg, field, iter, size);
394 if (es != ErrorStatus::Success) {
398 es = nextLayerWriter.write(msg, iter, size - field.length());
399 if ((es != ErrorStatus::Success) &&
400 (es != ErrorStatus::UpdateRequired)) {
404 return ErrorStatus::UpdateRequired;
407 template <
typename TMsg,
typename TIter,
typename TWriter>
413 TWriter&& nextLayerWriter,
414 std::random_access_iterator_tag)
const
416 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
419 template <
typename TMsg,
typename TIter,
typename TWriter>
425 TWriter&& nextLayerWriter,
426 std::output_iterator_tag)
const
428 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
431 template <
typename TMsg,
typename TIter,
typename TWriter>
437 TWriter&& nextLayerWriter)
const
440 (BaseImpl::MinFieldLength == BaseImpl::MaxFieldLength) ||
442 "Unable to perform write with size field having variable length and "
443 "no polymorphic length calculation available.");
444 using IterType =
typename std::decay<
decltype(iter)>::type;
445 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
446 return writeInternalNoLengthTagged(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter), Tag());
449 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
455 TWriter&& nextLayerWriter,
456 MsgHasLengthTag<TParams...>)
const
458 return writeInternalHasLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
461 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
467 TWriter&& nextLayerWriter,
468 MsgNoLengthTag<TParams...>)
const
470 return writeInternalNoLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
473 template <
typename TMsg,
typename... TParams>
474 constexpr std::size_t fieldLengthInternal(
const TMsg& msg, FixedLengthTag<TParams...>)
const
476 return BaseImpl::doFieldLength(msg);
479 template <
typename TMsg,
typename... TParams>
480 std::size_t fieldLengthInternal(
const TMsg& msg, VarLengthTag<TParams...>)
const
482 auto& thisObj = BaseImpl::thisLayer();
483 auto remSize = BaseImpl::nextLayer().length(msg);
485 thisObj.prepareFieldForWrite(remSize, &msg, fieldTmp);
486 return fieldTmp.length();
489 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename TForwardTag>
495 TNextLayerUpdater&& nextLayerUpdater,
496 TForwardTag&& tag)
const
498 std::size_t lenValue = size - Field::maxLength();
499 auto& thisObj = BaseImpl::thisLayer();
500 thisObj.prepareFieldForWrite(lenValue, msg, field);
502 if (field.length() != Field::maxLength()) {
503 lenValue = size - field.length();
504 thisObj.prepareFieldForWrite(lenValue, msg, field);
507 auto es = thisObj.doWriteField(msg, field, iter, size);
508 if (es != ErrorStatus::Success) {
512 return doUpdateForward(msg, iter, size - field.length(), std::forward<TNextLayerUpdater>(nextLayerUpdater), tag);
515 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
520 TNextLayerUpdater&& nextLayerUpdater,
521 NoMsgTypeTag<TParams...>)
const
523 static_cast<void>(msg);
524 return nextLayerUpdater.update(iter, size);
527 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
532 TNextLayerUpdater&& nextLayerUpdater,
533 ValidMsgTypeTag<TParams...>)
const
536 return nextLayerUpdater.update(*msg, iter, size);