24 #include "comms/details/tag.h"
25 #include "comms/protocol/details/ProtocolLayerBase.h"
26 #include "comms/protocol/details/MsgIdLayerOptionsParser.h"
27 #include "comms/protocol/details/ProtocolLayerExtendingClassHelper.h"
34 COMMS_MSVC_WARNING_PUSH
35 COMMS_MSVC_WARNING_DISABLE(4100)
36 COMMS_MSVC_WARNING_DISABLE(4189)
66 template <
typename TField,
68 typename TAllMessages,
75 details::ProtocolLayerExtendingClassT<
76 MsgIdLayer<TField, TMessage, TAllMessages, TNextLayer, TOptions...>,
77 details::MsgIdLayerOptionsParser<TOptions...>
82 "TAllMessages must be of std::tuple type");
88 details::ProtocolLayerExtendingClassT<
89 MsgIdLayer<TField, TMessage, TAllMessages, TNextLayer, TOptions...>,
90 details::MsgIdLayerOptionsParser<TOptions...>
94 static_assert(TMessage::hasMsgIdType(),
95 "Usage of MsgIdLayer requires support for ID type. "
96 "Use comms::option::def::MsgIdType option in message interface type definition.");
98 using ParsedOptionsInternal = details::MsgIdLayerOptionsParser<TOptions...>;
153 static constexpr
bool hasExtendingClass()
155 return ParsedOptionsInternal::HasExtendingClass;
163 return ParsedOptionsInternal::HasMsgFactory;
204 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
210 TNextLayerReader&& nextLayerReader,
211 TExtraValues... extraValues)
213 auto beforeReadIter = iter;
214 auto& thisObj = BaseImpl::thisLayer();
215 auto* msgPtr = BaseImpl::toMsgPtr(msg);
216 auto es = thisObj.doReadField(msgPtr, field, iter, size);
218 BaseImpl::updateMissingSize(field, size, extraValues...);
221 if (es != ErrorStatus::Success) {
225 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeReadIter, iter));
228 typename comms::util::LazyShallowConditional<
241 std::forward<TNextLayerReader>(nextLayerReader),
272 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
278 TNextLayerWriter&& nextLayerWriter)
const
280 auto& thisObj = BaseImpl::thisLayer();
281 using MsgType =
typename std::decay<decltype(msg)>::type;
282 thisObj.prepareFieldForWrite(
283 getMsgId(msg, IdRetrieveTag<MsgType>()),
287 auto es = thisObj.doWriteField(&msg, field, iter, size);
288 if (es != ErrorStatus::Success) {
295 typename comms::util::LazyShallowConditional<
296 comms::isMessageBase<MsgType>() || MsgType::hasWrite()
302 return writeInternal(field, msg, iter, size - field.length(), std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
317 return factory_.createMsg(
id, idx, reason);
324 return MsgFactory::isDispatchPolymorphic();
331 return MsgFactory::isDispatchStaticBinSearch();
338 return MsgFactory::isDispatchLinearSwitch();
349 return static_cast<MsgIdType>(field.getValue());
362 template <
typename TMsg>
365 static_cast<void>(field);
366 static_cast<void>(msg);
376 template <
typename TMsg>
379 static_cast<void>(msg);
380 static_cast<void>(field);
386 template <
typename... TParams>
387 using PolymorphicOpTag = comms::details::tag::Tag1<>;
389 template <
typename... TParams>
390 using DirectOpTag = comms::details::tag::Tag2<>;
392 template <
typename... TParams>
393 using PointerOpTag = comms::details::tag::Tag3<>;
395 template <
typename... TParams>
396 using StaticBinSearchOpTag = comms::details::tag::Tag4<>;
398 template <
typename TMsg>
399 using IdRetrieveTag =
400 typename comms::util::LazyShallowConditional<
401 details::protocolLayerHasDoGetId<TMsg>()
407 template <
typename... TParams>
408 using IdParamAsIsTag = comms::details::tag::Tag5<>;
410 template <
typename... TParams>
411 using IdParamCastTag = comms::details::tag::Tag6<>;
413 template <
typename TId>
415 typename comms::util::LazyShallowConditional<
416 std::is_base_of<MsgIdType, TId>::value
422 template <
typename... TParams>
423 using HasGenericMsgTag = comms::details::tag::Tag7<>;
425 template <
typename... TParams>
426 using NoGenericMsgTag = comms::details::tag::Tag8<>;
428 template <
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
429 class ReadRedirectionHandler
434 ReadRedirectionHandler(
437 TNextLayerReader&& nextLayerReader,
438 TExtraValues... extraValues)
441 m_nextLayerReader(std::forward<TNextLayerReader>(nextLayerReader)),
442 m_extraValues(extraValues...)
446 template <
typename TMsg>
447 RetType handle(TMsg& msg)
449 static_assert(comms::isMessageBase<TMsg>(),
"Expected to be a valid message object");
450 return handleInternal(msg, m_extraValues);
453 RetType handle(TMessage& msg)
455 static_cast<void>(msg);
456 static constexpr
bool Should_not_happen =
false;
457 static_cast<void>(Should_not_happen);
463 template <
typename TMsg>
464 RetType handleInternal(TMsg& msg, std::tuple<>&)
466 return m_nextLayerReader.read(msg, m_iter, m_size);
469 template <
typename TMsg,
typename T0>
470 RetType handleInternal(TMsg& msg, std::tuple<T0>& extraValues)
472 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues));
475 template <
typename TMsg,
typename T0,
typename T1>
476 RetType handleInternal(TMsg& msg, std::tuple<T0, T1>& extraValues)
478 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues), std::get<1>(extraValues));
481 template <
typename TMsg,
typename T0,
typename T1,
typename T2>
482 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2>& extraValues)
485 m_nextLayerReader.read(
489 std::get<0>(extraValues),
490 std::get<1>(extraValues),
491 std::get<2>(extraValues));
494 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3>
495 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3>& extraValues)
498 m_nextLayerReader.read(
502 std::get<0>(extraValues),
503 std::get<1>(extraValues),
504 std::get<2>(extraValues),
505 std::get<3>(extraValues));
508 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3,
typename T4>
509 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4>& extraValues)
512 m_nextLayerReader.read(
516 std::get<0>(extraValues),
517 std::get<1>(extraValues),
518 std::get<2>(extraValues),
519 std::get<3>(extraValues),
520 std::get<4>(extraValues));
523 template <
typename TMsg,
typename T0,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
524 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4, T5>& extraValues)
527 m_nextLayerReader.read(
531 std::get<0>(extraValues),
532 std::get<1>(extraValues),
533 std::get<2>(extraValues),
534 std::get<3>(extraValues),
535 std::get<4>(extraValues),
536 std::get<5>(extraValues));
540 std::size_t m_size = 0U;
541 TNextLayerReader&& m_nextLayerReader;
542 std::tuple<TExtraValues...> m_extraValues;
545 template <
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
546 ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...> makeReadRedirectionHandler(
549 TNextLayerReader&& nextLayerReader,
550 TExtraValues... extraValues)
552 return ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...>(iter, size, std::forward<TNextLayerReader>(nextLayerReader), extraValues...);
555 template <
typename TIter,
typename TNextLayerWriter>
556 class WriteRedirectionHandler
561 WriteRedirectionHandler(
564 TNextLayerWriter&& nextLayerWriter)
567 m_nextLayerWriter(std::forward<TNextLayerWriter>(nextLayerWriter))
571 template <
typename TMsg>
572 RetType handle(
const TMsg& msg)
574 static_assert(comms::isMessageBase<TMsg>(),
"Expected to be a valid message object");
575 return m_nextLayerWriter.write(msg, m_iter, m_size);
578 RetType handle(
const TMessage& msg)
580 static_cast<void>(msg);
581 static constexpr
bool Should_not_happen =
false;
582 static_cast<void>(Should_not_happen);
589 std::size_t m_size = 0U;
590 TNextLayerWriter&& m_nextLayerWriter;
593 template <
typename TIter,
typename TNextLayerWriter>
594 WriteRedirectionHandler<TIter, TNextLayerWriter> makeWriteRedirectionHandler(
597 TNextLayerWriter&& nextLayerWriter)
599 return WriteRedirectionHandler<TIter, TNextLayerWriter>(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
602 template <
typename TMsg,
typename... TParams>
603 static MsgIdParamType getMsgId(
const TMsg& msg, PolymorphicOpTag<TParams...>)
605 using MsgType =
typename std::decay<decltype(msg)>::type;
606 static_assert(comms::isMessage<MsgType>(),
607 "The message class is expected to inherit from comms::Message");
608 static_assert(MsgType::hasGetId(),
609 "The message interface class must expose polymorphic ID retrieval functionality, "
610 "use comms::option::app::IdInfoInterface option to define it.");
615 template <
typename TMsg,
typename... TParams>
616 static constexpr MsgIdParamType getMsgId(
const TMsg& msg, DirectOpTag<TParams...>)
618 return msg.doGetId();
621 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
627 TNextLayerReader&& nextLayerReader,
628 TExtraValues... extraValues)
630 using MsgType =
typename std::decay<decltype(msg)>::type;
631 static_assert(details::protocolLayerHasDoGetId<MsgType>(),
632 "Explicit message type is expected to expose compile type message ID by "
633 "using \"StaticNumIdImpl\" option");
635 auto& thisObj = BaseImpl::thisLayer();
636 auto id = thisObj.getMsgIdFromField(field);
637 BaseImpl::setMsgId(
id, extraValues...);
638 if (
id != MsgType::doGetId()) {
639 return ErrorStatus::InvalidMsgId;
642 thisObj.beforeRead(field, msg);
643 return nextLayerReader.read(msg, iter, size, extraValues...);
646 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
653 TNextLayerReader&& nextLayerReader,
655 TExtraValues... extraValues)
657 static_cast<void>(id);
658 static_cast<void>(idx);
659 return nextLayerReader.read(msg, iter, size, extraValues...);
662 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
668 TNextLayerReader&& nextLayerReader,
670 TExtraValues... extraValues)
673 doReadInternalDirect(
678 std::forward<TNextLayerReader>(nextLayerReader),
682 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
688 TNextLayerReader&& nextLayerReader,
690 TExtraValues... extraValues)
692 using MsgType =
typename std::decay<decltype(msg)>::type;
693 static_assert(comms::details::hasElementType<MsgType>(),
694 "Unsupported type of message object, expected to be either message itself or smart pointer");
696 using MsgElementType =
typename MsgType::element_type;
703 typename comms::util::LazyShallowConditional<
704 MsgElementType::hasRead()
710 auto& thisObj = BaseImpl::thisLayer();
711 const auto id = thisObj.getMsgIdFromField(field);
712 BaseImpl::setMsgId(
id, extraValues...);
716 CreateFailureReason failureReason = CreateFailureReason::None;
719 msg = createMsgInternal(
id, idx, &failureReason);
724 using IterType =
typename std::decay<decltype(iter)>::type;
725 static_assert(std::is_same<
typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
726 "Iterator used for reading is expected to be random access one");
727 IterType readStart = iter;
729 thisObj.beforeRead(field, *msg);
730 es = doReadInternal(
id, idx, msg, iter, size, std::forward<TNextLayerReader>(nextLayerReader), Tag(), extraValues...);
732 BaseImpl::setMsgIndex(idx, extraValues...);
741 BaseImpl::setMsgIndex(idx, extraValues...);
743 if (failureReason == CreateFailureReason::AllocFailure) {
747 COMMS_ASSERT(failureReason == CreateFailureReason::InvalidId);
748 using GenericMsgTag =
749 typename comms::util::LazyShallowConditional<
750 MsgFactory::hasGenericMessageSupport()
756 return createAndReadGenericMsgInternal(
762 std::forward<TNextLayerReader>(nextLayerReader),
768 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
775 TNextLayerReader&& nextLayerReader,
776 StaticBinSearchOpTag<>,
777 TExtraValues... extraValues)
780 makeReadRedirectionHandler(
783 std::forward<TNextLayerReader>(nextLayerReader),
785 return comms::dispatchMsgStaticBinSearch<AllMessages>(
id, idx, *msg, handler);
788 template <
typename TId,
typename... TParams>
789 MsgPtr createMsgInternalTagged(TId&&
id,
unsigned idx, CreateFailureReason* reason, IdParamAsIsTag<TParams...>)
791 return createMsg(std::forward<TId>(
id), idx, reason);
794 template <
typename TId,
typename... TParams>
795 MsgPtr createMsgInternalTagged(TId&&
id,
unsigned idx, CreateFailureReason* reason, IdParamCastTag<TParams...>)
797 return createMsg(
static_cast<MsgIdType>(
id), idx, reason);
800 template <
typename TId>
801 MsgPtr createMsgInternal(TId&&
id,
unsigned idx, CreateFailureReason* reason)
803 using IdType =
typename std::decay<decltype(
id)>::type;
804 return createMsgInternalTagged(std::forward<TId>(
id), idx, reason, IdParamTag<IdType>());
807 template <
typename TId,
typename... TParams>
808 MsgPtr createGenericMsgInternalTagged(TId&&
id,
unsigned idx, IdParamAsIsTag<TParams...>)
810 return factory_.createGenericMsg(std::forward<TId>(
id), idx);
813 template <
typename TId,
typename... TParams>
814 MsgPtr createGenericMsgInternalTagged(TId&&
id,
unsigned idx, IdParamCastTag<TParams...>)
816 return factory_.createGenericMsg(
static_cast<MsgIdType>(
id), idx);
819 template <
typename TId>
820 MsgPtr createGenericMsgInternal(TId&&
id,
unsigned idx)
822 using IdType =
typename std::decay<decltype(
id)>::type;
823 return createGenericMsgInternalTagged(std::forward<TId>(
id), idx, IdParamTag<IdType>());
826 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
833 TNextLayerReader&& nextLayerReader,
838 static_cast<void>(field);
839 static_cast<void>(msgIdx);
840 static_cast<void>(msg);
841 static_cast<void>(iter);
842 static_cast<void>(size);
843 static_cast<void>(nextLayerReader);
847 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
854 TNextLayerReader&& nextLayerReader,
857 TExtraValues... extraValues)
859 using GenericMsgType =
typename MsgFactory::GenericMessage;
861 auto& thisObj = BaseImpl::thisLayer();
862 auto id = thisObj.getMsgIdFromField(field);
863 msg = createGenericMsgInternal(
id, msgIdx);
868 thisObj.beforeRead(field, *msg);
871 typename comms::util::LazyShallowConditional<
872 GenericMsgType::hasRead()
883 std::forward<TNextLayerReader>(nextLayerReader),
888 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
893 TNextLayerReader&& nextLayerReader,
895 TExtraValues... extraValues)
897 return nextLayerReader.read(msg, iter, size, extraValues...);
900 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
905 TNextLayerReader&& nextLayerReader,
907 TExtraValues... extraValues)
909 using GenericMsgType =
typename MsgFactory::GenericMessage;
910 auto& castedMsgRef =
static_cast<GenericMsgType&
>(*msg);
911 return nextLayerReader.read(castedMsgRef, iter, size, extraValues...);
914 template <
typename TId,
typename... TParams>
915 std::size_t msgCountInternalTagged(TId&&
id, IdParamAsIsTag<TParams...>)
917 return factory_.msgCount(std::forward<TId>(
id));
920 template <
typename TId,
typename... TParams>
921 std::size_t msgCountInternalTagged(TId&&
id, IdParamCastTag<TParams...>)
923 return factory_.msgCount(
static_cast<MsgIdType>(
id));
927 template <
typename TId>
928 std::size_t msgCountInternal(TId&&
id)
930 using IdType =
typename std::decay<decltype(
id)>::type;
931 return msgCountInternalTagged(std::forward<TId>(
id), IdParamTag<IdType>());
934 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter,
typename... TParams>
940 TNextLayerWriter&& nextLayerWriter,
941 DirectOpTag<TParams...>)
const
943 static_cast<void>(field);
944 return nextLayerWriter.write(msg, iter, size);
948 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter,
typename... TParams>
954 TNextLayerWriter&& nextLayerWriter,
955 StaticBinSearchOpTag<TParams...>)
const
957 auto& thisObj = BaseImpl::thisLayer();
958 auto handler = makeWriteRedirectionHandler(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
959 auto id = thisObj.getMsgIdFromField(field);
969 template <
typename T>
970 struct MsgIdLayerCheckHelper
972 static const bool Value =
false;
975 template <
typename TField,
977 typename TAllMessages,
979 typename... TOptions>
980 struct MsgIdLayerCheckHelper<MsgIdLayer<TField, TMessage, TAllMessages, TNextLayer, TOptions...> >
982 static const bool Value =
true;
990 template <
typename T>
993 return details::MsgIdLayerCheckHelper<T>::Value;
1000 COMMS_MSVC_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition: Assert.h:170
Contains various compiler related definitions.
Provides common base class for the custom messages with default implementation.
Contains definition of comms::MsgFactory class.
Contains various tuple type manipulation classes and functions.
typename BaseImpl::MsgIdParamType MsgIdParamType
Type used for message ID passed as parameter or returned from function.
Definition: Message.h:203
typename Base::MsgPtr MsgPtr
Smart pointer to Message which holds allocated message object.
Definition: MsgFactory.h:109
Protocol layer that uses uses message ID field as a prefix to all the subsequent data written by othe...
Definition: MsgIdLayer.h:80
static void prepareFieldForWrite(MsgIdParamType id, const TMsg &msg, Field &field)
Prepare field for writing.
Definition: MsgIdLayer.h:377
static MsgIdType getMsgIdFromField(const Field &field)
Retrieve message id from the field.
Definition: MsgIdLayer.h:347
typename Message::MsgIdParamType MsgIdParamType
Type of message ID when passed by the parameter.
Definition: MsgIdLayer.h:123
typename MsgFactory::CreateFailureReason CreateFailureReason
Reason for message creation failure.
Definition: MsgIdLayer.h:129
MsgIdLayer & operator=(const MsgIdLayer &)=default
Copy assignment.
static constexpr bool hasMsgFactory()
Compile time inquiry of whether custom message factory class has been provided via comms::option::app...
Definition: MsgIdLayer.h:161
typename MsgFactory::MsgPtr MsgPtr
Type of smart pointer that will hold allocated message object.
Definition: MsgIdLayer.h:114
MsgIdLayer(MsgIdLayer &&)=default
Move constructor.
typename Message::MsgIdType MsgIdType
Type of message ID.
Definition: MsgIdLayer.h:120
~MsgIdLayer() noexcept=default
Destructor.
TMessage Message
Type of the input message interface.
Definition: MsgIdLayer.h:117
static constexpr bool isDispatchStaticBinSearch()
Compile time inquiry whether static binary search dispatch is generated internally to map message ID ...
Definition: MsgIdLayer.h:329
ErrorStatus doWrite(Field &field, const TMsg &msg, TIter &iter, std::size_t size, TNextLayerWriter &&nextLayerWriter) const
Customized write functionality, invoked by write().
Definition: MsgIdLayer.h:273
static constexpr bool isDispatchPolymorphic()
Compile time inquiry whether polymorphic dispatch tables are generated internally to map message ID t...
Definition: MsgIdLayer.h:322
MsgIdLayer & operator=(MsgIdLayer &&)=default
Move assignment.
constexpr bool isMsgIdLayer()
Compile time check of whether the provided type is a variant of MsgIdLayer.
Definition: MsgIdLayer.h:991
MsgIdLayer()=default
Default constructor.
MsgPtr createMsg(MsgIdParamType id, unsigned idx=0, CreateFailureReason *reason=nullptr)
Create message object given the ID.
Definition: MsgIdLayer.h:315
MsgIdLayer(const MsgIdLayer &)=default
Copy constructor.
static void beforeRead(const Field &field, TMsg &msg)
Extra operation before read.
Definition: MsgIdLayer.h:363
TAllMessages AllMessages
All supported message types bundled in std::tuple.
Definition: MsgIdLayer.h:110
typename BaseImpl::Field Field
Type of the field object used to read/write message ID value.
Definition: MsgIdLayer.h:126
typename ParsedOptionsInternal::ExtendingClass ExtendingClass
Type of real extending class.
Definition: MsgIdLayer.h:107
static constexpr bool isDispatchLinearSwitch()
Compile time inquiry whether linear switch dispatch is generated internally to map message ID to actu...
Definition: MsgIdLayer.h:336
comms::ErrorStatus doRead(Field &field, TMsg &msg, TIter &iter, std::size_t size, TNextLayerReader &&nextLayerReader, TExtraValues... extraValues)
Customized read functionality, invoked by read().
Definition: MsgIdLayer.h:205
Base class for all the middle (non MsgDataLayer) protocol transport layers.
Definition: ProtocolLayerBase.h:61
TField Field
Type of the field used for this layer.
Definition: ProtocolLayerBase.h:64
Contains extra logic to help with dispatching message types and objects.
This file provides all the definitions from comms::field namespace.
comms::option::def::ExtendingClass< T > ExtendingClass
Same as comms::option::def::ExtendingClass.
Definition: options.h:1822
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition: options.h:1459
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition: options.h:1448
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition: ErrorStatus.h:17
@ MsgAllocFailure
Used to indicate that message allocation has failed.
@ Success
Used to indicate successful outcome of the operation.
@ InvalidMsgId
Used to indicate that received message has unknown id.
auto dispatchMsgStaticBinSearch(TId &&id, std::size_t index, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using static binar...
Definition: dispatch.h:166
constexpr bool isMessageBase()
Compile time check of of whether the type is a message extending comms::MessageBase.
Definition: MessageBase.h:899
MsgFactoryCreateFailureReason
Definition: MsgFactoryCreateFailureReason.h:18
Check whether provided type is a variant of std::tuple.
Definition: Tuple.h:35
Replacement to some types from standard type_traits.