COMMS
Template library intended to help with implementation of communication protocols.
ProtocolLayerBase.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 <utility>
15 #include <algorithm>
16 #include <iterator>
17 
18 #include "comms/CompileControl.h"
19 #include "comms/ErrorStatus.h"
20 #include "comms/util/Tuple.h"
21 #include "comms/util/type_traits.h"
22 #include "comms/Assert.h"
23 #include "comms/options.h"
24 
25 #include "comms/protocol/details/ProtocolLayerBaseOptionsParser.h"
26 #include "comms/protocol/details/ProtocolLayerDetails.h"
27 #include "comms/details/protocol_layers_access.h"
28 #include "comms/details/detect.h"
29 #include "comms/details/tag.h"
30 
31 COMMS_MSVC_WARNING_PUSH
32 COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
33 
34 namespace comms
35 {
36 
37 namespace protocol
38 {
39 
55 template <
56  typename TField,
57  typename TNextLayer,
58  typename TDerived,
59  typename... TOptions>
61 {
62 public:
64  using Field = TField;
65 
67  using NextLayer = TNextLayer;
68 
70  using ParsedOptions = details::ProtocolLayerBaseOptionsParser<TOptions...>;
71 
76  using AllFields = typename std::decay<
77  decltype(
78  std::tuple_cat(
79  std::declval<std::tuple<Field> >(),
80  std::declval<typename TNextLayer::AllFields>())
81  )
82  >::type;
83 
87  using AllMessages = typename NextLayer::AllMessages;
88 
92  using MsgFactory = typename NextLayer::MsgFactory;
93 
96  using MsgPtr = typename details::ProtocolLayerMsgPtr<NextLayer>::Type;
97 
99  using ThisLayer = TDerived;
100 
102  static const std::size_t NumOfLayers = 1 + NextLayer::NumOfLayers;
103 
106 
109 
114  template <typename... TArgs>
115  explicit ProtocolLayerBase(TArgs&&... args)
116  : nextLayer_(std::forward<TArgs>(args)...)
117  {
118  }
119 
121  ~ProtocolLayerBase() noexcept = default;
122 
124  ProtocolLayerBase& operator=(const ProtocolLayerBase&) = default;
125 
127  NextLayer& nextLayer()
128  {
129  return nextLayer_;
130  }
131 
133  const NextLayer& nextLayer() const
134  {
135  return nextLayer_;
136  }
137 
140  {
141  return static_cast<ThisLayer&>(*this);
142  }
143 
145  const ThisLayer& thisLayer() const
146  {
147  return static_cast<const ThisLayer&>(*this);
148  }
149 
152  static constexpr bool canSplitRead()
153  {
154  return (!ParsedOptions::HasDisallowReadUntilDataSplit) && NextLayer::canSplitRead();
155  }
156 
212  template <typename TMsg, typename TIter, typename... TExtraValues>
214  TMsg& msg,
215  TIter& iter,
216  std::size_t size,
217  TExtraValues... extraValues)
218  {
219  using Tag =
220  typename comms::util::LazyShallowConditional<
221  ParsedOptions::HasForceReadUntilDataSplit
222  >::template Type<
223  SplitReadTag,
224  NormalReadTag
225  >;
226 
227  static_assert(std::is_same<Tag, NormalReadTag<> >::value || canSplitRead(),
228  "Read split is disallowed by at least one of the inner layers");
229  return readInternal(msg, iter, size, Tag(), extraValues...);
230  }
231 
256  template <typename TMsg, typename TIter, typename... TExtraValues>
258  TMsg& msg,
259  TIter& iter,
260  std::size_t size,
261  TExtraValues... extraValues)
262  {
263 
264  Field field;
265  auto& derivedObj = static_cast<TDerived&>(*this);
266  auto reader = createNextLayerUntilDataReader();
267  return
268  derivedObj.doRead(
269  field,
270  msg,
271  iter,
272  size,
273  reader,
274  extraValues...);
275  }
276 
299  template <typename TMsg, typename TIter, typename... TExtraValues>
301  TMsg& msg,
302  TIter& iter,
303  std::size_t size,
304  TExtraValues... extraValues)
305  {
306  return nextLayer().readFromData(msg, iter, size, extraValues...);
307  }
308 
334  template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
336  TAllFields& allFields,
337  TMsg& msg,
338  TIter& iter,
339  std::size_t size,
340  TExtraValues... extraValues)
341  {
342  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
343  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
344  static const std::size_t Idx =
345  std::tuple_size<AllFieldsDecayed>::value -
346  std::tuple_size<AllFields>::value;
347  auto& field = getField<Idx>(allFields);
348  auto& derivedObj = static_cast<TDerived&>(*this);
349  auto reader = createNextLayerCachedFieldsReader(allFields);
350  return
351  derivedObj.doRead(
352  field,
353  msg,
354  iter,
355  size,
356  reader,
357  extraValues...);
358  }
359 
385  template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
387  TAllFields& allFields,
388  TMsg& msg,
389  TIter& iter,
390  std::size_t size,
391  TExtraValues... extraValues)
392  {
393  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
394  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
395  static const std::size_t Idx =
396  std::tuple_size<AllFieldsDecayed>::value -
397  std::tuple_size<AllFields>::value;
398 
399  auto& field = getField<Idx>(allFields);
400  auto& derivedObj = static_cast<TDerived&>(*this);
401  auto reader = createNextLayerCachedFieldsUntilDataReader(allFields);
402  return
403  derivedObj.doRead(
404  field,
405  msg,
406  iter,
407  size,
408  reader,
409  extraValues...);
410  }
411 
435  template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
437  TAllFields& allFields,
438  TMsg& msg,
439  TIter& iter,
440  std::size_t size,
441  TExtraValues... extraValues)
442  {
443  return nextLayer().readFromDataFieldsCached(allFields, msg, iter, size, extraValues...);
444  }
445 
485  template <typename TMsg, typename TIter>
487  const TMsg& msg,
488  TIter& iter,
489  std::size_t size) const
490  {
491  Field field;
492  auto& derivedObj = static_cast<const TDerived&>(*this);
493  auto writer = createNextLayerWriter();
494  return derivedObj.doWrite(field, msg, iter, size, writer);
495  }
496 
514  template <typename TAllFields, typename TMsg, typename TIter>
516  TAllFields& allFields,
517  const TMsg& msg,
518  TIter& iter,
519  std::size_t size) const
520  {
521  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
522  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
523  static const std::size_t Idx =
524  std::tuple_size<AllFieldsDecayed>::value -
525  std::tuple_size<AllFields>::value;
526 
527  auto& field = getField<Idx>(allFields);
528  auto& derivedObj = static_cast<const TDerived&>(*this);
529  auto writer = createNextLayerCachedFieldsWriter(allFields);
530  return derivedObj.doWrite(field, msg, iter, size, writer);
531  }
532 
541  constexpr std::size_t length() const
542  {
543  return thisLayer().doFieldLength() + nextLayer_.length();
544  }
545 
558  template <typename TMsg>
559  constexpr std::size_t length(const TMsg& msg) const
560  {
561  return thisLayer().doFieldLength(msg) + nextLayer_.length(msg);
562  }
563 
600  template <typename TIter>
601  comms::ErrorStatus update(TIter& iter, std::size_t size) const
602  {
603  Field field;
604  auto& derivedObj = static_cast<const TDerived&>(*this);
605  auto updater = createNextLayerUpdater();
606  return derivedObj.doUpdate(field, iter, size, updater);
607  }
608 
616  template <typename TMsg, typename TIter>
617  comms::ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size) const
618  {
619  Field field;
620  auto& derivedObj = static_cast<const TDerived&>(*this);
621  auto updater = createNextLayerUpdater();
622  return derivedObj.doUpdate(msg, field, iter, size, updater);
623  }
624 
640  template <typename TAllFields, typename TIter>
642  TAllFields& allFields,
643  TIter& iter,
644  std::size_t size) const
645  {
646  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
647  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
648  static const std::size_t Idx =
649  std::tuple_size<AllFieldsDecayed>::value -
650  std::tuple_size<AllFields>::value;
651 
652  auto& field = getField<Idx>(allFields);
653  auto& derivedObj = static_cast<const TDerived&>(*this);
654  auto updater = createNextLayerCachedFieldsUpdater(allFields);
655  return derivedObj.doUpdate(field, iter, size, updater);
656  }
657 
675  template <typename TAllFields, typename TMsg, typename TIter>
677  TAllFields& allFields,
678  const TMsg& msg,
679  TIter& iter,
680  std::size_t size) const
681  {
682  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
683  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
684  static const std::size_t Idx =
685  std::tuple_size<AllFieldsDecayed>::value -
686  std::tuple_size<AllFields>::value;
687 
688  auto& field = getField<Idx>(allFields);
689  auto& derivedObj = static_cast<const TDerived&>(*this);
690  auto updater = createNextLayerCachedFieldsUpdater(allFields);
691  return derivedObj.doUpdate(msg, field, iter, size, updater);
692  }
693 
706  template <typename TIter, typename TNextLayerUpdater>
708  Field& field,
709  TIter& iter,
710  std::size_t size,
711  TNextLayerUpdater&& nextLayerUpdater) const
712  {
713  return updateInternal(field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), LengthTag<>());
714  }
715 
727  template <typename TMsg, typename TIter, typename TNextLayerUpdater>
729  const TMsg& msg,
730  Field& field,
731  TIter& iter,
732  std::size_t size,
733  TNextLayerUpdater&& nextLayerUpdater) const
734  {
735  return updateInternal(msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), LengthTag<>());
736  }
737 
744  static constexpr std::size_t doFieldLength()
745  {
746  return Field::minLength();
747  }
748 
756  template <typename TMsg>
757  static constexpr std::size_t doFieldLength(const TMsg&)
758  {
759  return doFieldLength();
760  }
761 
771  template <typename TId>
772  MsgPtr createMsg(TId&& id, unsigned idx = 0)
773  {
774  return nextLayer().createMsg(std::forward<TId>(id), idx);
775  }
776 
781  template <typename TAllFields>
782  static auto accessCachedField(TAllFields& allFields) ->
783  decltype(std::get<std::tuple_size<typename std::decay<TAllFields>::type>::value - std::tuple_size<AllFields>::value>(allFields))
784  {
785  using AllFieldsDecayed = typename std::decay<TAllFields>::type;
786  static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
787  static const std::size_t Idx =
788  std::tuple_size<AllFieldsDecayed>::value -
789  std::tuple_size<AllFields>::value;
790 
791  return std::get<Idx>(allFields);
792  }
793 
794 protected:
803  template <typename TMsg, typename TIter>
804  static comms::ErrorStatus doReadField(const TMsg* msgPtr, Field& field, TIter& iter, std::size_t len)
805  {
806  static_cast<void>(msgPtr);
807  return field.read(iter, len);
808  }
809 
818  template <typename TMsg, typename TIter>
819  static comms::ErrorStatus doWriteField(const TMsg* msgPtr, const Field& field, TIter& iter, std::size_t len)
820  {
821  static_cast<void>(msgPtr);
822  return field.write(iter, len);
823  }
824 
829  template <typename T>
830  static constexpr bool isMessageObjRef()
831  {
832  return comms::details::hasImplOptions<T>();
833  }
834 
838  template <typename TMsg>
839  static void resetMsg(TMsg& msg)
840  {
841  resetMsgInternal(msg, MsgTypeTag<typename std::decay<decltype(msg)>::type>());
842  }
843 
844 private:
845  template <typename... TParams>
846  using MessageObjTag = comms::details::tag::Tag5<>;
847 
848  template <typename... TParams>
849  using SmartPtrTag = comms::details::tag::Tag6<>;
850 
851  template <typename TMsg>
852  using MsgTypeTag =
853  typename comms::util::LazyShallowConditional<
854  comms::details::hasImplOptions<TMsg>()
855  >::template Type<
856  MessageObjTag,
857  SmartPtrTag
858  >;
859 
860  template <typename TMsg, typename... TParams>
861  static auto toMsgPtrInternal(TMsg& msg, MessageObjTag<TParams...>) -> decltype(&msg)
862  {
863  return &msg;
864  }
865 
866  template <typename TMsg, typename... TParams>
867  static auto toMsgPtrInternal(TMsg& msg, SmartPtrTag<TParams...>) -> decltype(msg.get())
868  {
869  return msg.get();
870  }
871 
872 protected:
877  template <typename TMsg>
878  static auto toMsgPtr(TMsg& msg) -> decltype(toMsgPtrInternal(msg, MsgTypeTag<typename std::decay<decltype(msg)>::type>()))
879  {
880  return toMsgPtrInternal(msg, MsgTypeTag<typename std::decay<decltype(msg)>::type>());
881  }
882 
891  template <typename... TExtraValues>
892  void updateMissingSize(std::size_t size, TExtraValues... extraValues) const
893  {
894  return updateMissingSizeInternal(size, extraValues...);
895  }
896 
906  template <typename... TExtraValues>
908  const Field& field,
909  std::size_t size,
910  TExtraValues... extraValues) const
911  {
912  return updateMissingSizeInternal(field, size, extraValues...);
913  }
914 
922  template <typename... TExtraValues>
924  std::size_t val,
925  TExtraValues... extraValues) const
926  {
927  return setMissingSizeInternal(val, extraValues...);
928  }
929 
937  template <typename TId, typename... TExtraValues>
938  void setMsgId(
939  TId val,
940  TExtraValues... extraValues) const
941  {
942  return setMsgIdInternal(val, extraValues...);
943  }
944 
952  template <typename... TExtraValues>
954  std::size_t val,
955  TExtraValues... extraValues) const
956  {
957  return setMsgIndexInternal(val, extraValues...);
958  }
959 
963  template <std::size_t TIdx, typename TAllFields>
964  static Field& getField(TAllFields& allFields)
965  {
967  "Expected TAllFields to be a tuple");
968  static_assert(TIdx < std::tuple_size<TAllFields>::value,
969  "Invalid tuple access index");
970 
971  auto& field = std::get<TIdx>(allFields);
972 
973  using FieldType = typename std::decay<decltype(field)>::type;
974  static_assert(
975  std::is_same<Field, FieldType>::value,
976  "Field has wrong type");
977 
978  return field;
979  }
980 
982  template <typename... TParams>
983  using FixedLengthTag = comms::details::tag::Tag1<>;
984 
985  template <typename... TParams>
986  using VarLengthTag = comms::details::tag::Tag2<>;
987 
988  static constexpr std::size_t MinFieldLength = Field::minLength();
989  static constexpr std::size_t MaxFieldLength = Field::maxLength();
990 
991  template <typename...>
992  using LengthTag =
993  typename comms::util::LazyShallowConditional<
994  (MinFieldLength == MaxFieldLength)
995  >::template Type<
996  FixedLengthTag,
997  VarLengthTag
998  >;
999 
1000  class NextLayerReader
1001  {
1002  public:
1003  explicit NextLayerReader(NextLayer& nextLayer)
1004  : nextLayer_(nextLayer)
1005  {
1006  }
1007 
1008  template <typename TMsgPtr, typename TIter, typename... TExtraValues>
1009  ErrorStatus read(
1010  TMsgPtr& msg,
1011  TIter& iter,
1012  std::size_t size,
1013  TExtraValues... extraValues)
1014  {
1015  return nextLayer_.read(msg, iter, size, extraValues...);
1016  }
1017  private:
1018  NextLayer& nextLayer_;
1019  };
1020 
1021  class NextLayerUntilDataReader
1022  {
1023  public:
1024  explicit NextLayerUntilDataReader(NextLayer& nextLayer)
1025  : nextLayer_(nextLayer)
1026  {
1027  }
1028 
1029  template <typename TMsgPtr, typename TIter, typename... TExtraValues>
1030  ErrorStatus read(
1031  TMsgPtr& msg,
1032  TIter& iter,
1033  std::size_t size,
1034  TExtraValues... extraValues)
1035  {
1036  return nextLayer_.readUntilData(msg, iter, size, extraValues...);
1037  }
1038  private:
1039  NextLayer& nextLayer_;
1040  };
1041 
1042  template <typename TAllFields>
1043  class NextLayerCachedFieldsReader
1044  {
1045  public:
1046  NextLayerCachedFieldsReader(
1047  NextLayer& nextLayer,
1048  TAllFields& allFields)
1049  : nextLayer_(nextLayer),
1050  allFields_(allFields)
1051  {
1052  }
1053 
1054  template<typename TMsgPtr, typename TIter, typename... TExtraValues>
1055  ErrorStatus read(
1056  TMsgPtr& msg,
1057  TIter& iter,
1058  std::size_t size,
1059  TExtraValues... extraValues)
1060  {
1061  return nextLayer_.readFieldsCached(allFields_, msg, iter, size, extraValues...);
1062  }
1063 
1064  private:
1065  NextLayer& nextLayer_;
1066  TAllFields& allFields_;
1067  };
1068 
1069  template <typename TAllFields>
1070  class NextLayerCachedFieldsUntilDataReader
1071  {
1072  public:
1073  NextLayerCachedFieldsUntilDataReader(
1074  NextLayer& nextLayer,
1075  TAllFields& allFields)
1076  : nextLayer_(nextLayer),
1077  allFields_(allFields)
1078  {
1079  }
1080 
1081  template<typename TMsgPtr, typename TIter, typename... TExtraValues>
1082  ErrorStatus read(
1083  TMsgPtr& msg,
1084  TIter& iter,
1085  std::size_t size,
1086  TExtraValues... extraValues)
1087  {
1088  return nextLayer_.readUntilDataFieldsCache(allFields_, msg, iter, size, extraValues...);
1089  }
1090 
1091  private:
1092  NextLayer& nextLayer_;
1093  TAllFields& allFields_;
1094  };
1095 
1096  class NextLayerWriter
1097  {
1098  public:
1099 
1100  explicit NextLayerWriter(const NextLayer& nextLayer)
1101  : nextLayer_(nextLayer)
1102  {
1103  }
1104 
1105  template <typename TMsg, typename TIter>
1106  ErrorStatus write(const TMsg& msg, TIter& iter, std::size_t size) const
1107  {
1108  return nextLayer_.write(msg, iter, size);
1109  }
1110 
1111  private:
1112  const NextLayer& nextLayer_;
1113  };
1114 
1115  template <typename TAllFields>
1116  class NextLayerCachedFieldsWriter
1117  {
1118  public:
1119  NextLayerCachedFieldsWriter(
1120  const NextLayer& nextLayer,
1121  TAllFields& allFields)
1122  : nextLayer_(nextLayer),
1123  allFields_(allFields)
1124  {
1125  }
1126 
1127  template <typename TMsg, typename TIter>
1128  ErrorStatus write(const TMsg& msg, TIter& iter, std::size_t size) const
1129  {
1130  return nextLayer_.writeFieldsCached(allFields_, msg, iter, size);
1131  }
1132 
1133  private:
1134  const NextLayer& nextLayer_;
1135  TAllFields& allFields_;
1136  };
1137 
1138  class NextLayerUpdater
1139  {
1140  public:
1141 
1142  explicit NextLayerUpdater(const NextLayer& nextLayer)
1143  : nextLayer_(nextLayer)
1144  {
1145  }
1146 
1147  template <typename TIter>
1148  ErrorStatus update(TIter& iter, std::size_t size) const
1149  {
1150  return nextLayer_.update(iter, size);
1151  }
1152 
1153  template <typename TMsg, typename TIter>
1154  ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size) const
1155  {
1156  return nextLayer_.update(msg, iter, size);
1157  }
1158 
1159  private:
1160  const NextLayer& nextLayer_;
1161  };
1162 
1163  template <typename TAllFields>
1164  class NextLayerCachedFieldsUpdater
1165  {
1166  public:
1167  NextLayerCachedFieldsUpdater(
1168  const NextLayer& nextLayer,
1169  TAllFields& allFields)
1170  : nextLayer_(nextLayer),
1171  allFields_(allFields)
1172  {
1173  }
1174 
1175  template <typename TIter>
1176  ErrorStatus update(TIter& iter, std::size_t size) const
1177  {
1178  return nextLayer_.updateFieldsCached(allFields_, iter, size);
1179  }
1180 
1181  template <typename TMsg, typename TIter>
1182  ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size) const
1183  {
1184  return nextLayer_.updateFieldsCached(allFields_, msg, iter, size);
1185  }
1186 
1187  private:
1188  const NextLayer& nextLayer_;
1189  TAllFields& allFields_;
1190  };
1191 
1192  NextLayerReader createNextLayerReader()
1193  {
1194  return NextLayerReader(nextLayer_);
1195  }
1196 
1197  NextLayerUntilDataReader createNextLayerUntilDataReader()
1198  {
1199  return NextLayerUntilDataReader(nextLayer_);
1200  }
1201 
1202  template <typename TAllFields>
1203  NextLayerCachedFieldsReader<TAllFields>
1204  createNextLayerCachedFieldsReader(TAllFields& fields)
1205  {
1206  return NextLayerCachedFieldsReader<TAllFields>(nextLayer_, fields);
1207  }
1208 
1209  template <typename TAllFields>
1210  NextLayerCachedFieldsUntilDataReader<TAllFields>
1211  createNextLayerCachedFieldsUntilDataReader(TAllFields& fields)
1212  {
1213  return NextLayerCachedFieldsUntilDataReader<TAllFields>(nextLayer_, fields);
1214  }
1215 
1216  NextLayerWriter createNextLayerWriter() const
1217  {
1218  return NextLayerWriter(nextLayer_);
1219  }
1220 
1221  template <typename TAllFields>
1222  NextLayerCachedFieldsWriter<TAllFields>
1223  createNextLayerCachedFieldsWriter(TAllFields& fields) const
1224  {
1225  return NextLayerCachedFieldsWriter<TAllFields>(nextLayer_, fields);
1226  }
1227 
1228  NextLayerUpdater createNextLayerUpdater() const
1229  {
1230  return NextLayerUpdater(nextLayer_);
1231  }
1232 
1233  template <typename TAllFields>
1234  NextLayerCachedFieldsUpdater<TAllFields>
1235  createNextLayerCachedFieldsUpdater(TAllFields& fields) const
1236  {
1237  return NextLayerCachedFieldsUpdater<TAllFields>(nextLayer_, fields);
1238  }
1239 
1241 private:
1242 
1243  template <typename... TParams>
1244  using NormalReadTag = comms::details::tag::Tag3<>;
1245 
1246  template <typename... TParams>
1247  using SplitReadTag = comms::details::tag::Tag4<>;
1248 
1249  template <typename TMsg, typename TIter, typename... TExtraValues>
1250  comms::ErrorStatus readInternal(
1251  TMsg& msg,
1252  TIter& iter,
1253  std::size_t size,
1254  NormalReadTag<>,
1255  TExtraValues... extraValues)
1256  {
1257  Field field;
1258  auto& derivedObj = static_cast<TDerived&>(*this);
1259  auto reader = createNextLayerReader();
1260  return derivedObj.doRead(field, msg, iter, size, reader, extraValues...);
1261  }
1262 
1263  template <typename TMsgPtr, typename TIter, typename... TExtraValues>
1264  comms::ErrorStatus readInternal(
1265  TMsgPtr& msgPtr,
1266  TIter& iter,
1267  std::size_t size,
1268  SplitReadTag<>,
1269  TExtraValues... extraValues)
1270  {
1271  auto fromIter = iter;
1272  auto es = readUntilData(msgPtr, iter, size, extraValues...);
1273  if (es != comms::ErrorStatus::Success) {
1274  return es;
1275  }
1276 
1277  auto consumed = static_cast<std::size_t>(std::distance(fromIter, iter));
1278  COMMS_ASSERT(consumed <= size);
1279  return readFromData(msgPtr, iter, size - consumed, extraValues...);
1280  }
1281 
1282  template <typename TIter, typename TNextLayerUpdater, typename... TParams>
1283  comms::ErrorStatus updateInternal(
1284  Field& field,
1285  TIter& iter,
1286  std::size_t size,
1287  TNextLayerUpdater&& nextLayerUpdater,
1288  FixedLengthTag<TParams...>) const
1289  {
1290  auto len = field.length();
1291  COMMS_ASSERT(len <= size);
1292  std::advance(iter, len);
1293  return nextLayerUpdater.update(iter, size - len);
1294  }
1295 
1296  template <typename TIter, typename TNextLayerUpdater, typename... TParams>
1297  comms::ErrorStatus updateInternal(
1298  Field& field,
1299  TIter& iter,
1300  std::size_t size,
1301  TNextLayerUpdater&& nextLayerUpdater,
1302  VarLengthTag<TParams...>) const
1303  {
1304  auto iterTmp = iter;
1305  auto es = field.read(iter, size);
1306  if (es == comms::ErrorStatus::Success) {
1307  auto diff = static_cast<std::size_t>(std::distance(iterTmp, iter));
1308  es = nextLayerUpdater.update(iter, size - diff);
1309  }
1310  return es;
1311  }
1312 
1313  template <typename TMsg, typename TIter, typename TNextLayerUpdater, typename... TParams>
1314  comms::ErrorStatus updateInternal(
1315  const TMsg& msg,
1316  Field& field,
1317  TIter& iter,
1318  std::size_t size,
1319  TNextLayerUpdater&& nextLayerUpdater,
1320  FixedLengthTag<TParams...>) const
1321  {
1322  auto len = field.length();
1323  COMMS_ASSERT(len <= size);
1324  std::advance(iter, len);
1325  return nextLayerUpdater.update(msg, iter, size - len);
1326  }
1327 
1328  template <typename TMsg, typename TIter, typename TNextLayerUpdater, typename... TParams>
1329  comms::ErrorStatus updateInternal(
1330  const TMsg& msg,
1331  Field& field,
1332  TIter& iter,
1333  std::size_t size,
1334  TNextLayerUpdater&& nextLayerUpdater,
1335  VarLengthTag<TParams...>) const
1336  {
1337  auto iterTmp = iter;
1338  auto es = field.read(iter, size);
1339  if (es == comms::ErrorStatus::Success) {
1340  auto diff = static_cast<std::size_t>(std::distance(iterTmp, iter));
1341  es = nextLayerUpdater.update(msg, iter, size - diff);
1342  }
1343  return es;
1344  }
1345 
1346  template <typename TMsg, typename... TParams>
1347  static void resetMsgInternal(TMsg&, MessageObjTag<TParams...>)
1348  {
1349  // Do nothing
1350  }
1351 
1352  template <typename TMsg, typename... TParams>
1353  static void resetMsgInternal(TMsg& msg, SmartPtrTag<TParams...>)
1354  {
1355  msg.reset();
1356  }
1357 
1358  static void updateMissingSizeInternal(std::size_t size)
1359  {
1360  static_cast<void>(size);
1361  }
1362 
1363  static void updateMissingSizeInternal(const Field& field, std::size_t size)
1364  {
1365  static_cast<void>(field);
1366  static_cast<void>(size);
1367  }
1368 
1369  template <typename... TExtraValues>
1370  void updateMissingSizeInternal(
1371  std::size_t size,
1372  details::MissingSizeRetriever<> retriever,
1373  TExtraValues... extraValues) const
1374  {
1375  COMMS_ASSERT(size <= length());
1376  retriever.setValue(std::max(std::size_t(1U), length() - size));
1377  updateMissingSizeInternal(size, extraValues...);
1378  }
1379 
1380  template <typename... TExtraValues>
1381  void updateMissingSizeInternal(
1382  const Field& field,
1383  std::size_t size,
1384  details::MissingSizeRetriever<> retriever,
1385  TExtraValues... extraValues) const
1386  {
1387  static_assert(
1388  details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1389  "Must be missing size retriever");
1390  auto totalLen = field.length() + nextLayer_.length();
1391  COMMS_ASSERT(size <= totalLen);
1392  retriever.setValue(std::max(std::size_t(1U), totalLen - size));
1393  updateMissingSizeInternal(size, extraValues...);
1394  }
1395 
1396  template <typename T, typename... TExtraValues>
1397  void updateMissingSizeInternal(
1398  std::size_t size,
1399  T retriever,
1400  TExtraValues... extraValues) const
1401  {
1402  static_cast<void>(retriever);
1403  static_assert(
1404  !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1405  "Mustn't be missing size retriever");
1406  updateMissingSizeInternal(size, extraValues...);
1407  }
1408 
1409  template <typename T, typename... TExtraValues>
1410  void updateMissingSizeInternal(
1411  const Field& field,
1412  std::size_t size,
1413  T retriever,
1414  TExtraValues... extraValues) const
1415  {
1416  static_cast<void>(retriever);
1417  static_assert(
1418  !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1419  "Mustn't be missing size retriever");
1420  updateMissingSizeInternal(field, size, extraValues...);
1421  }
1422 
1423  static void setMissingSizeInternal(std::size_t val)
1424  {
1425  static_cast<void>(val);
1426  }
1427 
1428  template <typename... TExtraValues>
1429  static void setMissingSizeInternal(
1430  std::size_t val,
1431  details::MissingSizeRetriever<> retriever,
1432  TExtraValues... extraValues)
1433  {
1434  retriever.setValue(val);
1435  setMissingSizeInternal(val, extraValues...);
1436  }
1437 
1438  template <typename T, typename... TExtraValues>
1439  static void setMissingSizeInternal(
1440  std::size_t val,
1441  T retriever,
1442  TExtraValues... extraValues)
1443  {
1444  static_cast<void>(retriever);
1445  static_assert(
1446  !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1447  "Mustn't be missing size retriever");
1448  setMissingSizeInternal(val, extraValues...);
1449  }
1450 
1451  template <typename TId>
1452  static void setMsgIdInternal(TId val)
1453  {
1454  static_cast<void>(val);
1455  }
1456 
1457  template <typename TId, typename U, typename... TExtraValues>
1458  static void setMsgIdInternal(
1459  TId val,
1460  details::MsgIdRetriever<U> retriever,
1461  TExtraValues... extraValues)
1462  {
1463  retriever.setValue(val);
1464  setMsgIdInternal(val, extraValues...);
1465  }
1466 
1467  template <typename TId, typename T, typename... TExtraValues>
1468  static void setMsgIdInternal(
1469  TId val,
1470  T retriever,
1471  TExtraValues... extraValues)
1472  {
1473  static_cast<void>(retriever);
1474  static_assert(
1475  !details::isMsgIdRetriever<typename std::decay<decltype(retriever)>::type>(),
1476  "Mustn't be message id retriever");
1477  setMsgIdInternal(val, extraValues...);
1478  }
1479 
1480  static void setMsgIndexInternal(std::size_t val)
1481  {
1482  static_cast<void>(val);
1483  }
1484 
1485  template <typename... TExtraValues>
1486  static void setMsgIndexInternal(
1487  std::size_t val,
1488  details::MsgIndexRetriever retriever,
1489  TExtraValues... extraValues)
1490  {
1491  retriever.setValue(val);
1492  setMsgIndexInternal(val, extraValues...);
1493  }
1494 
1495  template <typename T, typename... TExtraValues>
1496  static void setMsgIndexInternal(
1497  std::size_t val,
1498  T retriever,
1499  TExtraValues... extraValues)
1500  {
1501  static_cast<void>(retriever);
1502  static_assert(
1503  !details::isMsgIndexRetriever<typename std::decay<decltype(retriever)>::type>(),
1504  "Mustn't be missing size retriever");
1505  setMsgIndexInternal(val, extraValues...);
1506  }
1507 
1508  static_assert (comms::util::IsTuple<AllFields>::Value, "Must be tuple");
1509  NextLayer nextLayer_;
1510 };
1511 
1514 template <
1515  typename TField,
1516  typename TNextLayer,
1517  typename TDerived,
1518  typename... TOptions>
1519 ProtocolLayerBase<TField, TNextLayer, TDerived, TOptions...>&
1521 {
1522  return layer;
1523 }
1524 
1527 template <
1528  typename TField,
1529  typename TNextLayer,
1530  typename TDerived,
1531  typename... TOptions>
1532 constexpr
1533 const ProtocolLayerBase<TField, TNextLayer, TDerived, TOptions...>&
1535 {
1536  return layer;
1537 }
1538 
1560 inline
1561 details::MissingSizeRetriever<> missingSize(std::size_t& val)
1562 {
1563  return details::MissingSizeRetriever<>(val);
1564 }
1565 
1587 template <typename TId>
1588 details::MsgIdRetriever<TId> msgId(TId& val)
1589 {
1590  return details::MsgIdRetriever<TId>(val);
1591 }
1592 
1625 inline
1626 details::MsgIndexRetriever msgIndex(std::size_t& val)
1627 {
1628  return details::MsgIndexRetriever(val);
1629 }
1630 
1653 template <typename TIter>
1654 details::MsgPayloadRetriever<TIter> msgPayload(TIter& iter, std::size_t& len)
1655 {
1656  return details::MsgPayloadRetriever<TIter>(iter, len);
1657 }
1658 
1659 } // namespace protocol
1660 
1661 } // namespace comms
1662 
1669 #define COMMS_PROTOCOL_LAYERS_ACCESS(...) \
1670  COMMS_DO_ACCESS_LAYER_ACC_FUNC(__VA_ARGS__)
1671 
1678 #define COMMS_PROTOCOL_LAYERS_NAMES(...) \
1679  COMMS_DO_LAYER_TYPE_ALIAS(Base, __VA_ARGS__) \
1680  COMMS_DO_ACCESS_LAYER_ACC_FUNC(__VA_ARGS__)
1681 
1682 
1685 #define COMMS_PROTOCOL_LAYERS_ACCESS_INNER(...) \
1686  COMMS_PROTOCOL_LAYERS_ACCESS(__VA_ARGS__)
1687 
1690 #define COMMS_PROTOCOL_LAYERS_NAMES_INNER(...) \
1691  COMMS_PROTOCOL_LAYERS_NAMES(__VA_ARGS__)
1692 
1701 #define COMMS_PROTOCOL_LAYERS_ACCESS_OUTER(...) \
1702  COMMS_PROTOCOL_LAYERS_ACCESS(COMMS_EXPAND(COMMS_REVERSE_MACRO_ARGS(__VA_ARGS__)))
1703 
1710 #define COMMS_PROTOCOL_LAYERS_NAMES_OUTER(...) \
1711  COMMS_PROTOCOL_LAYERS_NAMES(COMMS_EXPAND(COMMS_REVERSE_MACRO_ARGS(__VA_ARGS__)))
1712 
1713 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.
This file contain definition of error statuses used by comms module.
Contains various tuple type manipulation classes and functions.
Base class for all the middle (non MsgDataLayer) protocol transport layers.
Definition: ProtocolLayerBase.h:61
ProtocolLayerBase(ProtocolLayerBase &&)=default
Move constructor.
static void resetMsg(TMsg &msg)
Reset msg in case it is a smart pointer (MsgPtr).
Definition: ProtocolLayerBase.h:839
void updateMissingSize(const Field &field, std::size_t size, TExtraValues... extraValues) const
Update the missing size information if such is requested.
Definition: ProtocolLayerBase.h:907
typename details::ProtocolLayerMsgPtr< NextLayer >::Type MsgPtr
Type of pointer to the message.
Definition: ProtocolLayerBase.h:96
comms::ErrorStatus doUpdate(const TMsg &msg, Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Default implementation of the "update" functaionality.
Definition: ProtocolLayerBase.h:728
ThisLayer & thisLayer()
Get access to this layer object.
Definition: ProtocolLayerBase.h:139
static comms::ErrorStatus doWriteField(const TMsg *msgPtr, const Field &field, TIter &iter, std::size_t len)
Write the layer field.
Definition: ProtocolLayerBase.h:819
comms::ErrorStatus update(TIter &iter, std::size_t size) const
Update recently written (using write()) message contents data.
Definition: ProtocolLayerBase.h:601
TField Field
Type of the field used for this layer.
Definition: ProtocolLayerBase.h:64
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: ProtocolLayerBase.h:782
comms::ErrorStatus update(const TMsg &msg, TIter &iter, std::size_t size) const
Update recently written (using write()) message contents data.
Definition: ProtocolLayerBase.h:617
MsgPtr createMsg(TId &&id, unsigned idx=0)
Create message object given the ID.
Definition: ProtocolLayerBase.h:772
ProtocolLayerBase(const ProtocolLayerBase &)=default
Copy constructor.
comms::ErrorStatus readUntilData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Perform read of data fields until data layer (message payload).
Definition: ProtocolLayerBase.h:257
ProtocolLayerBase(TArgs &&... args)
Constructor.
Definition: ProtocolLayerBase.h:115
comms::ErrorStatus readFromData(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Finalise the read operation by reading the message payload.
Definition: ProtocolLayerBase.h:300
comms::ErrorStatus readFromDataFieldsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Finalise the read operation by reading the message payload while caching the read transport informati...
Definition: ProtocolLayerBase.h:436
details::ProtocolLayerBaseOptionsParser< TOptions... > ParsedOptions
Parsed options structure.
Definition: ProtocolLayerBase.h:70
static constexpr bool canSplitRead()
Compile time check whether split read "until" and "from" data layer is allowed.
Definition: ProtocolLayerBase.h:152
void setMissingSize(std::size_t val, TExtraValues... extraValues) const
Set the missing size information if such is requested.
Definition: ProtocolLayerBase.h:923
constexpr std::size_t length() const
Get remaining length of wrapping transport information.
Definition: ProtocolLayerBase.h:541
comms::ErrorStatus read(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Deserialise message from the input data sequence.
Definition: ProtocolLayerBase.h:213
ErrorStatus updateFieldsCached(TAllFields &allFields, TIter &iter, std::size_t size) const
Update recently written (using writeFieldsCached()) message data as well as cached transport informat...
Definition: ProtocolLayerBase.h:641
comms::ErrorStatus write(const TMsg &msg, TIter &iter, std::size_t size) const
Serialise message into output data sequence.
Definition: ProtocolLayerBase.h:486
void setMsgIndex(std::size_t val, TExtraValues... extraValues) const
Set the message index information if such is requested.
Definition: ProtocolLayerBase.h:953
comms::ErrorStatus readUntilDataFieldsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Perform read of data fields until data layer (message payload) while caching the read transport infor...
Definition: ProtocolLayerBase.h:386
static comms::ErrorStatus doReadField(const TMsg *msgPtr, Field &field, TIter &iter, std::size_t len)
Read the layer field.
Definition: ProtocolLayerBase.h:804
ErrorStatus updateFieldsCached(TAllFields &allFields, const TMsg &msg, TIter &iter, std::size_t size) const
Update recently written (using writeFieldsCached()) message data as well as cached transport informat...
Definition: ProtocolLayerBase.h:676
void updateMissingSize(std::size_t size, TExtraValues... extraValues) const
Update the missing size information if such is requested.
Definition: ProtocolLayerBase.h:892
static constexpr std::size_t doFieldLength()
Default implementation of field length retrieval.
Definition: ProtocolLayerBase.h:744
TDerived ThisLayer
Actual derived class.
Definition: ProtocolLayerBase.h:99
comms::ErrorStatus doUpdate(Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Default implementation of the "update" functaionality.
Definition: ProtocolLayerBase.h:707
typename NextLayer::AllMessages AllMessages
All supported messages.
Definition: ProtocolLayerBase.h:87
static auto toMsgPtr(TMsg &msg) -> decltype(toMsgPtrInternal(msg, MsgTypeTag< typename std::decay< decltype(msg)>::type >()))
Get a pointer to the message object.
Definition: ProtocolLayerBase.h:878
TNextLayer NextLayer
Type of the next transport layer.
Definition: ProtocolLayerBase.h:67
typename std::decay< decltype(std::tuple_cat(std::declval< std::tuple< Field > >(), std::declval< typename TNextLayer::AllFields >())) >::type AllFields
Type of all the fields of all the transport layers wrapped in std::tuple.
Definition: ProtocolLayerBase.h:82
static Field & getField(TAllFields &allFields)
Retrieve reference to a layer specific field out of all fields.
Definition: ProtocolLayerBase.h:964
void setMsgId(TId val, TExtraValues... extraValues) const
Set the message ID information if such is requested.
Definition: ProtocolLayerBase.h:938
comms::ErrorStatus readFieldsCached(TAllFields &allFields, TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Deserialise message from the input data sequence while caching the read transport information fields.
Definition: ProtocolLayerBase.h:335
static constexpr std::size_t doFieldLength(const TMsg &)
Default implementation of field length retrieval when message is known.
Definition: ProtocolLayerBase.h:757
typename NextLayer::MsgFactory MsgFactory
Type of message factory.
Definition: ProtocolLayerBase.h:92
constexpr std::size_t length(const TMsg &msg) const
Get remaining length of wrapping transport information + length of the provided message.
Definition: ProtocolLayerBase.h:559
const ThisLayer & thisLayer() const
Get "const" access to this layer object.
Definition: ProtocolLayerBase.h:145
comms::ErrorStatus writeFieldsCached(TAllFields &allFields, const TMsg &msg, TIter &iter, std::size_t size) const
Serialise message into output data sequence while caching the written transport information fields.
Definition: ProtocolLayerBase.h:515
const NextLayer & nextLayer() const
Get "const" access to the next layer object.
Definition: ProtocolLayerBase.h:133
~ProtocolLayerBase() noexcept=default
Desctructor.
static constexpr bool isMessageObjRef()
Detect whether type is actual message object.
Definition: ProtocolLayerBase.h:830
comms::option::def::FieldType< TMsg > FieldType
Same as comms::option::def::FieldType.
Definition: options.h:1463
constexpr const ProtocolLayerBase< TField, TNextLayer, TDerived, TOptions... > & toProtocolLayerBase(const ProtocolLayerBase< TField, TNextLayer, TDerived, TOptions... > &layer)
Upcast protocol layer in order to have access to its internal types.
Definition: ProtocolLayerBase.h:1534
details::MsgIdRetriever< TId > msgId(TId &val)
Add "message ID" output parameter to protocol stack's (frame's) "read" operation.
Definition: ProtocolLayerBase.h:1588
details::MsgIndexRetriever msgIndex(std::size_t &val)
Add "message index" output parameter to protocol stack's (frame's) "read" operation.
Definition: ProtocolLayerBase.h:1626
details::MissingSizeRetriever missingSize(std::size_t &val)
Add "missing size" output parameter to protocol stack's (frame's) "read" operation.
Definition: ProtocolLayerBase.h:1561
details::MsgPayloadRetriever< TIter > msgPayload(TIter &iter, std::size_t &len)
Add "payload start" and "payload size" output parameters to protocol stack's (frame's) "read" operati...
Definition: ProtocolLayerBase.h:1654
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.
Contains definition of all the options used by the COMMS library.
Check whether provided type is a variant of std::tuple.
Definition: Tuple.h:35
Replacement to some types from standard type_traits.