17#include "comms/details/detect.h"
18#include "comms/details/tag.h"
19#include "comms/frame/details/MsgDataLayerOptionsParser.h"
42template <
typename... TOptions>
45 using ParsedOptionsInternal = details::MsgDataLayerOptionsParser<TOptions...>;
68 using Field =
typename ParsedOptionsInternal::FieldType;
129 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
134 TExtraValues... extraValues)
136 using MsgType =
typename std::decay<
decltype(msg)>::type;
139 comms::isMessageBase<MsgType>()
143 comms::isMessage<MsgType>()
146 typename comms::util::LazyShallowConditional<
147 std::is_pointer<MsgType>::value
155 if (setPayloadRequiredInternal(extraValues...)) {
156 auto fromIter = iter;
157 auto es = readInternal(msg, iter, size, Tag(), extraValues...);
158 setMsgPayloadInternal(fromIter,
static_cast<std::size_t
>(std::distance(fromIter, iter)), extraValues...);
162 return readInternal(msg, iter, size, Tag(), extraValues...);
168 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
175 static_cast<void>(msg);
176 static_cast<void>(iter);
177 static_cast<void>(size);
185 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
190 TExtraValues... extraValues)
192 return read(msg, iter, size, extraValues...);
219 template <
typename TAllFields,
typename TMsg,
typename TIter,
typename... TExtraValues>
221 TAllFields& allFields,
225 TExtraValues... extraValues)
229 "Expected TAllFields to be tuple.");
231 using AllFieldsDecayed =
typename std::decay<TAllFields>::type;
232 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(),
"Passed tuple is wrong.");
233 static const std::size_t Idx =
234 std::tuple_size<AllFieldsDecayed>::value -
235 std::tuple_size<AllFields>::value;
237 static_assert((Idx + 1) == std::tuple_size<TAllFields>::value,
238 "All fields must be read when MsgDataLayer is reached");
240 using IterType =
typename std::decay<
decltype(iter)>::type;
241 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
242 static_assert(std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
243 "Caching read from non random access iterators are not supported at this moment.");
245 auto& dataField = std::get<Idx>(allFields);
247 using FieldType =
typename std::decay<
decltype(dataField)>::type;
249 std::is_same<Field, FieldType>::value,
250 "Field has wrong type");
252 auto dataIter = iter;
253 auto es =
read(msg, iter, size, extraValues...);
258 auto dataSize =
static_cast<std::size_t
>(std::distance(dataIter, iter));
259 setMsgPayloadInternal(dataIter, dataSize, extraValues...);
261 auto dataEs = dataField.read(dataIter, dataSize);
262 static_cast<void>(dataEs);
270 template <
typename TAllFields,
typename TMsg,
typename TIter,
typename... TExtraValues>
272 TAllFields& allFields,
278 static_cast<void>(allFields);
279 static_cast<void>(msg);
280 static_cast<void>(iter);
281 static_cast<void>(size);
289 template <
typename TAllFields,
typename TMsg,
typename TIter,
typename... TExtraValues>
291 TAllFields& allFields,
295 TExtraValues... extraValues)
317 template <
typename TMsg,
typename TIter>
323 using MsgType =
typename std::decay<
decltype(msg)>::type;
326 comms::isMessage<MsgType>(),
327 "The provided message object must inherit from comms::Message");
331 comms::isMessageBase<MsgType>()
335 comms::isMessage<MsgType>()
338 typename comms::util::LazyShallowConditional<
339 std::is_pointer<MsgType>::value
347 return writeInternal(msg, iter, size, Tag());
365 template <
typename TAllFields,
typename TMsg,
typename TIter>
367 TAllFields& allFields,
373 "Expected TAllFields to be tuple.");
375 using AllFieldsDecayed =
typename std::decay<TAllFields>::type;
376 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(),
"Passed tuple is wrong.");
377 static const std::size_t Idx =
378 std::tuple_size<AllFieldsDecayed>::value -
379 std::tuple_size<AllFields>::value;
381 static_assert((Idx + 1) == std::tuple_size<TAllFields>::value,
382 "All fields must be written when MsgDataLayer is reached");
384 auto& dataField = std::get<Idx>(allFields);
385 using FieldType =
typename std::decay<
decltype(dataField)>::type;
387 std::is_same<Field, FieldType>::value,
388 "Field has wrong type");
390 using IterType =
typename std::decay<
decltype(iter)>::type;
391 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
392 return writeWithFieldCachedInternal(dataField, msg, iter, size, IterTag());
408 template <
typename TIter>
411 std::advance(iter, size);
421 template <
typename TMsg,
typename TIter>
424 static_cast<void>(msg);
425 return update(iter, size);
441 template <
typename TAllFields,
typename TIter>
443 TAllFields& allFields,
447 static_cast<void>(allFields);
448 std::advance(iter, size);
467 template <
typename TAllFields,
typename TMsg,
typename TIter>
469 TAllFields& allFields,
474 static_cast<void>(allFields);
475 static_cast<void>(msg);
476 std::advance(iter, size);
498 template <
typename TMsg>
499 static constexpr std::size_t
length(
const TMsg& msg)
501 using MsgType =
typename std::decay<
decltype(msg)>::type;
504 comms::isMessage<MsgType>(),
505 "The provided message object must inherit from comms::Message");
508 typename comms::util::LazyShallowConditional<
509 details::FrameLayerHasFieldsImpl<MsgType>::Value
514 return getMsgLength(msg, Tag());
521 template <
typename TAllFields>
523 decltype(std::get<std::tuple_size<typename std::decay<TAllFields>::type>::value - std::tuple_size<AllFields>::value>(allFields))
525 using AllFieldsDecayed =
typename std::decay<TAllFields>::type;
526 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(),
"Passed tuple is wrong.");
527 static const std::size_t Idx =
528 std::tuple_size<AllFieldsDecayed>::value -
529 std::tuple_size<AllFields>::value;
531 return std::get<Idx>(allFields);
535 template <
typename... TParams>
536 using MsgHasLengthTag = comms::details::tag::Tag1<>;
538 template <
typename... TParams>
539 using MsgNoLengthTag = comms::details::tag::Tag2<>;
541 template <
typename... TParams>
542 using MsgDirectLengthTag = comms::details::tag::Tag3<>;
544 template <
typename... TParams>
545 using DirectOpTag = comms::details::tag::Tag4<>;
547 template <
typename... TParams>
548 using InterfaceOpTag = comms::details::tag::Tag5<>;
550 template <
typename... TParams>
551 using PointerOpTag = comms::details::tag::Tag6<>;
553 template <
typename... TParams>
554 using OtherOpTag = comms::details::tag::Tag7<>;
556 template <
typename TMsg,
typename TIter>
562 std::random_access_iterator_tag)
564 return writeWithFieldCachedRandomAccess(field, msg, iter, size);
567 template <
typename TMsg,
typename TIter>
573 std::output_iterator_tag)
575 return writeWithFieldCachedOutput(field, msg, iter, size);
578 template <
typename TMsg,
typename TIter>
579 static ErrorStatus writeWithFieldCachedRandomAccess(
585 auto dataReadIter = iter;
586 auto es =
write(msg, iter, size);
591 auto writtenCount =
static_cast<std::size_t
>(std::distance(dataReadIter, iter));
592 auto dataEs = field.read(dataReadIter, writtenCount);
594 static_cast<void>(dataEs);
598 template <
typename TMsg,
typename TCollection>
602 std::back_insert_iterator<TCollection>& iter,
605 auto es =
write(msg, iter, size);
611 auto dataWriteIter = std::back_inserter(col);
612 auto dataWriteEs =
write(msg, dataWriteIter, size);
614 static_cast<void>(dataWriteEs);
616 auto dataReadIter = col.cbegin();
617 auto dataReadEs = field.read(dataReadIter, col.size());
619 static_cast<void>(dataReadEs);
624 template <
typename TMsg,
typename... TParams>
625 static std::size_t getMsgLength(
const TMsg& msg, MsgHasLengthTag<TParams...>)
627 using MsgType =
typename std::decay<
decltype(msg)>::type;
628 static_assert(MsgType::hasLength(),
"Message interface must define length()");
632 template <
typename TMsg,
typename... TParams>
633 static constexpr std::size_t getMsgLength(
const TMsg& msg, MsgDirectLengthTag<TParams...>)
635 using MsgType =
typename std::decay<
decltype(msg)>::type;
636 static_assert(MsgType::hasFields(),
"FieldsImpl option hasn't been used");
637 return msg.doLength();
640 template <
typename TMsg,
typename... TParams>
641 static constexpr std::size_t getMsgLength(
const TMsg&, MsgNoLengthTag<TParams...>)
646 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
651 TExtraValues... extraValues)
653 using MsgType =
typename std::decay<
decltype(msg)>::type;
656 comms::isMessage<MsgType>(),
657 "The provided message object must inherit from comms::Message");
659 static_assert(MsgType::hasRead(),
660 "Message interface must support polymorphic read operation");
662 using IterType =
typename std::decay<
decltype(iter)>::type;
664 static_assert(std::is_convertible<IterType, typename MsgType::ReadIterator>::value,
665 "The provided iterator is not convertible to ReadIterator defined by Message class");
667 using ReadIter =
typename std::add_lvalue_reference<typename MsgType::ReadIterator>::type;
669 auto result = msg.read(
static_cast<ReadIter
>(iter), size);
671 missingSizeRequiredInternal(extraValues...)) {
673 typename comms::util::LazyShallowConditional<
681 auto msgLen = getMsgLength(msg, Tag());
685 updateMissingSizeInternal(
missingSize, extraValues...);
690 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
695 TExtraValues... extraValues)
697 using MsgType =
typename std::decay<
decltype(msg)>::type;
700 comms::isMessageBase<MsgType>(),
701 "The provided message object must inherit from comms::MessageBase");
703 static_assert(details::frameLayerHasFieldsImpl<MsgType>(),
704 "Message class must use FieldsImpl option");
706 auto result = msg.doRead(iter, size);
708 (missingSizeRequiredInternal(extraValues...))) {
710 auto msgLen = getMsgLength(msg, MsgDirectLengthTag<>());
714 updateMissingSizeInternal(
missingSize, extraValues...);
719 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
725 TExtraValues... extraValues)
727 return readInternalDirect(msg, iter, size, extraValues...);
730 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
736 TExtraValues... extraValues)
738 static_assert(comms::isMessage<TMsg>(),
"Must be interface class");
739 static_assert(TMsg::hasRead(),
740 "Message interface must support polymorphic read operation");
742 return readInternalPolymorphic(msg, iter, size, extraValues...);
745 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
751 TExtraValues... extraValues)
753 return read(*msg, iter, size, extraValues...);
756 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
762 TExtraValues... extraValues)
764 using MsgType =
typename std::decay<
decltype(msg)>::type;
765 static_assert(comms::details::hasElementType<MsgType>(),
766 "Unsupported type of message object, expected to be either message itself, raw pointer or smart pointer");
767 return read(*msg, iter, size, extraValues...);
770 template <
typename TMsg,
typename TIter,
typename... TParams>
775 DirectOpTag<TParams...>)
777 return msg.doWrite(iter, size);
780 template <
typename TMsg,
typename TIter,
typename... TParams>
785 InterfaceOpTag<TParams...>)
787 using MsgType =
typename std::decay<
decltype(msg)>::type;
789 static_assert(MsgType::hasWrite(),
790 "Message interface must support polymorphic write operation");
792 using IterType =
typename std::decay<
decltype(iter)>::type;
794 static_assert(std::is_convertible<IterType, typename MsgType::WriteIterator>::value,
795 "The provided iterator is not convertible to WriteIterator defined by Message class");
797 using WriteIter =
typename std::add_lvalue_reference<typename MsgType::WriteIterator>::type;
799 return msg.write(
static_cast<WriteIter
>(iter), size);
802 template <
typename TMsg,
typename TIter,
typename... TParams>
807 PointerOpTag<TParams...>)
809 return write(*msg, iter, size);
812 template <
typename TMsg,
typename TIter,
typename... TParams>
817 OtherOpTag<TParams...>)
819 using MsgType =
typename std::decay<
decltype(msg)>::type;
820 static_assert(comms::details::hasElementType<MsgType>(),
821 "Unsupported type of message object, expected to be either message itself, raw pointer or smart pointer");
823 return write(*msg, iter, size);
826 static constexpr bool missingSizeRequiredInternal()
831 template <
typename... TExtraValues>
832 static bool missingSizeRequiredInternal(details::MissingSizeRetriever<>, TExtraValues...)
837 template <
typename T,
typename... TExtraValues>
838 static bool missingSizeRequiredInternal(T, TExtraValues... extraValues)
841 !details::isMissingSizeRetriever<T>(),
842 "Mustn't be missing size retriever");
843 return missingSizeRequiredInternal(extraValues...);
846 static void updateMissingSizeInternal(std::size_t val)
848 static_cast<void>(val);
851 template <
typename... TExtraValues>
852 static void updateMissingSizeInternal(
854 details::MissingSizeRetriever<> retriever,
855 TExtraValues... extraValues)
857 retriever.setValue(val);
858 updateMissingSizeInternal(val, extraValues...);
861 template <
typename T,
typename... TExtraValues>
862 static void updateMissingSizeInternal(std::size_t val, T retriever, TExtraValues... extraValues)
864 static_cast<void>(retriever);
866 !details::isMissingSizeRetriever<
typename std::decay<
decltype(retriever)>::type>(),
867 "Mustn't be missing size retriever");
868 updateMissingSizeInternal(val, extraValues...);
871 static constexpr bool setPayloadRequiredInternal()
876 template <
typename TIter,
typename... TExtraValues>
877 static bool setPayloadRequiredInternal(details::MsgPayloadRetriever<TIter>, TExtraValues...)
882 template <
typename T,
typename... TExtraValues>
883 static bool setPayloadRequiredInternal(T, TExtraValues... extraValues)
886 !details::isMsgPayloadRetriever<T>(),
887 "Mustn't be message payload retriever");
888 return setPayloadRequiredInternal(extraValues...);
891 template <
typename TIter>
892 static void setMsgPayloadInternal(TIter iter, std::size_t len)
894 static_cast<void>(iter);
895 static_cast<void>(len);
898 template <
typename TIter,
typename TOtherIter,
typename... TExtraValues>
899 static void setMsgPayloadInternal(
902 details::MsgPayloadRetriever<TOtherIter> retriever,
903 TExtraValues... extraValues)
905 retriever.setValue(iter, len);
906 setMsgPayloadInternal(iter, len, extraValues...);
909 template <
typename TIter,
typename T,
typename... TExtraValues>
910 static void setMsgPayloadInternal(
914 TExtraValues... extraValues)
916 static_cast<void>(retriever);
918 !details::isMsgPayloadRetriever<
typename std::decay<
decltype(retriever)>::type>(),
919 "Mustn't be message payload retriever");
920 setMsgPayloadInternal(iter, len, extraValues...);
927struct MsgDataLayerCheckHelper
929 static const bool Value =
false;
932template <
typename... TExtraOpts>
933struct MsgDataLayerCheckHelper<
MsgDataLayer<TExtraOpts...> >
935 static const bool Value =
true;
946 return details::MsgDataLayerCheckHelper<T>::Value;
949template <
typename... TExtraOpts>
957template <
typename... TExtraOpts>
959const MsgDataLayer<TExtraOpts...>&
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains definition of comms::Field class.
Contains definition of comms::frame::FrameLayerBase.
Provides common base class for the custom messages with default implementation.
Contains definition of Message object interface and various base classes for custom messages.
Contains various tuple type manipulation classes and functions.
Base class to all the field classes.
Definition Field.h:36
Message data layer.
Definition MsgDataLayer.h:44
MsgDataLayer()=default
Default constructor.
static ErrorStatus readFromData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Same as read().
Definition MsgDataLayer.h:186
static constexpr std::size_t length()
Get remaining length of wrapping transport information.
Definition MsgDataLayer.h:485
static comms::ErrorStatus update(const TMsg &msg, TIter &iter, std::size_t size)
Update recently written (using write()) message contents data.
Definition MsgDataLayer.h:422
constexpr bool isMsgDataLayer()
Compile time check of whether the provided type is a variant of MsgDataLayer.
Definition MsgDataLayer.h:944
std::tuple< Field > AllFields
All fields of the remaining transport layers, contains only Field.
Definition MsgDataLayer.h:71
static const std::size_t NumOfLayers
Static constant indicating amount of transport layers used.
Definition MsgDataLayer.h:82
typename ParsedOptionsInternal::FieldType Field
Raw data field type.
Definition MsgDataLayer.h:68
MsgDataLayer(const MsgDataLayer &)=default
Copy constructor.
static comms::ErrorStatus update(TIter &iter, std::size_t size)
Update recently written (using write()) message contents data.
Definition MsgDataLayer.h:409
~MsgDataLayer() noexcept=default
Destructor.
static ErrorStatus readFieldsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Read the message contents while caching the read transport information fields.
Definition MsgDataLayer.h:220
void AllMessages
Default value of AllMessages type.
Definition MsgDataLayer.h:75
static ErrorStatus readUntilDataFieldsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues...)
Read transport fields with caching until data layer.
Definition MsgDataLayer.h:271
static auto accessCachedField(TAllFields &allFields) -> decltype(std::get< std::tuple_size< typename std::decay< TAllFields >::type >::value - std::tuple_size< AllFields >::value >(allFields))
Access appropriate field from "cached" bundle of all the frame fields.
Definition MsgDataLayer.h:522
void MsgFactory
Default value of MsgFactory type.
Definition MsgDataLayer.h:79
static ErrorStatus readUntilData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues...)
Read transport fields until data layer.
Definition MsgDataLayer.h:169
static ErrorStatus readFromDataFeildsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Same as readFieldsCached().
Definition MsgDataLayer.h:290
static constexpr std::size_t length(const TMsg &msg)
Get remaining length of wrapping transport information + length of the provided message.
Definition MsgDataLayer.h:499
static ErrorStatus write(const TMsg &msg, TIter &iter, std::size_t size)
Write the message contents.
Definition MsgDataLayer.h:318
static ErrorStatus updateFieldsCached(TAllFields &allFields, TIter &iter, std::size_t size)
Update recently written (using writeFieldsCached()) message data as well as cached transport informat...
Definition MsgDataLayer.h:442
static ErrorStatus read(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Read the message contents.
Definition MsgDataLayer.h:130
ThisLayer & thisLayer()
Get access to this layer object.
Definition MsgDataLayer.h:52
static ErrorStatus writeFieldsCached(TAllFields &allFields, const TMsg &msg, TIter &iter, std::size_t size)
Write the message contents while caching the written transport information fields.
Definition MsgDataLayer.h:366
static ErrorStatus updateFieldsCached(TAllFields &allFields, const TMsg &msg, TIter &iter, std::size_t size)
Update recently written (using writeFieldsCached()) message data as well as cached transport informat...
Definition MsgDataLayer.h:468
MsgDataLayer(MsgDataLayer &&)=default
Move constructor.
const ThisLayer & thisLayer() const
Get "const" access to this layer object.
Definition MsgDataLayer.h:58
static constexpr bool canSplitRead()
Compile time check whether split read "until" and "from" data layer is allowed.
Definition MsgDataLayer.h:105
details::MissingSizeRetriever missingSize(std::size_t &val)
Add "missing size" output parameter to frame's "read" operation.
Definition FrameLayerBase.h:1564
FrameLayerBase< TField, TNextLayer, TDerived, TOptions... > & toFrameLayerBase(FrameLayerBase< TField, TNextLayer, TDerived, TOptions... > &layer)
Upcast protocol layer in order to have access to its internal types.
Definition FrameLayerBase.h:1524
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1500
comms::frame::MsgDataLayer< TOptions... > MsgDataLayer
Alias to the comms::frame::MsgDataLayer.
Definition MsgDataLayer.h:27
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
@ Success
Used to indicate successful outcome of the operation.
Replacement to std::conditional.
Definition type_traits.h:32
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:39
Replacement to some types from standard type_traits.