52class MsgSizeLayer :
public comms::frame::details::MsgSizeLayerBase<TField, TNextLayer, TOptions...>
54 using BaseImpl = comms::frame::details::MsgSizeLayerBase<TField, TNextLayer, TOptions...>;
55 using ParsedOptionsInternal = details::MsgSizeLayerOptionsParser<TOptions...>;
59 using Field =
typename BaseImpl::Field;
81 static constexpr
bool hasExtendingClass()
83 return ParsedOptionsInternal::HasExtendingClass;
87 static constexpr std::size_t doFieldLength()
89 return BaseImpl::doFieldLength();
92 template <
typename TMsg>
93 constexpr std::size_t doFieldLength(
const TMsg& msg)
const
95 return fieldLengthInternal(msg, LengthTag<>());
131 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
137 TNextLayerReader&& nextLayerReader,
138 TExtraValues... extraValues)
140 using IterType =
typename std::decay<
decltype(iter)>::type;
141 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
143 std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
144 "Current implementation of MsgSizeLayer requires iterator used for reading to be random-access one.");
147 auto* msgPtr = BaseImpl::toMsgPtr(msg);
148 auto& thisObj = BaseImpl::thisLayer();
149 auto es = thisObj.doReadField(msgPtr, field, iter, size);
150 if (es == ErrorStatus::NotEnoughData) {
151 BaseImpl::updateMissingSize(field, size, extraValues...);
154 if (es != ErrorStatus::Success) {
158 auto fromIter = iter;
159 auto readFieldLength =
static_cast<std::size_t
>(std::distance(begIter, iter));
160 std::size_t actualRemainingSize = (size - readFieldLength);
161 std::size_t requiredRemainingSize = thisObj.getRemainingSizeFromField(field);
163 if (actualRemainingSize < requiredRemainingSize) {
164 BaseImpl::setMissingSize(requiredRemainingSize - actualRemainingSize, extraValues...);
165 return ErrorStatus::NotEnoughData;
168 thisObj.beforeRead(field, msgPtr);
169 es = nextLayerReader.read(msg, iter, requiredRemainingSize, extraValues...);
170 if (es == ErrorStatus::NotEnoughData) {
171 BaseImpl::resetMsg(msg);
172 return ErrorStatus::ProtocolError;
175 if (es != ErrorStatus::ProtocolError) {
177 std::advance(iter, requiredRemainingSize);
181 static_cast<std::size_t
>(std::distance(fromIter, iter));
182 if (consumed < requiredRemainingSize) {
183 auto diff = requiredRemainingSize - consumed;
184 std::advance(iter, diff);
208 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
214 TNextLayerWriter&& nextLayerWriter)
const
216 using MsgType =
typename std::decay<
decltype(msg)>::type;
217 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), MsgLengthTag<MsgType>());
229 template <
typename TIter,
typename TNextLayerUpdater>
234 TNextLayerUpdater&& nextLayerUpdater)
const
236 using LocalMsgPtr =
typename BaseImpl::MsgPtr;
237 using ConstNullptrType =
238 typename details::MsgSizeLayerConstNullPtrCastHelper<
239 !std::is_void<LocalMsgPtr>::value
240 >::template Type<LocalMsgPtr>;
241 auto noMsgPtr =
static_cast<ConstNullptrType
>(
nullptr);
242 return doUpdateInternal(noMsgPtr, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), NoMsgTypeTag<>());
254 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
260 TNextLayerUpdater&& nextLayerUpdater)
const
262 return doUpdateInternal(&msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), ValidMsgTypeTag<>());
271 return static_cast<std::size_t
>(field.getValue());
282 template <
typename TMsg>
285 static_cast<void>(field);
286 static_cast<void>(msg);
297 template <
typename TMsg>
300 static_cast<void>(msg);
301 field.setValue(size);
305 template <
typename... TParams>
306 using FixedLengthTag =
typename BaseImpl::template FixedLengthTag<TParams...>;
308 template <
typename...TParams>
309 using VarLengthTag =
typename BaseImpl::template VarLengthTag<TParams...>;
311 template <
typename... TParams>
312 using LengthTag =
typename BaseImpl::template LengthTag<TParams...>;
314 template <
typename... TParams>
315 using MsgHasLengthTag = comms::details::tag::Tag3<>;
317 template <
typename... TParams>
318 using MsgNoLengthTag = comms::details::tag::Tag4<>;
320 template <
typename... TParams>
321 using ValidMsgTypeTag = comms::details::tag::Tag5<>;
323 template <
typename... TParams>
324 using NoMsgTypeTag = comms::details::tag::Tag6<>;
326 template<
typename TMsg>
328 typename comms::util::LazyShallowConditional<
329 details::FrameLayerHasFieldsImpl<TMsg>::Value || TMsg::hasLength()
335 template <
typename TMsg,
typename TIter,
typename TWriter>
341 TWriter&& nextLayerWriter)
const
343 std::size_t lenValue = BaseImpl::nextLayer().length(msg);
344 auto& thisObj = BaseImpl::thisLayer();
346 thisObj.prepareFieldForWrite(lenValue, &msg, field);
347 auto es = thisObj.doWriteField(&msg, field, iter, size);
348 if (es != ErrorStatus::Success) {
353 return nextLayerWriter.write(msg, iter, size - field.length());
356 template <
typename TMsg,
typename TIter,
typename TWriter>
357 ErrorStatus writeInternalRandomAccess(
362 TWriter&& nextLayerWriter)
const
364 auto valueIter = iter;
365 auto& thisObj = BaseImpl::thisLayer();
366 thisObj.prepareFieldForWrite(0U, &msg, field);
367 auto es = thisObj.doWriteField(&msg, field, iter, size);
368 if (es != ErrorStatus::Success) {
372 auto dataIter = iter;
374 auto sizeLen = field.length();
375 es = nextLayerWriter.write(msg, iter, size - sizeLen);
376 if (es != ErrorStatus::Success) {
380 auto dist =
static_cast<std::size_t
>(std::distance(dataIter, iter));
381 thisObj.prepareFieldForWrite(dist, &msg, field);
383 return thisObj.doWriteField(&msg, field, valueIter, sizeLen);
386 template <
typename TMsg,
typename TIter,
typename TWriter>
392 TWriter&& nextLayerWriter)
const
394 auto& thisObj = BaseImpl::thisLayer();
395 thisObj.prepareFieldForWrite(0U, &msg, field);
396 auto es = thisObj.doWriteField(&msg, field, iter, size);
397 if (es != ErrorStatus::Success) {
401 es = nextLayerWriter.write(msg, iter, size - field.length());
402 if ((es != ErrorStatus::Success) &&
403 (es != ErrorStatus::UpdateRequired)) {
407 return ErrorStatus::UpdateRequired;
410 template <
typename TMsg,
typename TIter,
typename TWriter>
416 TWriter&& nextLayerWriter,
417 std::random_access_iterator_tag)
const
419 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
422 template <
typename TMsg,
typename TIter,
typename TWriter>
428 TWriter&& nextLayerWriter,
429 std::output_iterator_tag)
const
431 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
434 template <
typename TMsg,
typename TIter,
typename TWriter>
440 TWriter&& nextLayerWriter)
const
443 (BaseImpl::MinFieldLength == BaseImpl::MaxFieldLength) ||
445 "Unable to perform write with size field having variable length and "
446 "no polymorphic length calculation available.");
447 using IterType =
typename std::decay<
decltype(iter)>::type;
448 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
449 return writeInternalNoLengthTagged(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter), Tag());
452 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
458 TWriter&& nextLayerWriter,
459 MsgHasLengthTag<TParams...>)
const
461 return writeInternalHasLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
464 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
470 TWriter&& nextLayerWriter,
471 MsgNoLengthTag<TParams...>)
const
473 return writeInternalNoLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
476 template <
typename TMsg,
typename... TParams>
477 constexpr std::size_t fieldLengthInternal(
const TMsg& msg, FixedLengthTag<TParams...>)
const
479 return BaseImpl::doFieldLength(msg);
482 template <
typename TMsg,
typename... TParams>
483 std::size_t fieldLengthInternal(
const TMsg& msg, VarLengthTag<TParams...>)
const
485 auto& thisObj = BaseImpl::thisLayer();
486 auto remSize = BaseImpl::nextLayer().length(msg);
488 thisObj.prepareFieldForWrite(remSize, &msg, fieldTmp);
489 return fieldTmp.length();
492 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename TForwardTag>
498 TNextLayerUpdater&& nextLayerUpdater,
499 TForwardTag&& tag)
const
501 std::size_t lenValue = size - Field::maxLength();
502 auto& thisObj = BaseImpl::thisLayer();
503 thisObj.prepareFieldForWrite(lenValue, msg, field);
505 if (field.length() != Field::maxLength()) {
506 lenValue = size - field.length();
507 thisObj.prepareFieldForWrite(lenValue, msg, field);
510 auto es = thisObj.doWriteField(msg, field, iter, size);
511 if (es != ErrorStatus::Success) {
515 return doUpdateForward(msg, iter, size - field.length(), std::forward<TNextLayerUpdater>(nextLayerUpdater), tag);
518 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
523 TNextLayerUpdater&& nextLayerUpdater,
524 NoMsgTypeTag<TParams...>)
const
526 static_cast<void>(msg);
527 return nextLayerUpdater.update(iter, size);
530 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
535 TNextLayerUpdater&& nextLayerUpdater,
536 ValidMsgTypeTag<TParams...>)
const
539 return nextLayerUpdater.update(*msg, iter, size);