48class MsgSizeLayer :
public comms::frame::details::MsgSizeLayerBase<TField, TNextLayer, TOptions...>
50 using BaseImpl = comms::frame::details::MsgSizeLayerBase<TField, TNextLayer, TOptions...>;
51 using ParsedOptionsInternal = details::MsgSizeLayerOptionsParser<TOptions...>;
55 using Field =
typename BaseImpl::Field;
84 static constexpr
bool hasExtendingClass()
86 return ParsedOptionsInternal::HasExtendingClass;
90 static constexpr std::size_t doFieldLength()
92 return BaseImpl::doFieldLength();
95 template <
typename TMsg>
96 constexpr std::size_t doFieldLength(
const TMsg& msg)
const
98 return fieldLengthInternal(msg, LengthTag<>());
134 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
140 TNextLayerReader&& nextLayerReader,
141 TExtraValues... extraValues)
143 using IterType =
typename std::decay<
decltype(iter)>::type;
144 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
146 std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
147 "Current implementation of MsgSizeLayer requires iterator used for reading to be random-access one.");
150 auto* msgPtr = BaseImpl::toMsgPtr(msg);
151 auto& thisObj = BaseImpl::thisLayer();
152 auto es = thisObj.doReadField(msgPtr, field, iter, size);
153 if (es == ErrorStatus::NotEnoughData) {
154 BaseImpl::updateMissingSize(field, size, extraValues...);
157 if (es != ErrorStatus::Success) {
161 auto fromIter = iter;
162 auto readFieldLength =
static_cast<std::size_t
>(std::distance(begIter, iter));
163 std::size_t actualRemainingSize = (size - readFieldLength);
164 std::size_t requiredRemainingSize = thisObj.getRemainingSizeFromField(field);
166 if (actualRemainingSize < requiredRemainingSize) {
167 BaseImpl::setMissingSize(requiredRemainingSize - actualRemainingSize, extraValues...);
168 return ErrorStatus::NotEnoughData;
171 thisObj.beforeRead(field, msgPtr);
172 es = nextLayerReader.read(msg, iter, requiredRemainingSize, extraValues...);
173 if (es == ErrorStatus::NotEnoughData) {
174 BaseImpl::resetMsg(msg);
175 return ErrorStatus::ProtocolError;
178 if (es != ErrorStatus::ProtocolError) {
180 std::advance(iter, requiredRemainingSize);
184 static_cast<std::size_t
>(std::distance(fromIter, iter));
185 if (consumed < requiredRemainingSize) {
186 auto diff = requiredRemainingSize - consumed;
187 std::advance(iter, diff);
212 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
218 TNextLayerWriter&& nextLayerWriter)
const
220 using MsgType =
typename std::decay<
decltype(msg)>::type;
221 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), MsgLengthTag<MsgType>());
233 template <
typename TIter,
typename TNextLayerUpdater>
238 TNextLayerUpdater&& nextLayerUpdater)
const
240 using LocalMsgPtr =
typename BaseImpl::MsgPtr;
241 using ConstNullptrType =
242 typename details::MsgSizeLayerConstNullPtrCastHelper<
243 !std::is_void<LocalMsgPtr>::value
244 >::template Type<LocalMsgPtr>;
245 auto noMsgPtr =
static_cast<ConstNullptrType
>(
nullptr);
246 return doUpdateInternal(noMsgPtr, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), NoMsgTypeTag<>());
258 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
264 TNextLayerUpdater&& nextLayerUpdater)
const
266 return doUpdateInternal(&msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), ValidMsgTypeTag<>());
275 return static_cast<std::size_t
>(field.getValue());
286 template <
typename TMsg>
289 static_cast<void>(field);
290 static_cast<void>(msg);
301 template <
typename TMsg>
304 static_cast<void>(msg);
305 field.setValue(size);
309 template <
typename... TParams>
310 using FixedLengthTag =
typename BaseImpl::template FixedLengthTag<TParams...>;
312 template <
typename...TParams>
313 using VarLengthTag =
typename BaseImpl::template VarLengthTag<TParams...>;
315 template <
typename... TParams>
316 using LengthTag =
typename BaseImpl::template LengthTag<TParams...>;
318 template <
typename... TParams>
319 using MsgHasLengthTag = comms::details::tag::Tag3<>;
321 template <
typename... TParams>
322 using MsgNoLengthTag = comms::details::tag::Tag4<>;
324 template <
typename... TParams>
325 using ValidMsgTypeTag = comms::details::tag::Tag5<>;
327 template <
typename... TParams>
328 using NoMsgTypeTag = comms::details::tag::Tag6<>;
330 template<
typename TMsg>
332 typename comms::util::LazyShallowConditional<
333 details::FrameLayerHasFieldsImpl<TMsg>::Value || TMsg::hasLength()
339 template <
typename TMsg,
typename TIter,
typename TWriter>
345 TWriter&& nextLayerWriter)
const
347 std::size_t lenValue = BaseImpl::nextLayer().length(msg);
348 auto& thisObj = BaseImpl::thisLayer();
350 thisObj.prepareFieldForWrite(lenValue, &msg, field);
351 auto es = thisObj.doWriteField(&msg, field, iter, size);
352 if (es != ErrorStatus::Success) {
357 return nextLayerWriter.write(msg, iter, size - field.length());
360 template <
typename TMsg,
typename TIter,
typename TWriter>
361 ErrorStatus writeInternalRandomAccess(
366 TWriter&& nextLayerWriter)
const
368 auto valueIter = iter;
369 auto& thisObj = BaseImpl::thisLayer();
370 thisObj.prepareFieldForWrite(0U, &msg, field);
371 auto es = thisObj.doWriteField(&msg, field, iter, size);
372 if (es != ErrorStatus::Success) {
376 auto dataIter = iter;
378 auto sizeLen = field.length();
379 es = nextLayerWriter.write(msg, iter, size - sizeLen);
380 if (es != ErrorStatus::Success) {
384 auto dist =
static_cast<std::size_t
>(std::distance(dataIter, iter));
385 thisObj.prepareFieldForWrite(dist, &msg, field);
387 return thisObj.doWriteField(&msg, field, valueIter, sizeLen);
390 template <
typename TMsg,
typename TIter,
typename TWriter>
396 TWriter&& nextLayerWriter)
const
398 auto& thisObj = BaseImpl::thisLayer();
399 thisObj.prepareFieldForWrite(0U, &msg, field);
400 auto es = thisObj.doWriteField(&msg, field, iter, size);
401 if (es != ErrorStatus::Success) {
405 es = nextLayerWriter.write(msg, iter, size - field.length());
406 if ((es != ErrorStatus::Success) &&
407 (es != ErrorStatus::UpdateRequired)) {
411 return ErrorStatus::UpdateRequired;
414 template <
typename TMsg,
typename TIter,
typename TWriter>
420 TWriter&& nextLayerWriter,
421 std::random_access_iterator_tag)
const
423 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
426 template <
typename TMsg,
typename TIter,
typename TWriter>
432 TWriter&& nextLayerWriter,
433 std::output_iterator_tag)
const
435 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
438 template <
typename TMsg,
typename TIter,
typename TWriter>
444 TWriter&& nextLayerWriter)
const
447 (BaseImpl::MinFieldLength == BaseImpl::MaxFieldLength) ||
449 "Unable to perform write with size field having variable length and "
450 "no polymorphic length calculation available.");
451 using IterType =
typename std::decay<
decltype(iter)>::type;
452 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
453 return writeInternalNoLengthTagged(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter), Tag());
456 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
462 TWriter&& nextLayerWriter,
463 MsgHasLengthTag<TParams...>)
const
465 return writeInternalHasLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
468 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
474 TWriter&& nextLayerWriter,
475 MsgNoLengthTag<TParams...>)
const
477 return writeInternalNoLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
480 template <
typename TMsg,
typename... TParams>
481 constexpr std::size_t fieldLengthInternal(
const TMsg& msg, FixedLengthTag<TParams...>)
const
483 return BaseImpl::doFieldLength(msg);
486 template <
typename TMsg,
typename... TParams>
487 std::size_t fieldLengthInternal(
const TMsg& msg, VarLengthTag<TParams...>)
const
489 auto& thisObj = BaseImpl::thisLayer();
490 auto remSize = BaseImpl::nextLayer().length(msg);
492 thisObj.prepareFieldForWrite(remSize, &msg, fieldTmp);
493 return fieldTmp.length();
496 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename TForwardTag>
502 TNextLayerUpdater&& nextLayerUpdater,
503 TForwardTag&& tag)
const
505 std::size_t lenValue = size - Field::maxLength();
506 auto& thisObj = BaseImpl::thisLayer();
507 thisObj.prepareFieldForWrite(lenValue, msg, field);
509 if (field.length() != Field::maxLength()) {
510 lenValue = size - field.length();
511 thisObj.prepareFieldForWrite(lenValue, msg, field);
514 auto es = thisObj.doWriteField(msg, field, iter, size);
515 if (es != ErrorStatus::Success) {
519 return doUpdateForward(msg, iter, size - field.length(), std::forward<TNextLayerUpdater>(nextLayerUpdater), tag);
522 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
527 TNextLayerUpdater&& nextLayerUpdater,
528 NoMsgTypeTag<TParams...>)
const
530 static_cast<void>(msg);
531 return nextLayerUpdater.update(iter, size);
534 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
539 TNextLayerUpdater&& nextLayerUpdater,
540 ValidMsgTypeTag<TParams...>)
const
543 return nextLayerUpdater.update(*msg, iter, size);