72class MsgIdLayer :
public comms::frame::details::MsgIdLayerBase<TField, TMessage, TAllMessages, TNextLayer, TOptions...>
75 "TAllMessages must be of std::tuple type");
77 static_assert(TMessage::hasMsgIdType(),
78 "Usage of MsgIdLayer requires support for ID type. "
79 "Use comms::option::def::MsgIdType option in message interface type definition.");
81 using BaseImpl = comms::frame::details::MsgIdLayerBase<TField, TMessage, TAllMessages, TNextLayer, TOptions...>;
82 using ParsedOptionsInternal = details::MsgIdLayerOptionsParser<TOptions...>;
105 using Field =
typename BaseImpl::Field;
130 static constexpr
bool hasExtendingClass()
132 return ParsedOptionsInternal::HasExtendingClass;
140 return ParsedOptionsInternal::HasMsgFactory;
181 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
187 TNextLayerReader&& nextLayerReader,
188 TExtraValues... extraValues)
190 auto beforeReadIter = iter;
191 auto& thisObj = BaseImpl::thisLayer();
192 auto* msgPtr = BaseImpl::toMsgPtr(msg);
193 auto es = thisObj.doReadField(msgPtr, field, iter, size);
195 BaseImpl::updateMissingSize(field, size, extraValues...);
198 if (es != ErrorStatus::Success) {
202 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeReadIter, iter));
205 typename comms::util::LazyShallowConditional<
218 std::forward<TNextLayerReader>(nextLayerReader),
249 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
255 TNextLayerWriter&& nextLayerWriter)
const
257 auto& thisObj = BaseImpl::thisLayer();
258 using MsgType =
typename std::decay<
decltype(msg)>::type;
259 static_assert(comms::isMessage<MsgType>(),
"The message type must extend comms::Message");
260 thisObj.prepareFieldForWrite(
261 getMsgId(msg, IdRetrieveTag<MsgType>()),
265 auto es = thisObj.doWriteField(&msg, field, iter, size);
266 if (es != ErrorStatus::Success) {
273 typename comms::util::LazyShallowConditional<
274 comms::isMessageBase<MsgType>() || MsgType::hasWrite()
280 return writeInternal(field, msg, iter, size - field.length(), std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
295 return m_factory.createMsg(
id, idx, reason);
302 return MsgFactory::isDispatchPolymorphic();
309 return MsgFactory::isDispatchStaticBinSearch();
316 return MsgFactory::isDispatchLinearSwitch();
327 return static_cast<MsgIdType>(field.getValue());
340 template <
typename TMsg>
343 static_cast<void>(field);
344 static_cast<void>(msg);
354 template <
typename TMsg>
357 static_cast<void>(msg);
358 static_cast<void>(field);
364 template <
typename... TParams>
365 using PolymorphicOpTag = comms::details::tag::Tag1<>;
367 template <
typename... TParams>
368 using DirectOpTag = comms::details::tag::Tag2<>;
370 template <
typename... TParams>
371 using PointerOpTag = comms::details::tag::Tag3<>;
373 template <
typename... TParams>
374 using StaticBinSearchOpTag = comms::details::tag::Tag4<>;
376 template <
typename TMsg>
377 using IdRetrieveTag =
378 typename comms::util::LazyShallowConditional<
379 comms::isMessageBase<TMsg>()
385 template <
typename... TParams>
386 using IdParamAsIsTag = comms::details::tag::Tag5<>;
388 template <
typename... TParams>
389 using IdParamCastTag = comms::details::tag::Tag6<>;
391 template <
typename TId>
393 typename comms::util::LazyShallowConditional<
394 std::is_base_of<MsgIdType, TId>::value
400 template <
typename... TParams>
401 using HasGenericMsgTag = comms::details::tag::Tag7<>;
403 template <
typename... TParams>
404 using NoGenericMsgTag = comms::details::tag::Tag8<>;
406 template <
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
407 class ReadRedirectionHandler
412 ReadRedirectionHandler(
415 TNextLayerReader&& nextLayerReader,
416 TExtraValues... extraValues)
419 m_nextLayerReader(
std::forward<TNextLayerReader>(nextLayerReader)),
420 m_extraValues(extraValues...)
424 template <
typename TMsg>
425 RetType handle(TMsg& msg)
427 static_assert(comms::isMessageBase<TMsg>(),
"Expected to be a valid message object");
428 return handleInternal(msg, m_extraValues);
431 RetType handle(TMessage& msg)
433 static_cast<void>(msg);
434 static constexpr bool Should_not_happen =
false;
435 static_cast<void>(Should_not_happen);
441 template <
typename TMsg>
442 RetType handleInternal(TMsg& msg, std::tuple<>&)
444 return m_nextLayerReader.read(msg, m_iter, m_size);
447 template <
typename TMsg,
typename T0>
448 RetType handleInternal(TMsg& msg, std::tuple<T0>& extraValues)
450 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues));
453 template <
typename TMsg,
typename T0,
typename T1>
454 RetType handleInternal(TMsg& msg, std::tuple<T0, T1>& extraValues)
456 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues), std::get<1>(extraValues));
459 template <
typename TMsg,
typename T0,
typename T1,
typename T2>
460 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2>& extraValues)
463 m_nextLayerReader.read(
467 std::get<0>(extraValues),
468 std::get<1>(extraValues),
469 std::get<2>(extraValues));
472 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3>
473 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3>& extraValues)
476 m_nextLayerReader.read(
480 std::get<0>(extraValues),
481 std::get<1>(extraValues),
482 std::get<2>(extraValues),
483 std::get<3>(extraValues));
486 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3,
typename T4>
487 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4>& extraValues)
490 m_nextLayerReader.read(
494 std::get<0>(extraValues),
495 std::get<1>(extraValues),
496 std::get<2>(extraValues),
497 std::get<3>(extraValues),
498 std::get<4>(extraValues));
501 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
502 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4, T5>& extraValues)
505 m_nextLayerReader.read(
509 std::get<0>(extraValues),
510 std::get<1>(extraValues),
511 std::get<2>(extraValues),
512 std::get<3>(extraValues),
513 std::get<4>(extraValues),
514 std::get<5>(extraValues));
518 std::size_t m_size = 0U;
519 TNextLayerReader&& m_nextLayerReader;
520 std::tuple<TExtraValues...> m_extraValues;
523 template <
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
524 ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...> makeReadRedirectionHandler(
527 TNextLayerReader&& nextLayerReader,
528 TExtraValues... extraValues)
530 return ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...>(iter, size, std::forward<TNextLayerReader>(nextLayerReader), extraValues...);
533 template <
typename TIter,
typename TNextLayerWriter>
534 class WriteRedirectionHandler
539 WriteRedirectionHandler(
542 TNextLayerWriter&& nextLayerWriter)
545 m_nextLayerWriter(
std::forward<TNextLayerWriter>(nextLayerWriter))
549 template <
typename TMsg>
550 RetType handle(
const TMsg& msg)
552 static_assert(comms::isMessageBase<TMsg>(),
"Expected to be a valid message object");
553 return m_nextLayerWriter.write(msg, m_iter, m_size);
556 RetType handle(
const TMessage& msg)
558 static_cast<void>(msg);
559 static constexpr bool Should_not_happen =
false;
560 static_cast<void>(Should_not_happen);
567 std::size_t m_size = 0U;
568 TNextLayerWriter&& m_nextLayerWriter;
571 template <
typename TIter,
typename TNextLayerWriter>
572 WriteRedirectionHandler<TIter, TNextLayerWriter> makeWriteRedirectionHandler(
575 TNextLayerWriter&& nextLayerWriter)
577 return WriteRedirectionHandler<TIter, TNextLayerWriter>(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
580 template <
typename TMsg,
typename... TParams>
581 static MsgIdParamType getMsgId(
const TMsg& msg, PolymorphicOpTag<TParams...>)
583 using MsgType =
typename std::decay<
decltype(msg)>::type;
584 static_assert(comms::isMessage<MsgType>(),
585 "The message class is expected to inherit from comms::Message");
586 static_assert(MsgType::hasGetId(),
587 "The message interface class must expose polymorphic ID retrieval functionality, "
588 "use comms::option::app::IdInfoInterface option to define it.");
593 template <
typename TMsg,
typename... TParams>
594 static constexpr MsgIdParamType getMsgId(
const TMsg& msg, DirectOpTag<TParams...>)
596 using MsgType =
typename std::decay<
decltype(msg)>::type;
597 static_assert(comms::isMessageBase<MsgType>(),
598 "The message class is expected to inherit from comms::MessageBase");
599 static_assert(MsgType::hasDoGetId(),
600 "The message class must expose direct ID retrieval functionality, "
601 "use comms::option::app::StaticNumIdImpl option to define it or "
602 "comms::option::app::HasDoGetId option to mark the class as providing one");
603 return msg.doGetId();
606 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
612 TNextLayerReader&& nextLayerReader,
613 TExtraValues... extraValues)
615 static_assert((!details::hasMsgIndexRetriever<TExtraValues...>()) || (comms::details::allMessagesAreStrongSorted<AllMessages>()),
616 "Message type index cannot be retrieved with direct message object invocation");
617 auto& thisObj = BaseImpl::thisLayer();
618 auto id = thisObj.getMsgIdFromField(field);
619 BaseImpl::setMsgId(
id, extraValues...);
620 BaseImpl::setMsgIndex(0U, extraValues...);
622 using MsgType =
typename std::decay<
decltype(msg)>::type;
623 if (
id != getMsgId(msg, IdRetrieveTag<MsgType>())) {
624 return ErrorStatus::InvalidMsgId;
627 thisObj.beforeRead(field, msg);
628 return nextLayerReader.read(msg, iter, size, extraValues...);
631 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
638 TNextLayerReader&& nextLayerReader,
640 TExtraValues... extraValues)
642 static_cast<void>(id);
643 static_cast<void>(idx);
644 return nextLayerReader.read(msg, iter, size, extraValues...);
647 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
653 TNextLayerReader&& nextLayerReader,
655 TExtraValues... extraValues)
658 doReadInternalDirect(
663 std::forward<TNextLayerReader>(nextLayerReader),
667 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
673 TNextLayerReader&& nextLayerReader,
675 TExtraValues... extraValues)
677 using MsgType =
typename std::decay<
decltype(msg)>::type;
678 static_assert(comms::details::hasElementType<MsgType>(),
679 "Unsupported type of message object, expected to be either message itself or smart pointer");
681 using MsgElementType =
typename MsgType::element_type;
684 typename comms::util::LazyShallowConditional<
685 MsgElementType::hasRead()
691 auto& thisObj = BaseImpl::thisLayer();
692 const auto id = thisObj.getMsgIdFromField(field);
693 BaseImpl::setMsgId(
id, extraValues...);
697 CreateFailureReason failureReason = CreateFailureReason::None;
700 msg = createMsgInternal(
id, idx, &failureReason);
705 using IterType =
typename std::decay<
decltype(iter)>::type;
706 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
707 "Iterator used for reading is expected to be random access one");
708 IterType readStart = iter;
710 thisObj.beforeRead(field, *msg);
711 es = doReadInternal(
id, idx, msg, iter, size, std::forward<TNextLayerReader>(nextLayerReader), Tag(), extraValues...);
713 BaseImpl::setMsgIndex(idx, extraValues...);
722 BaseImpl::setMsgIndex(idx, extraValues...);
724 if (failureReason == CreateFailureReason::AllocFailure) {
728 COMMS_ASSERT(failureReason == CreateFailureReason::InvalidId);
729 using GenericMsgTag =
730 typename comms::util::LazyShallowConditional<
731 MsgFactory::hasGenericMessageSupport()
738 createAndReadGenericMsgInternal(
744 std::forward<TNextLayerReader>(nextLayerReader),
750 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
757 TNextLayerReader&& nextLayerReader,
758 StaticBinSearchOpTag<>,
759 TExtraValues... extraValues)
762 makeReadRedirectionHandler(
765 std::forward<TNextLayerReader>(nextLayerReader),
767 return comms::dispatchMsgStaticBinSearch<AllMessages>(
id, idx, *msg, handler);
770 template <
typename TId,
typename... TParams>
771 MsgPtr createMsgInternalTagged(TId&&
id,
unsigned idx, CreateFailureReason* reason, IdParamAsIsTag<TParams...>)
773 return createMsg(std::forward<TId>(
id), idx, reason);
776 template <
typename TId,
typename... TParams>
777 MsgPtr createMsgInternalTagged(TId&&
id,
unsigned idx, CreateFailureReason* reason, IdParamCastTag<TParams...>)
779 return createMsg(
static_cast<MsgIdType>(
id), idx, reason);
782 template <
typename TId>
783 MsgPtr createMsgInternal(TId&&
id,
unsigned idx, CreateFailureReason* reason)
785 using IdType =
typename std::decay<
decltype(id)>::type;
786 return createMsgInternalTagged(std::forward<TId>(
id), idx, reason, IdParamTag<IdType>());
789 template <
typename TId,
typename... TParams>
790 MsgPtr createGenericMsgInternalTagged(TId&&
id,
unsigned idx, IdParamAsIsTag<TParams...>)
792 return m_factory.createGenericMsg(std::forward<TId>(
id), idx);
795 template <
typename TId,
typename... TParams>
796 MsgPtr createGenericMsgInternalTagged(TId&&
id,
unsigned idx, IdParamCastTag<TParams...>)
798 return m_factory.createGenericMsg(
static_cast<MsgIdType>(
id), idx);
801 template <
typename TId>
802 MsgPtr createGenericMsgInternal(TId&&
id,
unsigned idx)
804 using IdType =
typename std::decay<
decltype(id)>::type;
805 return createGenericMsgInternalTagged(std::forward<TId>(
id), idx, IdParamTag<IdType>());
808 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
815 TNextLayerReader&& nextLayerReader,
820 static_cast<void>(field);
821 static_cast<void>(msgIdx);
822 static_cast<void>(msg);
823 static_cast<void>(iter);
824 static_cast<void>(size);
825 static_cast<void>(nextLayerReader);
829 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
836 TNextLayerReader&& nextLayerReader,
839 TExtraValues... extraValues)
841 using GenericMsgType =
typename MsgFactory::GenericMessage;
843 auto& thisObj = BaseImpl::thisLayer();
844 auto id = thisObj.getMsgIdFromField(field);
845 msg = createGenericMsgInternal(
id, msgIdx);
850 thisObj.beforeRead(field, *msg);
853 typename comms::util::LazyShallowConditional<
854 GenericMsgType::hasRead()
865 std::forward<TNextLayerReader>(nextLayerReader),
870 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
875 TNextLayerReader&& nextLayerReader,
877 TExtraValues... extraValues)
879 return nextLayerReader.read(msg, iter, size, extraValues...);
882 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
887 TNextLayerReader&& nextLayerReader,
889 TExtraValues... extraValues)
891 using GenericMsgType =
typename MsgFactory::GenericMessage;
892 auto& castedMsgRef =
static_cast<GenericMsgType&
>(*msg);
893 return nextLayerReader.read(castedMsgRef, iter, size, extraValues...);
896 template <
typename TId,
typename... TParams>
897 std::size_t msgCountInternalTagged(TId&&
id, IdParamAsIsTag<TParams...>)
899 return m_factory.msgCount(std::forward<TId>(
id));
902 template <
typename TId,
typename... TParams>
903 std::size_t msgCountInternalTagged(TId&&
id, IdParamCastTag<TParams...>)
905 return m_factory.msgCount(
static_cast<MsgIdType>(
id));
908 template <
typename TId>
909 std::size_t msgCountInternal(TId&&
id)
911 using IdType =
typename std::decay<
decltype(id)>::type;
912 return msgCountInternalTagged(std::forward<TId>(
id), IdParamTag<IdType>());
915 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter,
typename... TParams>
921 TNextLayerWriter&& nextLayerWriter,
922 DirectOpTag<TParams...>)
const
924 static_cast<void>(field);
925 return nextLayerWriter.write(msg, iter, size);
928 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter,
typename... TParams>
934 TNextLayerWriter&& nextLayerWriter,
935 StaticBinSearchOpTag<TParams...>)
const
937 auto& thisObj = BaseImpl::thisLayer();
938 auto handler = makeWriteRedirectionHandler(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
939 auto id = thisObj.getMsgIdFromField(field);
943 MsgFactory m_factory;