20#include "comms/details/detect.h"
21#include "comms/details/tag.h"
23#include "comms/protocol/details/MsgDataLayerOptionsParser.h"
39template <
typename... TOptions>
42 using ParsedOptionsInternal = details::MsgDataLayerOptionsParser<TOptions...>;
65 using Field =
typename ParsedOptionsInternal::FieldType;
126 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
131 TExtraValues... extraValues)
133 using MsgType =
typename std::decay<
decltype(msg)>::type;
136 comms::isMessageBase<MsgType>()
140 comms::isMessage<MsgType>()
143 typename comms::util::LazyShallowConditional<
144 std::is_pointer<MsgType>::value
152 if (setPayloadRequiredInternal(extraValues...)) {
153 auto fromIter = iter;
154 auto es = readInternal(msg, iter, size, Tag(), extraValues...);
155 setMsgPayloadInternal(fromIter,
static_cast<std::size_t
>(std::distance(fromIter, iter)), extraValues...);
159 return readInternal(msg, iter, size, Tag(), extraValues...);
165 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
172 static_cast<void>(msg);
173 static_cast<void>(iter);
174 static_cast<void>(size);
182 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
187 TExtraValues... extraValues)
189 return read(msg, iter, size, extraValues...);
216 template <
typename TAllFields,
typename TMsg,
typename TIter,
typename... TExtraValues>
218 TAllFields& allFields,
222 TExtraValues... extraValues)
226 "Expected TAllFields to be tuple.");
228 using AllFieldsDecayed =
typename std::decay<TAllFields>::type;
229 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(),
"Passed tuple is wrong.");
230 static const std::size_t Idx =
231 std::tuple_size<AllFieldsDecayed>::value -
232 std::tuple_size<AllFields>::value;
234 static_assert((Idx + 1) == std::tuple_size<TAllFields>::value,
235 "All fields must be read when MsgDataLayer is reached");
237 using IterType =
typename std::decay<
decltype(iter)>::type;
238 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
239 static_assert(std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
240 "Caching read from non random access iterators are not supported at this moment.");
242 auto& dataField = std::get<Idx>(allFields);
244 using FieldType =
typename std::decay<
decltype(dataField)>::type;
246 std::is_same<Field, FieldType>::value,
247 "Field has wrong type");
249 auto dataIter = iter;
250 auto es =
read(msg, iter, size, extraValues...);
255 auto dataSize =
static_cast<std::size_t
>(std::distance(dataIter, iter));
256 setMsgPayloadInternal(dataIter, dataSize, extraValues...);
258 auto dataEs = dataField.read(dataIter, dataSize);
259 static_cast<void>(dataEs);
267 template <
typename TAllFields,
typename TMsg,
typename TIter,
typename... TExtraValues>
269 TAllFields& allFields,
275 static_cast<void>(allFields);
276 static_cast<void>(msg);
277 static_cast<void>(iter);
278 static_cast<void>(size);
286 template <
typename TAllFields,
typename TMsg,
typename TIter,
typename... TExtraValues>
288 TAllFields& allFields,
292 TExtraValues... extraValues)
314 template <
typename TMsg,
typename TIter>
320 using MsgType =
typename std::decay<
decltype(msg)>::type;
323 comms::isMessage<MsgType>(),
324 "The provided message object must inherit from comms::Message");
328 comms::isMessageBase<MsgType>()
332 comms::isMessage<MsgType>()
335 typename comms::util::LazyShallowConditional<
336 std::is_pointer<MsgType>::value
344 return writeInternal(msg, iter, size, Tag());
362 template <
typename TAllFields,
typename TMsg,
typename TIter>
364 TAllFields& allFields,
370 "Expected TAllFields to be tuple.");
372 using AllFieldsDecayed =
typename std::decay<TAllFields>::type;
373 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(),
"Passed tuple is wrong.");
374 static const std::size_t Idx =
375 std::tuple_size<AllFieldsDecayed>::value -
376 std::tuple_size<AllFields>::value;
378 static_assert((Idx + 1) == std::tuple_size<TAllFields>::value,
379 "All fields must be written when MsgDataLayer is reached");
381 auto& dataField = std::get<Idx>(allFields);
382 using FieldType =
typename std::decay<
decltype(dataField)>::type;
384 std::is_same<Field, FieldType>::value,
385 "Field has wrong type");
387 using IterType =
typename std::decay<
decltype(iter)>::type;
388 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
389 return writeWithFieldCachedInternal(dataField, msg, iter, size, IterTag());
405 template <
typename TIter>
408 std::advance(iter, size);
418 template <
typename TMsg,
typename TIter>
421 static_cast<void>(msg);
422 return update(iter, size);
438 template <
typename TAllFields,
typename TIter>
440 TAllFields& allFields,
444 static_cast<void>(allFields);
445 std::advance(iter, size);
464 template <
typename TAllFields,
typename TMsg,
typename TIter>
466 TAllFields& allFields,
471 static_cast<void>(allFields);
472 static_cast<void>(msg);
473 std::advance(iter, size);
495 template <
typename TMsg>
496 static constexpr std::size_t
length(
const TMsg& msg)
498 using MsgType =
typename std::decay<
decltype(msg)>::type;
501 comms::isMessage<MsgType>(),
502 "The provided message object must inherit from comms::Message");
505 typename comms::util::LazyShallowConditional<
506 details::ProtocolLayerHasFieldsImpl<MsgType>::Value
511 return getMsgLength(msg, Tag());
518 template <
typename TAllFields>
520 decltype(std::get<std::tuple_size<typename std::decay<TAllFields>::type>::value - std::tuple_size<AllFields>::value>(allFields))
522 using AllFieldsDecayed =
typename std::decay<TAllFields>::type;
523 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(),
"Passed tuple is wrong.");
524 static const std::size_t Idx =
525 std::tuple_size<AllFieldsDecayed>::value -
526 std::tuple_size<AllFields>::value;
528 return std::get<Idx>(allFields);
532 template <
typename... TParams>
533 using MsgHasLengthTag = comms::details::tag::Tag1<>;
535 template <
typename... TParams>
536 using MsgNoLengthTag = comms::details::tag::Tag2<>;
538 template <
typename... TParams>
539 using MsgDirectLengthTag = comms::details::tag::Tag3<>;
541 template <
typename... TParams>
542 using DirectOpTag = comms::details::tag::Tag4<>;
544 template <
typename... TParams>
545 using InterfaceOpTag = comms::details::tag::Tag5<>;
547 template <
typename... TParams>
548 using PointerOpTag = comms::details::tag::Tag6<>;
550 template <
typename... TParams>
551 using OtherOpTag = comms::details::tag::Tag7<>;
553 template <
typename TMsg,
typename TIter>
559 std::random_access_iterator_tag)
561 return writeWithFieldCachedRandomAccess(field, msg, iter, size);
564 template <
typename TMsg,
typename TIter>
570 std::output_iterator_tag)
572 return writeWithFieldCachedOutput(field, msg, iter, size);
575 template <
typename TMsg,
typename TIter>
576 static ErrorStatus writeWithFieldCachedRandomAccess(
582 auto dataReadIter = iter;
583 auto es =
write(msg, iter, size);
588 auto writtenCount =
static_cast<std::size_t
>(std::distance(dataReadIter, iter));
589 auto dataEs = field.read(dataReadIter, writtenCount);
591 static_cast<void>(dataEs);
595 template <
typename TMsg,
typename TCollection>
599 std::back_insert_iterator<TCollection>& iter,
602 auto es =
write(msg, iter, size);
608 auto dataWriteIter = std::back_inserter(col);
609 auto dataWriteEs =
write(msg, dataWriteIter, size);
611 static_cast<void>(dataWriteEs);
613 auto dataReadIter = col.cbegin();
614 auto dataReadEs = field.read(dataReadIter, col.size());
616 static_cast<void>(dataReadEs);
621 template <
typename TMsg,
typename... TParams>
622 static std::size_t getMsgLength(
const TMsg& msg, MsgHasLengthTag<TParams...>)
624 using MsgType =
typename std::decay<
decltype(msg)>::type;
625 static_assert(MsgType::hasLength(),
"Message interface must define length()");
629 template <
typename TMsg,
typename... TParams>
630 static constexpr std::size_t getMsgLength(
const TMsg& msg, MsgDirectLengthTag<TParams...>)
632 using MsgType =
typename std::decay<
decltype(msg)>::type;
633 static_assert(MsgType::hasFields(),
"FieldsImpl option hasn't been used");
634 return msg.doLength();
637 template <
typename TMsg,
typename... TParams>
638 static constexpr std::size_t getMsgLength(
const TMsg&, MsgNoLengthTag<TParams...>)
643 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
648 TExtraValues... extraValues)
650 using MsgType =
typename std::decay<
decltype(msg)>::type;
653 comms::isMessage<MsgType>(),
654 "The provided message object must inherit from comms::Message");
656 static_assert(MsgType::hasRead(),
657 "Message interface must support polymorphic read operation");
659 using IterType =
typename std::decay<
decltype(iter)>::type;
661 static_assert(std::is_convertible<IterType, typename MsgType::ReadIterator>::value,
662 "The provided iterator is not convertible to ReadIterator defined by Message class");
664 using ReadIter =
typename std::add_lvalue_reference<typename MsgType::ReadIterator>::type;
666 auto result = msg.read(
static_cast<ReadIter
>(iter), size);
668 missingSizeRequiredInternal(extraValues...)) {
670 typename comms::util::LazyShallowConditional<
678 auto msgLen = getMsgLength(msg, Tag());
682 updateMissingSizeInternal(
missingSize, extraValues...);
687 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
692 TExtraValues... extraValues)
694 using MsgType =
typename std::decay<
decltype(msg)>::type;
697 comms::isMessageBase<MsgType>(),
698 "The provided message object must inherit from comms::MessageBase");
700 static_assert(details::protocolLayerHasFieldsImpl<MsgType>(),
701 "Message class must use FieldsImpl option");
703 auto result = msg.doRead(iter, size);
705 (missingSizeRequiredInternal(extraValues...))) {
707 auto msgLen = getMsgLength(msg, MsgDirectLengthTag<>());
711 updateMissingSizeInternal(
missingSize, extraValues...);
716 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
722 TExtraValues... extraValues)
724 return readInternalDirect(msg, iter, size, extraValues...);
727 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
733 TExtraValues... extraValues)
735 static_assert(comms::isMessage<TMsg>(),
"Must be interface class");
736 static_assert(TMsg::hasRead(),
737 "Message interface must support polymorphic read operation");
739 return readInternalPolymorphic(msg, iter, size, extraValues...);
742 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
748 TExtraValues... extraValues)
750 return read(*msg, iter, size, extraValues...);
753 template <
typename TMsg,
typename TIter,
typename... TExtraValues>
759 TExtraValues... extraValues)
761 using MsgType =
typename std::decay<
decltype(msg)>::type;
762 static_assert(comms::details::hasElementType<MsgType>(),
763 "Unsupported type of message object, expected to be either message itself, raw pointer or smart pointer");
764 return read(*msg, iter, size, extraValues...);
767 template <
typename TMsg,
typename TIter,
typename... TParams>
772 DirectOpTag<TParams...>)
774 return msg.doWrite(iter, size);
777 template <
typename TMsg,
typename TIter,
typename... TParams>
782 InterfaceOpTag<TParams...>)
784 using MsgType =
typename std::decay<
decltype(msg)>::type;
786 static_assert(MsgType::hasWrite(),
787 "Message interface must support polymorphic write operation");
789 using IterType =
typename std::decay<
decltype(iter)>::type;
791 static_assert(std::is_convertible<IterType, typename MsgType::WriteIterator>::value,
792 "The provided iterator is not convertible to WriteIterator defined by Message class");
794 using WriteIter =
typename std::add_lvalue_reference<typename MsgType::WriteIterator>::type;
796 return msg.write(
static_cast<WriteIter
>(iter), size);
799 template <
typename TMsg,
typename TIter,
typename... TParams>
804 PointerOpTag<TParams...>)
806 return write(*msg, iter, size);
809 template <
typename TMsg,
typename TIter,
typename... TParams>
814 OtherOpTag<TParams...>)
816 using MsgType =
typename std::decay<
decltype(msg)>::type;
817 static_assert(comms::details::hasElementType<MsgType>(),
818 "Unsupported type of message object, expected to be either message itself, raw pointer or smart pointer");
820 return write(*msg, iter, size);
823 static constexpr bool missingSizeRequiredInternal()
828 template <
typename... TExtraValues>
829 static bool missingSizeRequiredInternal(details::MissingSizeRetriever<>, TExtraValues...)
834 template <
typename T,
typename... TExtraValues>
835 static bool missingSizeRequiredInternal(T, TExtraValues... extraValues)
838 !details::isMissingSizeRetriever<T>(),
839 "Mustn't be missing size retriever");
840 return missingSizeRequiredInternal(extraValues...);
843 static void updateMissingSizeInternal(std::size_t val)
845 static_cast<void>(val);
848 template <
typename... TExtraValues>
849 static void updateMissingSizeInternal(
851 details::MissingSizeRetriever<> retriever,
852 TExtraValues... extraValues)
854 retriever.setValue(val);
855 updateMissingSizeInternal(val, extraValues...);
858 template <
typename T,
typename... TExtraValues>
859 static void updateMissingSizeInternal(std::size_t val, T retriever, TExtraValues... extraValues)
861 static_cast<void>(retriever);
863 !details::isMissingSizeRetriever<
typename std::decay<
decltype(retriever)>::type>(),
864 "Mustn't be missing size retriever");
865 updateMissingSizeInternal(val, extraValues...);
868 static constexpr bool setPayloadRequiredInternal()
873 template <
typename TIter,
typename... TExtraValues>
874 static bool setPayloadRequiredInternal(details::MsgPayloadRetriever<TIter>, TExtraValues...)
879 template <
typename T,
typename... TExtraValues>
880 static bool setPayloadRequiredInternal(T, TExtraValues... extraValues)
883 !details::isMsgPayloadRetriever<T>(),
884 "Mustn't be message payload retriever");
885 return setPayloadRequiredInternal(extraValues...);
888 template <
typename TIter>
889 static void setMsgPayloadInternal(TIter iter, std::size_t len)
891 static_cast<void>(iter);
892 static_cast<void>(len);
895 template <
typename TIter,
typename TOtherIter,
typename... TExtraValues>
896 static void setMsgPayloadInternal(
899 details::MsgPayloadRetriever<TOtherIter> retriever,
900 TExtraValues... extraValues)
902 retriever.setValue(iter, len);
903 setMsgPayloadInternal(iter, len, extraValues...);
906 template <
typename TIter,
typename T,
typename... TExtraValues>
907 static void setMsgPayloadInternal(
911 TExtraValues... extraValues)
913 static_cast<void>(retriever);
915 !details::isMsgPayloadRetriever<
typename std::decay<
decltype(retriever)>::type>(),
916 "Mustn't be message payload retriever");
917 setMsgPayloadInternal(iter, len, extraValues...);
924struct MsgDataLayerCheckHelper
926 static const bool Value =
false;
929template <
typename... TExtraOpts>
930struct MsgDataLayerCheckHelper<MsgDataLayer<TExtraOpts...> >
932 static const bool Value =
true;
943 return details::MsgDataLayerCheckHelper<T>::Value;
946template <
typename... TExtraOpts>
954template <
typename... TExtraOpts>
956const MsgDataLayer<TExtraOpts...>&
957toProtocolLayerBase(
const MsgDataLayer<TExtraOpts...>& layer)
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::field::IntValue.
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 definition of comms::protocol::ProtocolLayerBase.
Contains various tuple type manipulation classes and functions.
Base class to all the field classes.
Definition Field.h:33
Message data layer.
Definition MsgDataLayer.h:41
static constexpr std::size_t length(const TMsg &msg)
Get remaining length of wrapping transport information + length of the provided message.
Definition MsgDataLayer.h:496
static comms::ErrorStatus update(const TMsg &msg, TIter &iter, std::size_t size)
Update recently written (using write()) message contents data.
Definition MsgDataLayer.h:419
constexpr bool isMsgDataLayer()
Compile time check of whether the provided type is a variant of MsgDataLayer.
Definition MsgDataLayer.h:941
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:217
typename ParsedOptionsInternal::FieldType Field
Raw data field type.
Definition MsgDataLayer.h:65
void AllMessages
Default value of AllMessages type.
Definition MsgDataLayer.h:72
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:363
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:465
MsgDataLayer(const MsgDataLayer &)=default
Copy constructor.
static const std::size_t NumOfLayers
Static constant indicating amount of transport layers used.
Definition MsgDataLayer.h:79
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:439
const ThisLayer & thisLayer() const
Get "const" access to this layer object.
Definition MsgDataLayer.h:55
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:268
static ErrorStatus readFromData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Same as read().
Definition MsgDataLayer.h:183
~MsgDataLayer() noexcept=default
Destructor.
static ErrorStatus write(const TMsg &msg, TIter &iter, std::size_t size)
Write the message contents.
Definition MsgDataLayer.h:315
ThisLayer & thisLayer()
Get access to this layer object.
Definition MsgDataLayer.h:49
static comms::ErrorStatus update(TIter &iter, std::size_t size)
Update recently written (using write()) message contents data.
Definition MsgDataLayer.h:406
static constexpr std::size_t length()
Get remaining length of wrapping transport information.
Definition MsgDataLayer.h:482
static ErrorStatus read(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Read the message contents.
Definition MsgDataLayer.h:127
MsgDataLayer()=default
Default constructor.
static ErrorStatus readUntilData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues...)
Read transport fields until data layer.
Definition MsgDataLayer.h:166
static constexpr bool canSplitRead()
Compile time check whether split read "until" and "from" data layer is allowed.
Definition MsgDataLayer.h:102
std::tuple< Field > AllFields
All fields of the remaining transport layers, contains only Field.
Definition MsgDataLayer.h:68
void MsgFactory
Default value of MsgFactory type.
Definition MsgDataLayer.h:76
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 protocol stack fields.
Definition MsgDataLayer.h:519
MsgDataLayer(MsgDataLayer &&)=default
Move constructor.
static ErrorStatus readFromDataFeildsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Same as readFieldsCached().
Definition MsgDataLayer.h:287
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1468
details::MissingSizeRetriever missingSize(std::size_t &val)
Add "missing size" output parameter to protocol stack's (frame's) "read" operation.
Definition ProtocolLayerBase.h:1561
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ Success
Used to indicate successful outcome of the operation.
Replacement to std::conditional.
Definition type_traits.h:28
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:36
Replacement to some types from standard type_traits.