COMMS
Template library intended to help with implementation of communication protocols.
MsgDataLayer.h
Go to the documentation of this file.
1 //
2 // Copyright 2014 - 2024 (C). Alex Robenko. All rights reserved.
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
10 
11 #pragma once
12 
13 #include <tuple>
14 #include <iterator>
15 #include <type_traits>
16 #include "comms/Assert.h"
17 #include "comms/Field.h"
18 #include "comms/Message.h"
19 #include "comms/MessageBase.h"
20 #include "comms/details/detect.h"
21 #include "comms/details/tag.h"
22 #include "comms/field/ArrayList.h"
23 #include "comms/field/IntValue.h"
24 #include "comms/util/Tuple.h"
25 #include "comms/util/type_traits.h"
26 #include "ProtocolLayerBase.h"
27 
28 namespace comms
29 {
30 
31 namespace protocol
32 {
33 
40 template <typename... TExtraOpts>
42 {
43 public:
45  using ThisLayer = MsgDataLayer<TExtraOpts...>;
46 
49  {
50  return *this;
51  }
52 
54  const ThisLayer& thisLayer() const
55  {
56  return *this;
57  }
58 
62  using Field =
65  std::uint8_t,
66  TExtraOpts...
67  >;
68 
70  using AllFields = std::tuple<Field>;
71 
74  using AllMessages = void;
75 
78  using MsgFactory = void;
79 
81  static const std::size_t NumOfLayers = 1;
82 
84  MsgDataLayer() = default;
85 
87  MsgDataLayer(const MsgDataLayer&) = default;
88 
90  MsgDataLayer(MsgDataLayer&&) = default;
91 
93  ~MsgDataLayer() noexcept = default;
94 
96  MsgDataLayer& operator=(const MsgDataLayer&) = default;
97 
99  MsgDataLayer& operator=(MsgDataLayer&&) = default;
100 
104  static constexpr bool canSplitRead()
105  {
106  return true;
107  }
108 
128  template <typename TMsg, typename TIter, typename... TExtraValues>
130  TMsg& msg,
131  TIter& iter,
132  std::size_t size,
133  TExtraValues... extraValues)
134  {
135  using MsgType = typename std::decay<decltype(msg)>::type;
136  using Tag =
137  typename comms::util::Conditional<
138  comms::isMessageBase<MsgType>()
139  >::template Type<
140  DirectOpTag<>,
141  typename comms::util::Conditional<
142  comms::isMessage<MsgType>()
143  >::template Type<
144  InterfaceOpTag<>,
145  typename comms::util::LazyShallowConditional<
146  std::is_pointer<MsgType>::value
147  >::template Type<
148  PointerOpTag,
149  OtherOpTag
150  >
151  >
152  >;
153 
154  if (setPayloadRequiredInternal(extraValues...)) {
155  auto fromIter = iter;
156  auto es = readInternal(msg, iter, size, Tag(), extraValues...);
157  setMsgPayloadInternal(fromIter, static_cast<std::size_t>(std::distance(fromIter, iter)), extraValues...);
158  return es;
159  }
160 
161  return readInternal(msg, iter, size, Tag(), extraValues...);
162  }
163 
167  template <typename TMsg, typename TIter, typename... TExtraValues>
169  TMsg& msg,
170  TIter& iter,
171  std::size_t size,
172  TExtraValues...)
173  {
174  static_cast<void>(msg);
175  static_cast<void>(iter);
176  static_cast<void>(size);
178  }
179 
184  template <typename TMsg, typename TIter, typename... TExtraValues>
186  TMsg& msg,
187  TIter& iter,
188  std::size_t size,
189  TExtraValues... extraValues)
190  {
191  return read(msg, iter, size, extraValues...);
192  }
193 
218  template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
220  TAllFields& allFields,
221  TMsg& msg,
222  TIter& iter,
223  std::size_t size,
224  TExtraValues... extraValues)
225  {
226 
228  "Expected TAllFields to be tuple.");
229 
230  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
231  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
232  static const std::size_t Idx =
233  std::tuple_size<AllFieldsDecayed>::value -
234  std::tuple_size<AllFields>::value;
235 
236  static_assert((Idx + 1) == std::tuple_size<TAllFields>::value,
237  "All fields must be read when MsgDataLayer is reached");
238 
239  using IterType = typename std::decay<decltype(iter)>::type;
240  using IterTag = typename std::iterator_traits<IterType>::iterator_category;
241  static_assert(std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
242  "Caching read from non random access iterators are not supported at this moment.");
243 
244  auto& dataField = std::get<Idx>(allFields);
245 
246  using FieldType = typename std::decay<decltype(dataField)>::type;
247  static_assert(
248  std::is_same<Field, FieldType>::value,
249  "Field has wrong type");
250 
251  auto dataIter = iter;
252  auto es = read(msg, iter, size, extraValues...);
253  if (es != ErrorStatus::Success) {
254  return es;
255  }
256 
257  auto dataSize = static_cast<std::size_t>(std::distance(dataIter, iter));
258  setMsgPayloadInternal(dataIter, dataSize, extraValues...);
259 
260  auto dataEs = dataField.read(dataIter, dataSize);
261  static_cast<void>(dataEs);
263  return es;
264  }
265 
269  template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
271  TAllFields& allFields,
272  TMsg& msg,
273  TIter& iter,
274  std::size_t size,
275  TExtraValues...)
276  {
277  static_cast<void>(allFields);
278  static_cast<void>(msg);
279  static_cast<void>(iter);
280  static_cast<void>(size);
282  }
283 
288  template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
290  TAllFields& allFields,
291  TMsg& msg,
292  TIter& iter,
293  std::size_t size,
294  TExtraValues... extraValues)
295  {
296  return readFieldsCached(allFields, msg, iter, size, extraValues...);
297  }
298 
316  template <typename TMsg, typename TIter>
318  const TMsg& msg,
319  TIter& iter,
320  std::size_t size)
321  {
322  using MsgType = typename std::decay<decltype(msg)>::type;
323 
324  static_assert(
325  comms::isMessage<MsgType>(),
326  "The provided message object must inherit from comms::Message");
327 
328  using Tag =
329  typename comms::util::Conditional<
330  comms::isMessageBase<MsgType>()
331  >::template Type<
332  DirectOpTag<>,
333  typename comms::util::Conditional<
334  comms::isMessage<MsgType>()
335  >::template Type<
336  InterfaceOpTag<>,
337  typename comms::util::LazyShallowConditional<
338  std::is_pointer<MsgType>::value
339  >::template Type<
340  PointerOpTag,
341  OtherOpTag
342  >
343  >
344  >;
345 
346  return writeInternal(msg, iter, size, Tag());
347  }
348 
364  template <typename TAllFields, typename TMsg, typename TIter>
366  TAllFields& allFields,
367  const TMsg& msg,
368  TIter& iter,
369  std::size_t size)
370  {
372  "Expected TAllFields to be tuple.");
373 
374  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
375  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
376  static const std::size_t Idx =
377  std::tuple_size<AllFieldsDecayed>::value -
378  std::tuple_size<AllFields>::value;
379 
380  static_assert((Idx + 1) == std::tuple_size<TAllFields>::value,
381  "All fields must be written when MsgDataLayer is reached");
382 
383  auto& dataField = std::get<Idx>(allFields);
384  using FieldType = typename std::decay<decltype(dataField)>::type;
385  static_assert(
386  std::is_same<Field, FieldType>::value,
387  "Field has wrong type");
388 
389  using IterType = typename std::decay<decltype(iter)>::type;
390  using IterTag = typename std::iterator_traits<IterType>::iterator_category;
391  return writeWithFieldCachedInternal(dataField, msg, iter, size, IterTag());
392  }
393 
407  template <typename TIter>
408  static comms::ErrorStatus update(TIter& iter, std::size_t size)
409  {
410  std::advance(iter, size);
412  }
413 
420  template <typename TMsg, typename TIter>
421  static comms::ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size)
422  {
423  static_cast<void>(msg);
424  return update(iter, size);
425  }
426 
440  template <typename TAllFields, typename TIter>
442  TAllFields& allFields,
443  TIter& iter,
444  std::size_t size)
445  {
446  static_cast<void>(allFields);
447  std::advance(iter, size);
449  }
450 
466  template <typename TAllFields, typename TMsg, typename TIter>
468  TAllFields& allFields,
469  const TMsg& msg,
470  TIter& iter,
471  std::size_t size)
472  {
473  static_cast<void>(allFields);
474  static_cast<void>(msg);
475  std::advance(iter, size);
477  }
478 
484  static constexpr std::size_t length()
485  {
486  return 0U;
487  }
488 
497  template <typename TMsg>
498  static constexpr std::size_t length(const TMsg& msg)
499  {
500  using MsgType = typename std::decay<decltype(msg)>::type;
501 
502  static_assert(
503  comms::isMessage<MsgType>(),
504  "The provided message object must inherit from comms::Message");
505 
506  using Tag =
507  typename comms::util::LazyShallowConditional<
508  details::ProtocolLayerHasFieldsImpl<MsgType>::Value
509  >::template Type<
510  MsgDirectLengthTag,
511  MsgHasLengthTag
512  >;
513  return getMsgLength(msg, Tag());
514  }
515 
520  template <typename TAllFields>
521  static auto accessCachedField(TAllFields& allFields) ->
522  decltype(std::get<std::tuple_size<typename std::decay<TAllFields>::type>::value - std::tuple_size<AllFields>::value>(allFields))
523  {
524  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
525  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
526  static const std::size_t Idx =
527  std::tuple_size<AllFieldsDecayed>::value -
528  std::tuple_size<AllFields>::value;
529 
530  return std::get<Idx>(allFields);
531  }
532 
533 private:
534  template <typename... TParams>
535  using MsgHasLengthTag = comms::details::tag::Tag1<>;
536 
537  template <typename... TParams>
538  using MsgNoLengthTag = comms::details::tag::Tag2<>;
539 
540  template <typename... TParams>
541  using MsgDirectLengthTag = comms::details::tag::Tag3<>;
542 
543  template <typename... TParams>
544  using DirectOpTag = comms::details::tag::Tag4<>;
545 
546  template <typename... TParams>
547  using InterfaceOpTag = comms::details::tag::Tag5<>;
548 
549  template <typename... TParams>
550  using PointerOpTag = comms::details::tag::Tag6<>;
551 
552  template <typename... TParams>
553  using OtherOpTag = comms::details::tag::Tag7<>;
554 
555  template <typename TMsg, typename TIter>
556  static ErrorStatus writeWithFieldCachedInternal(
557  Field& field,
558  const TMsg& msg,
559  TIter& iter,
560  std::size_t size,
561  std::random_access_iterator_tag)
562  {
563  return writeWithFieldCachedRandomAccess(field, msg, iter, size);
564  }
565 
566  template <typename TMsg, typename TIter>
567  static ErrorStatus writeWithFieldCachedInternal(
568  Field& field,
569  const TMsg& msg,
570  TIter& iter,
571  std::size_t size,
572  std::output_iterator_tag)
573  {
574  return writeWithFieldCachedOutput(field, msg, iter, size);
575  }
576 
577  template <typename TMsg, typename TIter>
578  static ErrorStatus writeWithFieldCachedRandomAccess(
579  Field& field,
580  const TMsg& msg,
581  TIter& iter,
582  std::size_t size)
583  {
584  auto dataReadIter = iter;
585  auto es = write(msg, iter, size);
586  if (es != comms::ErrorStatus::Success) {
587  return es;
588  }
589 
590  auto writtenCount = static_cast<std::size_t>(std::distance(dataReadIter, iter));
591  auto dataEs = field.read(dataReadIter, writtenCount);
593  static_cast<void>(dataEs);
595  }
596 
597  template <typename TMsg, typename TCollection>
598  static ErrorStatus writeWithFieldCachedOutput(
599  Field& field,
600  const TMsg& msg,
601  std::back_insert_iterator<TCollection>& iter,
602  std::size_t size)
603  {
604  auto es = write(msg, iter, size);
605  if (es != comms::ErrorStatus::Success) {
606  return es;
607  }
608 
609  TCollection col;
610  auto dataWriteIter = std::back_inserter(col);
611  auto dataWriteEs = write(msg, dataWriteIter, size);
613  static_cast<void>(dataWriteEs);
614 
615  auto dataReadIter = col.cbegin();
616  auto dataReadEs = field.read(dataReadIter, col.size());
618  static_cast<void>(dataReadEs);
619 
621  }
622 
623  template <typename TMsg, typename... TParams>
624  static std::size_t getMsgLength(const TMsg& msg, MsgHasLengthTag<TParams...>)
625  {
626  using MsgType = typename std::decay<decltype(msg)>::type;
627  static_assert(MsgType::hasLength(), "Message interface must define length()");
628  return msg.length();
629  }
630 
631  template <typename TMsg, typename... TParams>
632  static constexpr std::size_t getMsgLength(const TMsg& msg, MsgDirectLengthTag<TParams...>)
633  {
634  using MsgType = typename std::decay<decltype(msg)>::type;
635  static_assert(MsgType::hasFields(), "FieldsImpl option hasn't been used");
636  return msg.doLength();
637  }
638 
639  template <typename TMsg, typename... TParams>
640  static constexpr std::size_t getMsgLength(const TMsg&, MsgNoLengthTag<TParams...>)
641  {
642  return 0U;
643  }
644 
645  template <typename TMsg, typename TIter, typename... TExtraValues>
646  static ErrorStatus readInternalPolymorphic(
647  TMsg& msg,
648  TIter& iter,
649  std::size_t size,
650  TExtraValues... extraValues)
651  {
652  using MsgType = typename std::decay<decltype(msg)>::type;
653 
654  static_assert(
655  comms::isMessage<MsgType>(),
656  "The provided message object must inherit from comms::Message");
657 
658  static_assert(MsgType::hasRead(),
659  "Message interface must support polymorphic read operation");
660 
661  using IterType = typename std::decay<decltype(iter)>::type;
662 
663  static_assert(std::is_convertible<IterType, typename MsgType::ReadIterator>::value,
664  "The provided iterator is not convertible to ReadIterator defined by Message class");
665 
666  using ReadIter = typename std::add_lvalue_reference<typename MsgType::ReadIterator>::type;
667 
668  auto result = msg.read(static_cast<ReadIter>(iter), size);
669  if ((result == ErrorStatus::NotEnoughData) &&
670  missingSizeRequiredInternal(extraValues...)) {
671  using Tag =
672  typename comms::util::LazyShallowConditional<
673  MsgType::hasLength()
674  >::template Type<
675  MsgHasLengthTag,
676  MsgNoLengthTag
677  >;
678 
679  std::size_t missingSize = 1U;
680  auto msgLen = getMsgLength(msg, Tag());
681  if (size < msgLen) {
682  missingSize = msgLen - size;
683  }
684  updateMissingSizeInternal(missingSize, extraValues...);
685  }
686  return result;
687  }
688 
689  template <typename TMsg, typename TIter, typename... TExtraValues>
690  static ErrorStatus readInternalDirect(
691  TMsg& msg,
692  TIter& iter,
693  std::size_t size,
694  TExtraValues... extraValues)
695  {
696  using MsgType = typename std::decay<decltype(msg)>::type;
697 
698  static_assert(
699  comms::isMessageBase<MsgType>(),
700  "The provided message object must inherit from comms::MessageBase");
701 
702  static_assert(details::protocolLayerHasFieldsImpl<MsgType>(),
703  "Message class must use FieldsImpl option");
704 
705  auto result = msg.doRead(iter, size);
706  if ((result == ErrorStatus::NotEnoughData) &&
707  (missingSizeRequiredInternal(extraValues...))) {
708  std::size_t missingSize = 1U;
709  auto msgLen = getMsgLength(msg, MsgDirectLengthTag<>());
710  if (size < msgLen) {
711  missingSize = msgLen - size;
712  }
713  updateMissingSizeInternal(missingSize, extraValues...);
714  }
715  return result;
716  }
717 
718  template <typename TMsg, typename TIter, typename... TExtraValues>
719  static ErrorStatus readInternal(
720  TMsg& msg,
721  TIter& iter,
722  std::size_t size,
723  DirectOpTag<>,
724  TExtraValues... extraValues)
725  {
726  return readInternalDirect(msg, iter, size, extraValues...);
727  }
728 
729  template <typename TMsg, typename TIter, typename... TExtraValues>
730  static ErrorStatus readInternal(
731  TMsg& msg,
732  TIter& iter,
733  std::size_t size,
734  InterfaceOpTag<>,
735  TExtraValues... extraValues)
736  {
737  static_assert(comms::isMessage<TMsg>(), "Must be interface class");
738  static_assert(TMsg::hasRead(),
739  "Message interface must support polymorphic read operation");
740 
741  return readInternalPolymorphic(msg, iter, size, extraValues...);
742  }
743 
744  template <typename TMsg, typename TIter, typename... TExtraValues>
745  static ErrorStatus readInternal(
746  TMsg& msg,
747  TIter& iter,
748  std::size_t size,
749  PointerOpTag<>,
750  TExtraValues... extraValues)
751  {
752  return read(*msg, iter, size, extraValues...);
753  }
754 
755  template <typename TMsg, typename TIter, typename... TExtraValues>
756  static ErrorStatus readInternal(
757  TMsg& msg,
758  TIter& iter,
759  std::size_t size,
760  OtherOpTag<>,
761  TExtraValues... extraValues)
762  {
763  using MsgType = typename std::decay<decltype(msg)>::type;
764  static_assert(comms::details::hasElementType<MsgType>(),
765  "Unsupported type of message object, expected to be either message itself, raw pointer or smart pointer");
766  return read(*msg, iter, size, extraValues...);
767  }
768 
769  template <typename TMsg, typename TIter, typename... TParams>
770  static ErrorStatus writeInternal(
771  const TMsg& msg,
772  TIter& iter,
773  std::size_t size,
774  DirectOpTag<TParams...>)
775  {
776  return msg.doWrite(iter, size);
777  }
778 
779  template <typename TMsg, typename TIter, typename... TParams>
780  static ErrorStatus writeInternal(
781  const TMsg& msg,
782  TIter& iter,
783  std::size_t size,
784  InterfaceOpTag<TParams...>)
785  {
786  using MsgType = typename std::decay<decltype(msg)>::type;
787 
788  static_assert(MsgType::hasWrite(),
789  "Message interface must support polymorphic write operation");
790 
791  using IterType = typename std::decay<decltype(iter)>::type;
792 
793  static_assert(std::is_convertible<IterType, typename MsgType::WriteIterator>::value,
794  "The provided iterator is not convertible to WriteIterator defined by Message class");
795 
796  using WriteIter = typename std::add_lvalue_reference<typename MsgType::WriteIterator>::type;
797 
798  return msg.write(static_cast<WriteIter>(iter), size);
799  }
800 
801  template <typename TMsg, typename TIter, typename... TParams>
802  static ErrorStatus writeInternal(
803  const TMsg& msg,
804  TIter& iter,
805  std::size_t size,
806  PointerOpTag<TParams...>)
807  {
808  return write(*msg, iter, size);
809  }
810 
811  template <typename TMsg, typename TIter, typename... TParams>
812  static ErrorStatus writeInternal(
813  const TMsg& msg,
814  TIter& iter,
815  std::size_t size,
816  OtherOpTag<TParams...>)
817  {
818  using MsgType = typename std::decay<decltype(msg)>::type;
819  static_assert(comms::details::hasElementType<MsgType>(),
820  "Unsupported type of message object, expected to be either message itself, raw pointer or smart pointer");
821 
822  return write(*msg, iter, size);
823  }
824 
825  static constexpr bool missingSizeRequiredInternal()
826  {
827  return false;
828  }
829 
830  template <typename... TExtraValues>
831  static bool missingSizeRequiredInternal(details::MissingSizeRetriever<>, TExtraValues...)
832  {
833  return true;
834  }
835 
836  template <typename T, typename... TExtraValues>
837  static bool missingSizeRequiredInternal(T, TExtraValues... extraValues)
838  {
839  static_assert(
840  !details::isMissingSizeRetriever<T>(),
841  "Mustn't be missing size retriever");
842  return missingSizeRequiredInternal(extraValues...);
843  }
844 
845  static void updateMissingSizeInternal(std::size_t val)
846  {
847  static_cast<void>(val);
848  }
849 
850  template <typename... TExtraValues>
851  static void updateMissingSizeInternal(
852  std::size_t val,
853  details::MissingSizeRetriever<> retriever,
854  TExtraValues... extraValues)
855  {
856  retriever.setValue(val);
857  updateMissingSizeInternal(val, extraValues...);
858  }
859 
860  template <typename T, typename... TExtraValues>
861  static void updateMissingSizeInternal(std::size_t val, T retriever, TExtraValues... extraValues)
862  {
863  static_cast<void>(retriever);
864  static_assert(
865  !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
866  "Mustn't be missing size retriever");
867  updateMissingSizeInternal(val, extraValues...);
868  }
869 
870  static constexpr bool setPayloadRequiredInternal()
871  {
872  return false;
873  }
874 
875  template <typename TIter, typename... TExtraValues>
876  static bool setPayloadRequiredInternal(details::MsgPayloadRetriever<TIter>, TExtraValues...)
877  {
878  return true;
879  }
880 
881  template <typename T, typename... TExtraValues>
882  static bool setPayloadRequiredInternal(T, TExtraValues... extraValues)
883  {
884  static_assert(
885  !details::isMsgPayloadRetriever<T>(),
886  "Mustn't be message payload retriever");
887  return setPayloadRequiredInternal(extraValues...);
888  }
889 
890  template <typename TIter>
891  static void setMsgPayloadInternal(TIter iter, std::size_t len)
892  {
893  static_cast<void>(iter);
894  static_cast<void>(len);
895  }
896 
897  template <typename TIter, typename TOtherIter, typename... TExtraValues>
898  static void setMsgPayloadInternal(
899  TIter iter,
900  std::size_t len,
901  details::MsgPayloadRetriever<TOtherIter> retriever,
902  TExtraValues... extraValues)
903  {
904  retriever.setValue(iter, len);
905  setMsgPayloadInternal(iter, len, extraValues...);
906  }
907 
908  template <typename TIter, typename T, typename... TExtraValues>
909  static void setMsgPayloadInternal(
910  TIter iter,
911  std::size_t len,
912  T retriever,
913  TExtraValues... extraValues)
914  {
915  static_cast<void>(retriever);
916  static_assert(
917  !details::isMsgPayloadRetriever<typename std::decay<decltype(retriever)>::type>(),
918  "Mustn't be message payload retriever");
919  setMsgPayloadInternal(iter, len, extraValues...);
920  }
921 };
922 
923 namespace details
924 {
925 template <typename T>
926 struct MsgDataLayerCheckHelper
927 {
928  static const bool Value = false;
929 };
930 
931 template <typename... TExtraOpts>
932 struct MsgDataLayerCheckHelper<MsgDataLayer<TExtraOpts...> >
933 {
934  static const bool Value = true;
935 };
936 
937 } // namespace details
938 
942 template <typename T>
943 constexpr bool isMsgDataLayer()
944 {
945  return details::MsgDataLayerCheckHelper<T>::Value;
946 }
947 
948 template <typename... TExtraOpts>
949 constexpr
950 MsgDataLayer<TExtraOpts...>&
951 toProtocolLayerBase(MsgDataLayer<TExtraOpts...>& layer)
952 {
953  return layer;
954 }
955 
956 template <typename... TExtraOpts>
957 constexpr
958 const MsgDataLayer<TExtraOpts...>&
959 toProtocolLayerBase(const MsgDataLayer<TExtraOpts...>& layer)
960 {
961  return layer;
962 }
963 
964 } // namespace protocol
965 
966 } // namespace comms
967 
968 
969 
Contains definition of comms::field::ArrayList.
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
Field that represents a sequential collection of fields.
Definition: ArrayList.h:192
Message data layer.
Definition: MsgDataLayer.h:42
static comms::ErrorStatus update(TIter &iter, std::size_t size)
Update recently written (using write()) message contents data.
Definition: MsgDataLayer.h:408
const ThisLayer & thisLayer() const
Get "const" access to this layer object.
Definition: MsgDataLayer.h:54
constexpr bool isMsgDataLayer()
Compile time check of whether the provided type is a variant of MsgDataLayer.
Definition: MsgDataLayer.h:943
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:521
static ErrorStatus readFromDataFeildsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Same as readFieldsCached().
Definition: MsgDataLayer.h:289
static ErrorStatus readFromData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Same as read().
Definition: MsgDataLayer.h:185
MsgDataLayer(MsgDataLayer &&)=default
Move constructor.
static constexpr std::size_t length(const TMsg &msg)
Get remaining length of wrapping transport information + length of the provided message.
Definition: MsgDataLayer.h:498
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:467
void AllMessages
Default value of AllMessages type.
Definition: MsgDataLayer.h:74
static const std::size_t NumOfLayers
Static constant indicating amount of transport layers used.
Definition: MsgDataLayer.h:81
void MsgFactory
Default value of MsgFactory type.
Definition: MsgDataLayer.h:78
static ErrorStatus read(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Read the message contents.
Definition: MsgDataLayer.h:129
std::tuple< Field > AllFields
All fields of the remaining transport layers, contains only Field.
Definition: MsgDataLayer.h:70
static constexpr bool canSplitRead()
Compile time check whether split read "until" and "from" data layer is allowed.
Definition: MsgDataLayer.h:104
static ErrorStatus write(const TMsg &msg, TIter &iter, std::size_t size)
Write the message contents.
Definition: MsgDataLayer.h:317
static ErrorStatus readUntilData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues...)
Read transport fields until data layer.
Definition: MsgDataLayer.h:168
MsgDataLayer()=default
Default constructor.
comms::field::ArrayList< comms::Field< comms::option::def::BigEndian >, std::uint8_t, TExtraOpts... > Field
Raw data field type.
Definition: MsgDataLayer.h:67
static comms::ErrorStatus update(const TMsg &msg, TIter &iter, std::size_t size)
Update recently written (using write()) message contents data.
Definition: MsgDataLayer.h:421
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:219
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:441
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:365
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:270
static constexpr std::size_t length()
Get remaining length of wrapping transport information.
Definition: MsgDataLayer.h:484
ThisLayer & thisLayer()
Get access to this layer object.
Definition: MsgDataLayer.h:48
~MsgDataLayer() noexcept=default
Destructor.
MsgDataLayer(const MsgDataLayer &)=default
Copy constructor.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition: options.h:1459
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition: options.h:1463
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:35
Replacement to some types from standard type_traits.