71class MsgIdLayer :
public comms::frame::details::MsgIdLayerBase<TField, TMessage, TAllMessages, TNextLayer, TOptions...>
74 "TAllMessages must be of std::tuple type");
76 static_assert(TMessage::hasMsgIdType(),
77 "Usage of MsgIdLayer requires support for ID type. "
78 "Use comms::option::def::MsgIdType option in message interface type definition.");
80 using BaseImpl = comms::frame::details::MsgIdLayerBase<TField, TMessage, TAllMessages, TNextLayer, TOptions...>;
81 using ParsedOptionsInternal = details::MsgIdLayerOptionsParser<TOptions...>;
104 using Field =
typename BaseImpl::Field;
129 static constexpr
bool hasExtendingClass()
131 return ParsedOptionsInternal::HasExtendingClass;
139 return ParsedOptionsInternal::HasMsgFactory;
180 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
186 TNextLayerReader&& nextLayerReader,
187 TExtraValues... extraValues)
189 auto beforeReadIter = iter;
190 auto& thisObj = BaseImpl::thisLayer();
191 auto* msgPtr = BaseImpl::toMsgPtr(msg);
192 auto es = thisObj.doReadField(msgPtr, field, iter, size);
194 BaseImpl::updateMissingSize(field, size, extraValues...);
197 if (es != ErrorStatus::Success) {
201 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeReadIter, iter));
204 typename comms::util::LazyShallowConditional<
217 std::forward<TNextLayerReader>(nextLayerReader),
248 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
254 TNextLayerWriter&& nextLayerWriter)
const
256 auto& thisObj = BaseImpl::thisLayer();
257 using MsgType =
typename std::decay<
decltype(msg)>::type;
258 static_assert(comms::isMessage<MsgType>(),
"The message type must extend comms::Message");
259 thisObj.prepareFieldForWrite(
260 getMsgId(msg, IdRetrieveTag<MsgType>()),
264 auto es = thisObj.doWriteField(&msg, field, iter, size);
265 if (es != ErrorStatus::Success) {
272 typename comms::util::LazyShallowConditional<
273 comms::isMessageBase<MsgType>() || MsgType::hasWrite()
279 return writeInternal(field, msg, iter, size - field.length(), std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
294 return m_factory.createMsg(
id, idx, reason);
301 return MsgFactory::isDispatchPolymorphic();
308 return MsgFactory::isDispatchStaticBinSearch();
315 return MsgFactory::isDispatchLinearSwitch();
326 return static_cast<MsgIdType>(field.getValue());
339 template <
typename TMsg>
342 static_cast<void>(field);
343 static_cast<void>(msg);
353 template <
typename TMsg>
356 static_cast<void>(msg);
357 static_cast<void>(field);
363 template <
typename... TParams>
364 using PolymorphicOpTag = comms::details::tag::Tag1<>;
366 template <
typename... TParams>
367 using DirectOpTag = comms::details::tag::Tag2<>;
369 template <
typename... TParams>
370 using PointerOpTag = comms::details::tag::Tag3<>;
372 template <
typename... TParams>
373 using StaticBinSearchOpTag = comms::details::tag::Tag4<>;
375 template <
typename TMsg>
376 using IdRetrieveTag =
377 typename comms::util::LazyShallowConditional<
378 comms::isMessageBase<TMsg>()
384 template <
typename... TParams>
385 using IdParamAsIsTag = comms::details::tag::Tag5<>;
387 template <
typename... TParams>
388 using IdParamCastTag = comms::details::tag::Tag6<>;
390 template <
typename TId>
392 typename comms::util::LazyShallowConditional<
393 std::is_base_of<MsgIdType, TId>::value
399 template <
typename... TParams>
400 using HasGenericMsgTag = comms::details::tag::Tag7<>;
402 template <
typename... TParams>
403 using NoGenericMsgTag = comms::details::tag::Tag8<>;
405 template <
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
406 class ReadRedirectionHandler
411 ReadRedirectionHandler(
414 TNextLayerReader&& nextLayerReader,
415 TExtraValues... extraValues)
418 m_nextLayerReader(
std::forward<TNextLayerReader>(nextLayerReader)),
419 m_extraValues(extraValues...)
423 template <
typename TMsg>
424 RetType handle(TMsg& msg)
426 static_assert(comms::isMessageBase<TMsg>(),
"Expected to be a valid message object");
427 return handleInternal(msg, m_extraValues);
430 RetType handle(TMessage& msg)
432 static_cast<void>(msg);
433 static constexpr bool Should_not_happen =
false;
434 static_cast<void>(Should_not_happen);
440 template <
typename TMsg>
441 RetType handleInternal(TMsg& msg, std::tuple<>&)
443 return m_nextLayerReader.read(msg, m_iter, m_size);
446 template <
typename TMsg,
typename T0>
447 RetType handleInternal(TMsg& msg, std::tuple<T0>& extraValues)
449 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues));
452 template <
typename TMsg,
typename T0,
typename T1>
453 RetType handleInternal(TMsg& msg, std::tuple<T0, T1>& extraValues)
455 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues), std::get<1>(extraValues));
458 template <
typename TMsg,
typename T0,
typename T1,
typename T2>
459 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2>& extraValues)
462 m_nextLayerReader.read(
466 std::get<0>(extraValues),
467 std::get<1>(extraValues),
468 std::get<2>(extraValues));
471 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3>
472 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3>& extraValues)
475 m_nextLayerReader.read(
479 std::get<0>(extraValues),
480 std::get<1>(extraValues),
481 std::get<2>(extraValues),
482 std::get<3>(extraValues));
485 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3,
typename T4>
486 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4>& extraValues)
489 m_nextLayerReader.read(
493 std::get<0>(extraValues),
494 std::get<1>(extraValues),
495 std::get<2>(extraValues),
496 std::get<3>(extraValues),
497 std::get<4>(extraValues));
500 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
501 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4, T5>& extraValues)
504 m_nextLayerReader.read(
508 std::get<0>(extraValues),
509 std::get<1>(extraValues),
510 std::get<2>(extraValues),
511 std::get<3>(extraValues),
512 std::get<4>(extraValues),
513 std::get<5>(extraValues));
517 std::size_t m_size = 0U;
518 TNextLayerReader&& m_nextLayerReader;
519 std::tuple<TExtraValues...> m_extraValues;
522 template <
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
523 ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...> makeReadRedirectionHandler(
526 TNextLayerReader&& nextLayerReader,
527 TExtraValues... extraValues)
529 return ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...>(iter, size, std::forward<TNextLayerReader>(nextLayerReader), extraValues...);
532 template <
typename TIter,
typename TNextLayerWriter>
533 class WriteRedirectionHandler
538 WriteRedirectionHandler(
541 TNextLayerWriter&& nextLayerWriter)
544 m_nextLayerWriter(
std::forward<TNextLayerWriter>(nextLayerWriter))
548 template <
typename TMsg>
549 RetType handle(
const TMsg& msg)
551 static_assert(comms::isMessageBase<TMsg>(),
"Expected to be a valid message object");
552 return m_nextLayerWriter.write(msg, m_iter, m_size);
555 RetType handle(
const TMessage& msg)
557 static_cast<void>(msg);
558 static constexpr bool Should_not_happen =
false;
559 static_cast<void>(Should_not_happen);
566 std::size_t m_size = 0U;
567 TNextLayerWriter&& m_nextLayerWriter;
570 template <
typename TIter,
typename TNextLayerWriter>
571 WriteRedirectionHandler<TIter, TNextLayerWriter> makeWriteRedirectionHandler(
574 TNextLayerWriter&& nextLayerWriter)
576 return WriteRedirectionHandler<TIter, TNextLayerWriter>(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
579 template <
typename TMsg,
typename... TParams>
580 static MsgIdParamType getMsgId(
const TMsg& msg, PolymorphicOpTag<TParams...>)
582 using MsgType =
typename std::decay<
decltype(msg)>::type;
583 static_assert(comms::isMessage<MsgType>(),
584 "The message class is expected to inherit from comms::Message");
585 static_assert(MsgType::hasGetId(),
586 "The message interface class must expose polymorphic ID retrieval functionality, "
587 "use comms::option::app::IdInfoInterface option to define it.");
592 template <
typename TMsg,
typename... TParams>
593 static constexpr MsgIdParamType getMsgId(
const TMsg& msg, DirectOpTag<TParams...>)
595 using MsgType =
typename std::decay<
decltype(msg)>::type;
596 static_assert(comms::isMessageBase<MsgType>(),
597 "The message class is expected to inherit from comms::MessageBase");
598 static_assert(MsgType::hasDoGetId(),
599 "The message class must expose direct ID retrieval functionality, "
600 "use comms::option::app::StaticNumIdImpl option to define it or "
601 "comms::option::app::HasDoGetId option to mark the class as providing one");
602 return msg.doGetId();
605 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
611 TNextLayerReader&& nextLayerReader,
612 TExtraValues... extraValues)
614 static_assert((!details::hasMsgIndexRetriever<TExtraValues...>()) || (comms::details::allMessagesAreStrongSorted<AllMessages>()),
615 "Message type index cannot be retrieved with direct message object invocation");
616 auto& thisObj = BaseImpl::thisLayer();
617 auto id = thisObj.getMsgIdFromField(field);
618 BaseImpl::setMsgId(
id, extraValues...);
619 BaseImpl::setMsgIndex(0U, extraValues...);
621 using MsgType =
typename std::decay<
decltype(msg)>::type;
622 if (
id != getMsgId(msg, IdRetrieveTag<MsgType>())) {
623 return ErrorStatus::InvalidMsgId;
626 thisObj.beforeRead(field, msg);
627 return nextLayerReader.read(msg, iter, size, extraValues...);
630 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
637 TNextLayerReader&& nextLayerReader,
639 TExtraValues... extraValues)
641 static_cast<void>(id);
642 static_cast<void>(idx);
643 return nextLayerReader.read(msg, iter, size, extraValues...);
646 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
652 TNextLayerReader&& nextLayerReader,
654 TExtraValues... extraValues)
657 doReadInternalDirect(
662 std::forward<TNextLayerReader>(nextLayerReader),
666 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
672 TNextLayerReader&& nextLayerReader,
674 TExtraValues... extraValues)
676 using MsgType =
typename std::decay<
decltype(msg)>::type;
677 static_assert(comms::details::hasElementType<MsgType>(),
678 "Unsupported type of message object, expected to be either message itself or smart pointer");
680 using MsgElementType =
typename MsgType::element_type;
683 typename comms::util::LazyShallowConditional<
684 MsgElementType::hasRead()
690 auto& thisObj = BaseImpl::thisLayer();
691 const auto id = thisObj.getMsgIdFromField(field);
692 BaseImpl::setMsgId(
id, extraValues...);
696 CreateFailureReason failureReason = CreateFailureReason::None;
699 msg = createMsgInternal(
id, idx, &failureReason);
704 using IterType =
typename std::decay<
decltype(iter)>::type;
705 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
706 "Iterator used for reading is expected to be random access one");
707 IterType readStart = iter;
709 thisObj.beforeRead(field, *msg);
710 es = doReadInternal(
id, idx, msg, iter, size, std::forward<TNextLayerReader>(nextLayerReader), Tag(), extraValues...);
712 BaseImpl::setMsgIndex(idx, extraValues...);
721 BaseImpl::setMsgIndex(idx, extraValues...);
723 if (failureReason == CreateFailureReason::AllocFailure) {
727 COMMS_ASSERT(failureReason == CreateFailureReason::InvalidId);
728 using GenericMsgTag =
729 typename comms::util::LazyShallowConditional<
730 MsgFactory::hasGenericMessageSupport()
737 createAndReadGenericMsgInternal(
743 std::forward<TNextLayerReader>(nextLayerReader),
749 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
756 TNextLayerReader&& nextLayerReader,
757 StaticBinSearchOpTag<>,
758 TExtraValues... extraValues)
761 makeReadRedirectionHandler(
764 std::forward<TNextLayerReader>(nextLayerReader),
766 return comms::dispatchMsgStaticBinSearch<AllMessages>(
id, idx, *msg, handler);
769 template <
typename TId,
typename... TParams>
770 MsgPtr createMsgInternalTagged(TId&&
id,
unsigned idx, CreateFailureReason* reason, IdParamAsIsTag<TParams...>)
772 return createMsg(std::forward<TId>(
id), idx, reason);
775 template <
typename TId,
typename... TParams>
776 MsgPtr createMsgInternalTagged(TId&&
id,
unsigned idx, CreateFailureReason* reason, IdParamCastTag<TParams...>)
778 return createMsg(
static_cast<MsgIdType>(
id), idx, reason);
781 template <
typename TId>
782 MsgPtr createMsgInternal(TId&&
id,
unsigned idx, CreateFailureReason* reason)
784 using IdType =
typename std::decay<
decltype(id)>::type;
785 return createMsgInternalTagged(std::forward<TId>(
id), idx, reason, IdParamTag<IdType>());
788 template <
typename TId,
typename... TParams>
789 MsgPtr createGenericMsgInternalTagged(TId&&
id,
unsigned idx, IdParamAsIsTag<TParams...>)
791 return m_factory.createGenericMsg(std::forward<TId>(
id), idx);
794 template <
typename TId,
typename... TParams>
795 MsgPtr createGenericMsgInternalTagged(TId&&
id,
unsigned idx, IdParamCastTag<TParams...>)
797 return m_factory.createGenericMsg(
static_cast<MsgIdType>(
id), idx);
800 template <
typename TId>
801 MsgPtr createGenericMsgInternal(TId&&
id,
unsigned idx)
803 using IdType =
typename std::decay<
decltype(id)>::type;
804 return createGenericMsgInternalTagged(std::forward<TId>(
id), idx, IdParamTag<IdType>());
807 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
814 TNextLayerReader&& nextLayerReader,
819 static_cast<void>(field);
820 static_cast<void>(msgIdx);
821 static_cast<void>(msg);
822 static_cast<void>(iter);
823 static_cast<void>(size);
824 static_cast<void>(nextLayerReader);
828 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
835 TNextLayerReader&& nextLayerReader,
838 TExtraValues... extraValues)
840 using GenericMsgType =
typename MsgFactory::GenericMessage;
842 auto& thisObj = BaseImpl::thisLayer();
843 auto id = thisObj.getMsgIdFromField(field);
844 msg = createGenericMsgInternal(
id, msgIdx);
849 thisObj.beforeRead(field, *msg);
852 typename comms::util::LazyShallowConditional<
853 GenericMsgType::hasRead()
864 std::forward<TNextLayerReader>(nextLayerReader),
869 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
874 TNextLayerReader&& nextLayerReader,
876 TExtraValues... extraValues)
878 return nextLayerReader.read(msg, iter, size, extraValues...);
881 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
886 TNextLayerReader&& nextLayerReader,
888 TExtraValues... extraValues)
890 using GenericMsgType =
typename MsgFactory::GenericMessage;
891 auto& castedMsgRef =
static_cast<GenericMsgType&
>(*msg);
892 return nextLayerReader.read(castedMsgRef, iter, size, extraValues...);
895 template <
typename TId,
typename... TParams>
896 std::size_t msgCountInternalTagged(TId&&
id, IdParamAsIsTag<TParams...>)
898 return m_factory.msgCount(std::forward<TId>(
id));
901 template <
typename TId,
typename... TParams>
902 std::size_t msgCountInternalTagged(TId&&
id, IdParamCastTag<TParams...>)
904 return m_factory.msgCount(
static_cast<MsgIdType>(
id));
907 template <
typename TId>
908 std::size_t msgCountInternal(TId&&
id)
910 using IdType =
typename std::decay<
decltype(id)>::type;
911 return msgCountInternalTagged(std::forward<TId>(
id), IdParamTag<IdType>());
914 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter,
typename... TParams>
920 TNextLayerWriter&& nextLayerWriter,
921 DirectOpTag<TParams...>)
const
923 static_cast<void>(field);
924 return nextLayerWriter.write(msg, iter, size);
927 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter,
typename... TParams>
933 TNextLayerWriter&& nextLayerWriter,
934 StaticBinSearchOpTag<TParams...>)
const
936 auto& thisObj = BaseImpl::thisLayer();
937 auto handler = makeWriteRedirectionHandler(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
938 auto id = thisObj.getMsgIdFromField(field);
942 MsgFactory m_factory;