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;
85 static constexpr
bool hasExtendingClass()
87 return ParsedOptionsInternal::HasExtendingClass;
91 static constexpr std::size_t doFieldLength()
93 return BaseImpl::doFieldLength();
96 template <
typename TMsg>
97 constexpr std::size_t doFieldLength(
const TMsg& msg)
const
99 return fieldLengthInternal(msg, LengthTag<>());
135 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
141 TNextLayerReader&& nextLayerReader,
142 TExtraValues... extraValues)
144 using IterType =
typename std::decay<
decltype(iter)>::type;
145 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
147 std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
148 "Current implementation of MsgSizeLayer requires iterator used for reading to be random-access one.");
151 auto* msgPtr = BaseImpl::toMsgPtr(msg);
152 auto& thisObj = BaseImpl::thisLayer();
153 auto es = thisObj.doReadField(msgPtr, field, iter, size);
154 if (es == ErrorStatus::NotEnoughData) {
155 BaseImpl::updateMissingSize(field, size, extraValues...);
158 if (es != ErrorStatus::Success) {
162 auto fromIter = iter;
163 auto readFieldLength =
static_cast<std::size_t
>(std::distance(begIter, iter));
164 std::size_t actualRemainingSize = (size - readFieldLength);
165 std::size_t requiredRemainingSize = thisObj.getRemainingSizeFromField(field);
167 if (actualRemainingSize < requiredRemainingSize) {
168 BaseImpl::setMissingSize(requiredRemainingSize - actualRemainingSize, extraValues...);
169 return ErrorStatus::NotEnoughData;
172 thisObj.beforeRead(field, msgPtr);
173 es = nextLayerReader.read(msg, iter, requiredRemainingSize, extraValues...);
174 if (es == ErrorStatus::NotEnoughData) {
175 BaseImpl::resetMsg(msg);
176 return ErrorStatus::ProtocolError;
179 if (es != ErrorStatus::ProtocolError) {
181 std::advance(iter, requiredRemainingSize);
185 static_cast<std::size_t
>(std::distance(fromIter, iter));
186 if (consumed < requiredRemainingSize) {
187 auto diff = requiredRemainingSize - consumed;
188 std::advance(iter, diff);
213 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
219 TNextLayerWriter&& nextLayerWriter)
const
221 using MsgType =
typename std::decay<
decltype(msg)>::type;
222 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), MsgLengthTag<MsgType>());
234 template <
typename TIter,
typename TNextLayerUpdater>
239 TNextLayerUpdater&& nextLayerUpdater)
const
241 using LocalMsgPtr =
typename BaseImpl::MsgPtr;
242 using ConstNullptrType =
243 typename details::MsgSizeLayerConstNullPtrCastHelper<
244 !std::is_void<LocalMsgPtr>::value
245 >::template Type<LocalMsgPtr>;
246 auto noMsgPtr =
static_cast<ConstNullptrType
>(
nullptr);
247 return doUpdateInternal(noMsgPtr, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), NoMsgTypeTag<>());
259 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
265 TNextLayerUpdater&& nextLayerUpdater)
const
267 return doUpdateInternal(&msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), ValidMsgTypeTag<>());
276 return static_cast<std::size_t
>(field.getValue());
287 template <
typename TMsg>
290 static_cast<void>(field);
291 static_cast<void>(msg);
302 template <
typename TMsg>
305 static_cast<void>(msg);
306 field.setValue(size);
310 template <
typename... TParams>
311 using FixedLengthTag =
typename BaseImpl::template FixedLengthTag<TParams...>;
313 template <
typename...TParams>
314 using VarLengthTag =
typename BaseImpl::template VarLengthTag<TParams...>;
316 template <
typename... TParams>
317 using LengthTag =
typename BaseImpl::template LengthTag<TParams...>;
319 template <
typename... TParams>
320 using MsgHasLengthTag = comms::details::tag::Tag3<>;
322 template <
typename... TParams>
323 using MsgNoLengthTag = comms::details::tag::Tag4<>;
325 template <
typename... TParams>
326 using ValidMsgTypeTag = comms::details::tag::Tag5<>;
328 template <
typename... TParams>
329 using NoMsgTypeTag = comms::details::tag::Tag6<>;
331 template<
typename TMsg>
333 typename comms::util::LazyShallowConditional<
334 details::FrameLayerHasFieldsImpl<TMsg>::Value || TMsg::hasLength()
340 template <
typename TMsg,
typename TIter,
typename TWriter>
346 TWriter&& nextLayerWriter)
const
348 std::size_t lenValue = BaseImpl::nextLayer().length(msg);
349 auto& thisObj = BaseImpl::thisLayer();
351 thisObj.prepareFieldForWrite(lenValue, &msg, field);
352 auto es = thisObj.doWriteField(&msg, field, iter, size);
353 if (es != ErrorStatus::Success) {
358 return nextLayerWriter.write(msg, iter, size - field.length());
361 template <
typename TMsg,
typename TIter,
typename TWriter>
362 ErrorStatus writeInternalRandomAccess(
367 TWriter&& nextLayerWriter)
const
369 auto valueIter = iter;
370 auto& thisObj = BaseImpl::thisLayer();
371 thisObj.prepareFieldForWrite(0U, &msg, field);
372 auto es = thisObj.doWriteField(&msg, field, iter, size);
373 if (es != ErrorStatus::Success) {
377 auto dataIter = iter;
379 auto sizeLen = field.length();
380 es = nextLayerWriter.write(msg, iter, size - sizeLen);
381 if (es != ErrorStatus::Success) {
385 auto dist =
static_cast<std::size_t
>(std::distance(dataIter, iter));
386 thisObj.prepareFieldForWrite(dist, &msg, field);
388 return thisObj.doWriteField(&msg, field, valueIter, sizeLen);
391 template <
typename TMsg,
typename TIter,
typename TWriter>
397 TWriter&& nextLayerWriter)
const
399 auto& thisObj = BaseImpl::thisLayer();
400 thisObj.prepareFieldForWrite(0U, &msg, field);
401 auto es = thisObj.doWriteField(&msg, field, iter, size);
402 if (es != ErrorStatus::Success) {
406 es = nextLayerWriter.write(msg, iter, size - field.length());
407 if ((es != ErrorStatus::Success) &&
408 (es != ErrorStatus::UpdateRequired)) {
412 return ErrorStatus::UpdateRequired;
415 template <
typename TMsg,
typename TIter,
typename TWriter>
421 TWriter&& nextLayerWriter,
422 std::random_access_iterator_tag)
const
424 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
427 template <
typename TMsg,
typename TIter,
typename TWriter>
433 TWriter&& nextLayerWriter,
434 std::output_iterator_tag)
const
436 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
439 template <
typename TMsg,
typename TIter,
typename TWriter>
445 TWriter&& nextLayerWriter)
const
448 (BaseImpl::MinFieldLength == BaseImpl::MaxFieldLength) ||
450 "Unable to perform write with size field having variable length and "
451 "no polymorphic length calculation available.");
452 using IterType =
typename std::decay<
decltype(iter)>::type;
453 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
454 return writeInternalNoLengthTagged(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter), Tag());
457 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
463 TWriter&& nextLayerWriter,
464 MsgHasLengthTag<TParams...>)
const
466 return writeInternalHasLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
469 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
475 TWriter&& nextLayerWriter,
476 MsgNoLengthTag<TParams...>)
const
478 return writeInternalNoLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
481 template <
typename TMsg,
typename... TParams>
482 constexpr std::size_t fieldLengthInternal(
const TMsg& msg, FixedLengthTag<TParams...>)
const
484 return BaseImpl::doFieldLength(msg);
487 template <
typename TMsg,
typename... TParams>
488 std::size_t fieldLengthInternal(
const TMsg& msg, VarLengthTag<TParams...>)
const
490 auto& thisObj = BaseImpl::thisLayer();
491 auto remSize = BaseImpl::nextLayer().length(msg);
493 thisObj.prepareFieldForWrite(remSize, &msg, fieldTmp);
494 return fieldTmp.length();
497 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename TForwardTag>
503 TNextLayerUpdater&& nextLayerUpdater,
504 TForwardTag&& tag)
const
506 std::size_t lenValue = size - Field::maxLength();
507 auto& thisObj = BaseImpl::thisLayer();
508 thisObj.prepareFieldForWrite(lenValue, msg, field);
510 if (field.length() != Field::maxLength()) {
511 lenValue = size - field.length();
512 thisObj.prepareFieldForWrite(lenValue, msg, field);
515 auto es = thisObj.doWriteField(msg, field, iter, size);
516 if (es != ErrorStatus::Success) {
520 return doUpdateForward(msg, iter, size - field.length(), std::forward<TNextLayerUpdater>(nextLayerUpdater), tag);
523 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
528 TNextLayerUpdater&& nextLayerUpdater,
529 NoMsgTypeTag<TParams...>)
const
531 static_cast<void>(msg);
532 return nextLayerUpdater.update(iter, size);
535 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
540 TNextLayerUpdater&& nextLayerUpdater,
541 ValidMsgTypeTag<TParams...>)
const
544 return nextLayerUpdater.update(*msg, iter, size);