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