COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
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
19#include "comms/ErrorStatus.h"
20#include "comms/util/Tuple.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
31COMMS_MSVC_WARNING_PUSH
32COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
33
34namespace comms
35{
36
37namespace protocol
38{
39
55template <
56 typename TField,
57 typename TNextLayer,
58 typename TDerived,
59 typename... TOptions>
61{
62public:
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
794protected:
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
844private:
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
872protected:
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>
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
1241private:
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
1514template <
1515 typename TField,
1516 typename TNextLayer,
1517 typename TDerived,
1518 typename... TOptions>
1519ProtocolLayerBase<TField, TNextLayer, TDerived, TOptions...>&
1521{
1522 return layer;
1523}
1524
1527template <
1528 typename TField,
1529 typename TNextLayer,
1530 typename TDerived,
1531 typename... TOptions>
1532constexpr
1533const ProtocolLayerBase<TField, TNextLayer, TDerived, TOptions...>&
1535{
1536 return layer;
1537}
1538
1560inline
1561details::MissingSizeRetriever<> missingSize(std::size_t& val)
1562{
1563 return details::MissingSizeRetriever<>(val);
1564}
1565
1587template <typename TId>
1588details::MsgIdRetriever<TId> msgId(TId& val)
1589{
1590 return details::MsgIdRetriever<TId>(val);
1591}
1592
1625inline
1626details::MsgIndexRetriever msgIndex(std::size_t& val)
1627{
1628 return details::MsgIndexRetriever(val);
1629}
1630
1653template <typename TIter>
1654details::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
1713COMMS_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
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
const NextLayer & nextLayer() const
Get "const" access to the next layer object.
Definition ProtocolLayerBase.h:133
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
ThisLayer & thisLayer()
Get access to this layer object.
Definition ProtocolLayerBase.h:139
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
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 Field & getField(TAllFields &allFields)
Retrieve reference to a layer specific field out of all fields.
Definition ProtocolLayerBase.h:964
static constexpr std::size_t doFieldLength(const TMsg &)
Default implementation of field length retrieval when message is known.
Definition ProtocolLayerBase.h:757
const ThisLayer & thisLayer() const
Get "const" access to this layer object.
Definition ProtocolLayerBase.h:145
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
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
~ProtocolLayerBase() noexcept=default
Desctructor.
static constexpr bool isMessageObjRef()
Detect whether type is actual message object.
Definition ProtocolLayerBase.h:830
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
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
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.
STL namespace.
Contains definition of all the options used by the COMMS library.
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:36
Replacement to some types from standard type_traits.