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 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
12
13#pragma once
14
15#include "comms/Assert.h"
17#include "comms/details/protocol_layers_access.h"
18#include "comms/details/detect.h"
19#include "comms/details/tag.h"
20#include "comms/ErrorStatus.h"
21#include "comms/frame/details/FrameLayerBaseOptionsParser.h"
22#include "comms/frame/details/FrameLayerDetails.h"
23#include "comms/Message.h"
24#include "comms/options.h"
25#include "comms/util/Tuple.h"
27
28#include <algorithm>
29#include <cstddef>
30#include <iterator>
31#include <tuple>
32#include <type_traits>
33#include <utility>
34
35COMMS_MSVC_WARNING_PUSH
36COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
37
38namespace comms
39{
40
41namespace frame
42{
43
59template <
60 typename TField,
61 typename TNextLayer,
62 typename TDerived,
63 typename... TOptions>
65{
66public:
68 using Field = TField;
69
71 using NextLayer = TNextLayer;
72
74 using ParsedOptions = details::FrameLayerBaseOptionsParser<TOptions...>;
75
80 using AllFields = typename std::decay<
81 decltype(
82 std::tuple_cat(
83 std::declval<std::tuple<Field> >(),
84 std::declval<typename TNextLayer::AllFields>())
85 )
86 >::type;
87
91 using AllMessages = typename NextLayer::AllMessages;
92
96 using MsgFactory = typename NextLayer::MsgFactory;
97
100 using MsgPtr = typename details::FrameLayerMsgPtr<NextLayer>::Type;
101
103 using ThisLayer = TDerived;
104
106 static const std::size_t NumOfLayers = 1 + NextLayer::NumOfLayers;
107
110
113
118 template <typename... TArgs>
119 explicit FrameLayerBase(TArgs&&... args) :
120 m_nextLayer(std::forward<TArgs>(args)...)
121 {
122 }
123
125 ~FrameLayerBase() noexcept = default;
126
128 FrameLayerBase& operator=(const FrameLayerBase&) = default;
129
131 NextLayer& nextLayer()
132 {
133 return m_nextLayer;
134 }
135
137 const NextLayer& nextLayer() const
138 {
139 return m_nextLayer;
140 }
141
144 {
145 return static_cast<ThisLayer&>(*this);
146 }
147
149 const ThisLayer& thisLayer() const
150 {
151 return static_cast<const ThisLayer&>(*this);
152 }
153
156 static constexpr bool canSplitRead()
157 {
158 return (!ParsedOptions::HasDisallowReadUntilDataSplit) && NextLayer::canSplitRead();
159 }
160
216 template <typename TMsg, typename TIter, typename... TExtraValues>
218 TMsg& msg,
219 TIter& iter,
220 std::size_t size,
221 TExtraValues... extraValues)
222 {
223 using Tag =
224 typename comms::util::LazyShallowConditional<
225 ParsedOptions::HasForceReadUntilDataSplit
226 >::template Type<
227 SplitReadTag,
228 NormalReadTag
229 >;
230
231 static_assert(std::is_same<Tag, NormalReadTag<> >::value || canSplitRead(),
232 "Read split is disallowed by at least one of the inner layers");
233 return readInternal(msg, iter, size, Tag(), extraValues...);
234 }
235
260 template <typename TMsg, typename TIter, typename... TExtraValues>
262 TMsg& msg,
263 TIter& iter,
264 std::size_t size,
265 TExtraValues... extraValues)
266 {
267
268 Field field;
269 auto& derivedObj = static_cast<TDerived&>(*this);
270 auto reader = createNextLayerUntilDataReader();
271 return
272 derivedObj.doRead(
273 field,
274 msg,
275 iter,
276 size,
277 reader,
278 extraValues...);
279 }
280
303 template <typename TMsg, typename TIter, typename... TExtraValues>
305 TMsg& msg,
306 TIter& iter,
307 std::size_t size,
308 TExtraValues... extraValues)
309 {
310 return nextLayer().readFromData(msg, iter, size, extraValues...);
311 }
312
338 template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
340 TAllFields& allFields,
341 TMsg& msg,
342 TIter& iter,
343 std::size_t size,
344 TExtraValues... extraValues)
345 {
346 using AllFieldsDecayed = typename std::decay<TAllFields>::type;
347 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
348 static const std::size_t Idx =
349 std::tuple_size<AllFieldsDecayed>::value -
350 std::tuple_size<AllFields>::value;
351 auto& field = getField<Idx>(allFields);
352 auto& derivedObj = static_cast<TDerived&>(*this);
353 auto reader = createNextLayerCachedFieldsReader(allFields);
354 return
355 derivedObj.doRead(
356 field,
357 msg,
358 iter,
359 size,
360 reader,
361 extraValues...);
362 }
363
389 template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
391 TAllFields& allFields,
392 TMsg& msg,
393 TIter& iter,
394 std::size_t size,
395 TExtraValues... extraValues)
396 {
397 using AllFieldsDecayed = typename std::decay<TAllFields>::type;
398 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
399 static const std::size_t Idx =
400 std::tuple_size<AllFieldsDecayed>::value -
401 std::tuple_size<AllFields>::value;
402
403 auto& field = getField<Idx>(allFields);
404 auto& derivedObj = static_cast<TDerived&>(*this);
405 auto reader = createNextLayerCachedFieldsUntilDataReader(allFields);
406 return
407 derivedObj.doRead(
408 field,
409 msg,
410 iter,
411 size,
412 reader,
413 extraValues...);
414 }
415
439 template <typename TAllFields, typename TMsg, typename TIter, typename... TExtraValues>
441 TAllFields& allFields,
442 TMsg& msg,
443 TIter& iter,
444 std::size_t size,
445 TExtraValues... extraValues)
446 {
447 return nextLayer().readFromDataFieldsCached(allFields, msg, iter, size, extraValues...);
448 }
449
489 template <typename TMsg, typename TIter>
491 const TMsg& msg,
492 TIter& iter,
493 std::size_t size) const
494 {
495 Field field;
496 auto& derivedObj = static_cast<const TDerived&>(*this);
497 auto writer = createNextLayerWriter();
498 return derivedObj.doWrite(field, msg, iter, size, writer);
499 }
500
518 template <typename TAllFields, typename TMsg, typename TIter>
520 TAllFields& allFields,
521 const TMsg& msg,
522 TIter& iter,
523 std::size_t size) const
524 {
525 using AllFieldsDecayed = typename std::decay<TAllFields>::type;
526 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
527 static const std::size_t Idx =
528 std::tuple_size<AllFieldsDecayed>::value -
529 std::tuple_size<AllFields>::value;
530
531 auto& field = getField<Idx>(allFields);
532 auto& derivedObj = static_cast<const TDerived&>(*this);
533 auto writer = createNextLayerCachedFieldsWriter(allFields);
534 return derivedObj.doWrite(field, msg, iter, size, writer);
535 }
536
545 constexpr std::size_t length() const
546 {
547 return thisLayer().doFieldLength() + m_nextLayer.length();
548 }
549
562 template <typename TMsg>
563 constexpr std::size_t length(const TMsg& msg) const
564 {
565 return thisLayer().doFieldLength(msg) + m_nextLayer.length(msg);
566 }
567
604 template <typename TIter>
605 comms::ErrorStatus update(TIter& iter, std::size_t size) const
606 {
607 Field field;
608 auto& derivedObj = static_cast<const TDerived&>(*this);
609 auto updater = createNextLayerUpdater();
610 return derivedObj.doUpdate(field, iter, size, updater);
611 }
612
620 template <typename TMsg, typename TIter>
621 comms::ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size) const
622 {
623 Field field;
624 auto& derivedObj = static_cast<const TDerived&>(*this);
625 auto updater = createNextLayerUpdater();
626 return derivedObj.doUpdate(msg, field, iter, size, updater);
627 }
628
644 template <typename TAllFields, typename TIter>
646 TAllFields& allFields,
647 TIter& iter,
648 std::size_t size) const
649 {
650 using AllFieldsDecayed = typename std::decay<TAllFields>::type;
651 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
652 static const std::size_t Idx =
653 std::tuple_size<AllFieldsDecayed>::value -
654 std::tuple_size<AllFields>::value;
655
656 auto& field = getField<Idx>(allFields);
657 auto& derivedObj = static_cast<const TDerived&>(*this);
658 auto updater = createNextLayerCachedFieldsUpdater(allFields);
659 return derivedObj.doUpdate(field, iter, size, updater);
660 }
661
679 template <typename TAllFields, typename TMsg, typename TIter>
681 TAllFields& allFields,
682 const TMsg& msg,
683 TIter& iter,
684 std::size_t size) const
685 {
686 using AllFieldsDecayed = typename std::decay<TAllFields>::type;
687 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
688 static const std::size_t Idx =
689 std::tuple_size<AllFieldsDecayed>::value -
690 std::tuple_size<AllFields>::value;
691
692 auto& field = getField<Idx>(allFields);
693 auto& derivedObj = static_cast<const TDerived&>(*this);
694 auto updater = createNextLayerCachedFieldsUpdater(allFields);
695 return derivedObj.doUpdate(msg, field, iter, size, updater);
696 }
697
710 template <typename TIter, typename TNextLayerUpdater>
712 Field& field,
713 TIter& iter,
714 std::size_t size,
715 TNextLayerUpdater&& nextLayerUpdater) const
716 {
717 return updateInternal(field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), LengthTag<>());
718 }
719
731 template <typename TMsg, typename TIter, typename TNextLayerUpdater>
733 const TMsg& msg,
734 Field& field,
735 TIter& iter,
736 std::size_t size,
737 TNextLayerUpdater&& nextLayerUpdater) const
738 {
739 return updateInternal(msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), LengthTag<>());
740 }
741
748 static constexpr std::size_t doFieldLength()
749 {
750 return Field::minLength();
751 }
752
760 template <typename TMsg>
761 static constexpr std::size_t doFieldLength(const TMsg&)
762 {
763 return doFieldLength();
764 }
765
775 template <typename TId>
776 MsgPtr createMsg(TId&& id, unsigned idx = 0)
777 {
778 return nextLayer().createMsg(std::forward<TId>(id), idx);
779 }
780
785 template <typename TAllFields>
786 static auto accessCachedField(TAllFields& allFields) ->
787 decltype(std::get<std::tuple_size<typename std::decay<TAllFields>::type>::value - std::tuple_size<AllFields>::value>(allFields))
788 {
789 using AllFieldsDecayed = typename std::decay<TAllFields>::type;
790 static_assert(util::tupleIsTailOf<AllFields, AllFieldsDecayed>(), "Passed tuple is wrong.");
791 static const std::size_t Idx =
792 std::tuple_size<AllFieldsDecayed>::value -
793 std::tuple_size<AllFields>::value;
794
795 return std::get<Idx>(allFields);
796 }
797
798protected:
807 template <typename TMsg, typename TIter>
808 static comms::ErrorStatus doReadField(const TMsg* msgPtr, Field& field, TIter& iter, std::size_t len)
809 {
810 static_cast<void>(msgPtr);
811 return field.read(iter, len);
812 }
813
822 template <typename TMsg, typename TIter>
823 static comms::ErrorStatus doWriteField(const TMsg* msgPtr, const Field& field, TIter& iter, std::size_t len)
824 {
825 static_cast<void>(msgPtr);
826 return field.write(iter, len);
827 }
828
833 template <typename T>
834 static constexpr bool isMessageObjRef()
835 {
836 return comms::details::hasImplOptions<T>();
837 }
838
842 template <typename TMsg>
843 static void resetMsg(TMsg& msg)
844 {
845 resetMsgInternal(msg, MsgTypeTag<typename std::decay<decltype(msg)>::type>());
846 }
847
848private:
849 template <typename... TParams>
850 using MessageObjTag = comms::details::tag::Tag5<>;
851
852 template <typename... TParams>
853 using SmartPtrTag = comms::details::tag::Tag6<>;
854
855 template <typename TMsg>
856 using MsgTypeTag =
857 typename comms::util::LazyShallowConditional<
858 comms::isMessage<TMsg>()
859 >::template Type<
860 MessageObjTag,
861 SmartPtrTag
862 >;
863
864 template <typename TMsg, typename... TParams>
865 static auto toMsgPtrInternal(TMsg& msg, MessageObjTag<TParams...>) -> decltype(&msg)
866 {
867 return &msg;
868 }
869
870 template <typename TMsg, typename... TParams>
871 static auto toMsgPtrInternal(TMsg& msg, SmartPtrTag<TParams...>) -> decltype(msg.get())
872 {
873 return msg.get();
874 }
875
876protected:
881 template <typename TMsg>
882 static auto toMsgPtr(TMsg& msg) -> decltype(toMsgPtrInternal(msg, MsgTypeTag<typename std::decay<decltype(msg)>::type>()))
883 {
884 return toMsgPtrInternal(msg, MsgTypeTag<typename std::decay<decltype(msg)>::type>());
885 }
886
895 template <typename... TExtraValues>
896 void updateMissingSize(std::size_t size, TExtraValues... extraValues) const
897 {
898 return updateMissingSizeInternal(size, extraValues...);
899 }
900
910 template <typename... TExtraValues>
912 const Field& field,
913 std::size_t size,
914 TExtraValues... extraValues) const
915 {
916 return updateMissingSizeInternal(field, size, extraValues...);
917 }
918
926 template <typename... TExtraValues>
928 std::size_t val,
929 TExtraValues... extraValues) const
930 {
931 return setMissingSizeInternal(val, extraValues...);
932 }
933
941 template <typename TId, typename... TExtraValues>
943 TId val,
944 TExtraValues... extraValues) const
945 {
946 return setMsgIdInternal(val, extraValues...);
947 }
948
956 template <typename... TExtraValues>
958 std::size_t val,
959 TExtraValues... extraValues) const
960 {
961 return setMsgIndexInternal(val, extraValues...);
962 }
963
967 template <std::size_t TIdx, typename TAllFields>
968 static Field& getField(TAllFields& allFields)
969 {
971 "Expected TAllFields to be a tuple");
972 static_assert(TIdx < std::tuple_size<TAllFields>::value,
973 "Invalid tuple access index");
974
975 auto& field = std::get<TIdx>(allFields);
976
977 using FieldType = typename std::decay<decltype(field)>::type;
978 static_assert(
979 std::is_same<Field, FieldType>::value,
980 "Field has wrong type");
981
982 return field;
983 }
984
986 template <typename... TParams>
987 using FixedLengthTag = comms::details::tag::Tag1<>;
988
989 template <typename... TParams>
990 using VarLengthTag = comms::details::tag::Tag2<>;
991
992 static constexpr std::size_t MinFieldLength = Field::minLength();
993 static constexpr std::size_t MaxFieldLength = Field::maxLength();
994
995 template <typename...>
996 using LengthTag =
997 typename comms::util::LazyShallowConditional<
998 (MinFieldLength == MaxFieldLength)
999 >::template Type<
1000 FixedLengthTag,
1001 VarLengthTag
1002 >;
1003
1004 class NextLayerReader
1005 {
1006 public:
1007 explicit NextLayerReader(NextLayer& nextLayer)
1008 : m_nextLayer(nextLayer)
1009 {
1010 }
1011
1012 template <typename TMsgPtr, typename TIter, typename... TExtraValues>
1013 ErrorStatus read(
1014 TMsgPtr& msg,
1015 TIter& iter,
1016 std::size_t size,
1017 TExtraValues... extraValues)
1018 {
1019 return m_nextLayer.read(msg, iter, size, extraValues...);
1020 }
1021 private:
1022 NextLayer& m_nextLayer;
1023 };
1024
1025 class NextLayerUntilDataReader
1026 {
1027 public:
1028 explicit NextLayerUntilDataReader(NextLayer& nextLayer)
1029 : m_nextLayer(nextLayer)
1030 {
1031 }
1032
1033 template <typename TMsgPtr, typename TIter, typename... TExtraValues>
1034 ErrorStatus read(
1035 TMsgPtr& msg,
1036 TIter& iter,
1037 std::size_t size,
1038 TExtraValues... extraValues)
1039 {
1040 return m_nextLayer.readUntilData(msg, iter, size, extraValues...);
1041 }
1042 private:
1043 NextLayer& m_nextLayer;
1044 };
1045
1046 template <typename TAllFields>
1047 class NextLayerCachedFieldsReader
1048 {
1049 public:
1050 NextLayerCachedFieldsReader(
1051 NextLayer& nextLayer,
1052 TAllFields& allFields)
1053 : m_nextLayer(nextLayer),
1054 m_allFields(allFields)
1055 {
1056 }
1057
1058 template<typename TMsgPtr, typename TIter, typename... TExtraValues>
1059 ErrorStatus read(
1060 TMsgPtr& msg,
1061 TIter& iter,
1062 std::size_t size,
1063 TExtraValues... extraValues)
1064 {
1065 return m_nextLayer.readFieldsCached(m_allFields, msg, iter, size, extraValues...);
1066 }
1067
1068 private:
1069 NextLayer& m_nextLayer;
1070 TAllFields& m_allFields;
1071 };
1072
1073 template <typename TAllFields>
1074 class NextLayerCachedFieldsUntilDataReader
1075 {
1076 public:
1077 NextLayerCachedFieldsUntilDataReader(
1078 NextLayer& nextLayer,
1079 TAllFields& allFields)
1080 : m_nextLayer(nextLayer),
1081 m_allFields(allFields)
1082 {
1083 }
1084
1085 template<typename TMsgPtr, typename TIter, typename... TExtraValues>
1086 ErrorStatus read(
1087 TMsgPtr& msg,
1088 TIter& iter,
1089 std::size_t size,
1090 TExtraValues... extraValues)
1091 {
1092 return m_nextLayer.readUntilDataFieldsCache(m_allFields, msg, iter, size, extraValues...);
1093 }
1094
1095 private:
1096 NextLayer& m_nextLayer;
1097 TAllFields& m_allFields;
1098 };
1099
1100 class NextLayerWriter
1101 {
1102 public:
1103
1104 explicit NextLayerWriter(const NextLayer& nextLayer)
1105 : m_nextLayer(nextLayer)
1106 {
1107 }
1108
1109 template <typename TMsg, typename TIter>
1110 ErrorStatus write(const TMsg& msg, TIter& iter, std::size_t size) const
1111 {
1112 return m_nextLayer.write(msg, iter, size);
1113 }
1114
1115 private:
1116 const NextLayer& m_nextLayer;
1117 };
1118
1119 template <typename TAllFields>
1120 class NextLayerCachedFieldsWriter
1121 {
1122 public:
1123 NextLayerCachedFieldsWriter(
1124 const NextLayer& nextLayer,
1125 TAllFields& allFields)
1126 : m_nextLayer(nextLayer),
1127 m_allFields(allFields)
1128 {
1129 }
1130
1131 template <typename TMsg, typename TIter>
1132 ErrorStatus write(const TMsg& msg, TIter& iter, std::size_t size) const
1133 {
1134 return m_nextLayer.writeFieldsCached(m_allFields, msg, iter, size);
1135 }
1136
1137 private:
1138 const NextLayer& m_nextLayer;
1139 TAllFields& m_allFields;
1140 };
1141
1142 class NextLayerUpdater
1143 {
1144 public:
1145
1146 explicit NextLayerUpdater(const NextLayer& nextLayer)
1147 : m_nextLayer(nextLayer)
1148 {
1149 }
1150
1151 template <typename TIter>
1152 ErrorStatus update(TIter& iter, std::size_t size) const
1153 {
1154 return m_nextLayer.update(iter, size);
1155 }
1156
1157 template <typename TMsg, typename TIter>
1158 ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size) const
1159 {
1160 return m_nextLayer.update(msg, iter, size);
1161 }
1162
1163 private:
1164 const NextLayer& m_nextLayer;
1165 };
1166
1167 template <typename TAllFields>
1168 class NextLayerCachedFieldsUpdater
1169 {
1170 public:
1171 NextLayerCachedFieldsUpdater(
1172 const NextLayer& nextLayer,
1173 TAllFields& allFields)
1174 : m_nextLayer(nextLayer),
1175 m_allFields(allFields)
1176 {
1177 }
1178
1179 template <typename TIter>
1180 ErrorStatus update(TIter& iter, std::size_t size) const
1181 {
1182 return m_nextLayer.updateFieldsCached(m_allFields, iter, size);
1183 }
1184
1185 template <typename TMsg, typename TIter>
1186 ErrorStatus update(const TMsg& msg, TIter& iter, std::size_t size) const
1187 {
1188 return m_nextLayer.updateFieldsCached(m_allFields, msg, iter, size);
1189 }
1190
1191 private:
1192 const NextLayer& m_nextLayer;
1193 TAllFields& m_allFields;
1194 };
1195
1196 NextLayerReader createNextLayerReader()
1197 {
1198 return NextLayerReader(m_nextLayer);
1199 }
1200
1201 NextLayerUntilDataReader createNextLayerUntilDataReader()
1202 {
1203 return NextLayerUntilDataReader(m_nextLayer);
1204 }
1205
1206 template <typename TAllFields>
1207 NextLayerCachedFieldsReader<TAllFields>
1208 createNextLayerCachedFieldsReader(TAllFields& fields)
1209 {
1210 return NextLayerCachedFieldsReader<TAllFields>(m_nextLayer, fields);
1211 }
1212
1213 template <typename TAllFields>
1214 NextLayerCachedFieldsUntilDataReader<TAllFields>
1215 createNextLayerCachedFieldsUntilDataReader(TAllFields& fields)
1216 {
1217 return NextLayerCachedFieldsUntilDataReader<TAllFields>(m_nextLayer, fields);
1218 }
1219
1220 NextLayerWriter createNextLayerWriter() const
1221 {
1222 return NextLayerWriter(m_nextLayer);
1223 }
1224
1225 template <typename TAllFields>
1226 NextLayerCachedFieldsWriter<TAllFields>
1227 createNextLayerCachedFieldsWriter(TAllFields& fields) const
1228 {
1229 return NextLayerCachedFieldsWriter<TAllFields>(m_nextLayer, fields);
1230 }
1231
1232 NextLayerUpdater createNextLayerUpdater() const
1233 {
1234 return NextLayerUpdater(m_nextLayer);
1235 }
1236
1237 template <typename TAllFields>
1238 NextLayerCachedFieldsUpdater<TAllFields>
1239 createNextLayerCachedFieldsUpdater(TAllFields& fields) const
1240 {
1241 return NextLayerCachedFieldsUpdater<TAllFields>(m_nextLayer, fields);
1242 }
1243
1245private:
1246
1247 template <typename... TParams>
1248 using NormalReadTag = comms::details::tag::Tag3<>;
1249
1250 template <typename... TParams>
1251 using SplitReadTag = comms::details::tag::Tag4<>;
1252
1253 template <typename TMsg, typename TIter, typename... TExtraValues>
1254 comms::ErrorStatus readInternal(
1255 TMsg& msg,
1256 TIter& iter,
1257 std::size_t size,
1258 NormalReadTag<>,
1259 TExtraValues... extraValues)
1260 {
1261 Field field;
1262 auto& derivedObj = static_cast<TDerived&>(*this);
1263 auto reader = createNextLayerReader();
1264 return derivedObj.doRead(field, msg, iter, size, reader, extraValues...);
1265 }
1266
1267 template <typename TMsgPtr, typename TIter, typename... TExtraValues>
1268 comms::ErrorStatus readInternal(
1269 TMsgPtr& msgPtr,
1270 TIter& iter,
1271 std::size_t size,
1272 SplitReadTag<>,
1273 TExtraValues... extraValues)
1274 {
1275 auto fromIter = iter;
1276 auto es = readUntilData(msgPtr, iter, size, extraValues...);
1277 if (es != comms::ErrorStatus::Success) {
1278 return es;
1279 }
1280
1281 auto consumed = static_cast<std::size_t>(std::distance(fromIter, iter));
1282 COMMS_ASSERT(consumed <= size);
1283 return readFromData(msgPtr, iter, size - consumed, extraValues...);
1284 }
1285
1286 template <typename TIter, typename TNextLayerUpdater, typename... TParams>
1287 comms::ErrorStatus updateInternal(
1288 Field& field,
1289 TIter& iter,
1290 std::size_t size,
1291 TNextLayerUpdater&& nextLayerUpdater,
1292 FixedLengthTag<TParams...>) const
1293 {
1294 auto len = field.length();
1295 COMMS_ASSERT(len <= size);
1296 std::advance(iter, len);
1297 return nextLayerUpdater.update(iter, size - len);
1298 }
1299
1300 template <typename TIter, typename TNextLayerUpdater, typename... TParams>
1301 comms::ErrorStatus updateInternal(
1302 Field& field,
1303 TIter& iter,
1304 std::size_t size,
1305 TNextLayerUpdater&& nextLayerUpdater,
1306 VarLengthTag<TParams...>) const
1307 {
1308 auto iterTmp = iter;
1309 auto es = field.read(iter, size);
1310 if (es == comms::ErrorStatus::Success) {
1311 auto diff = static_cast<std::size_t>(std::distance(iterTmp, iter));
1312 es = nextLayerUpdater.update(iter, size - diff);
1313 }
1314 return es;
1315 }
1316
1317 template <typename TMsg, typename TIter, typename TNextLayerUpdater, typename... TParams>
1318 comms::ErrorStatus updateInternal(
1319 const TMsg& msg,
1320 Field& field,
1321 TIter& iter,
1322 std::size_t size,
1323 TNextLayerUpdater&& nextLayerUpdater,
1324 FixedLengthTag<TParams...>) const
1325 {
1326 auto len = field.length();
1327 COMMS_ASSERT(len <= size);
1328 std::advance(iter, len);
1329 return nextLayerUpdater.update(msg, iter, size - len);
1330 }
1331
1332 template <typename TMsg, typename TIter, typename TNextLayerUpdater, typename... TParams>
1333 comms::ErrorStatus updateInternal(
1334 const TMsg& msg,
1335 Field& field,
1336 TIter& iter,
1337 std::size_t size,
1338 TNextLayerUpdater&& nextLayerUpdater,
1339 VarLengthTag<TParams...>) const
1340 {
1341 auto iterTmp = iter;
1342 auto es = field.read(iter, size);
1343 if (es == comms::ErrorStatus::Success) {
1344 auto diff = static_cast<std::size_t>(std::distance(iterTmp, iter));
1345 es = nextLayerUpdater.update(msg, iter, size - diff);
1346 }
1347 return es;
1348 }
1349
1350 template <typename TMsg, typename... TParams>
1351 static void resetMsgInternal(TMsg&, MessageObjTag<TParams...>)
1352 {
1353 // Do nothing
1354 }
1355
1356 template <typename TMsg, typename... TParams>
1357 static void resetMsgInternal(TMsg& msg, SmartPtrTag<TParams...>)
1358 {
1359 msg.reset();
1360 }
1361
1362 static void updateMissingSizeInternal(std::size_t size)
1363 {
1364 static_cast<void>(size);
1365 }
1366
1367 static void updateMissingSizeInternal(const Field& field, std::size_t size)
1368 {
1369 static_cast<void>(field);
1370 static_cast<void>(size);
1371 }
1372
1373 template <typename... TExtraValues>
1374 void updateMissingSizeInternal(
1375 std::size_t size,
1376 details::MissingSizeRetriever<> retriever,
1377 TExtraValues... extraValues) const
1378 {
1379 COMMS_ASSERT(size <= length());
1380 retriever.setValue(std::max(std::size_t(1U), length() - size));
1381 updateMissingSizeInternal(size, extraValues...);
1382 }
1383
1384 template <typename... TExtraValues>
1385 void updateMissingSizeInternal(
1386 const Field& field,
1387 std::size_t size,
1388 details::MissingSizeRetriever<> retriever,
1389 TExtraValues... extraValues) const
1390 {
1391 static_assert(
1392 details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1393 "Must be missing size retriever");
1394 auto totalLen = field.length() + m_nextLayer.length();
1395 COMMS_ASSERT(size <= totalLen);
1396 retriever.setValue(std::max(std::size_t(1U), totalLen - size));
1397 updateMissingSizeInternal(size, extraValues...);
1398 }
1399
1400 template <typename T, typename... TExtraValues>
1401 void updateMissingSizeInternal(
1402 std::size_t size,
1403 T retriever,
1404 TExtraValues... extraValues) const
1405 {
1406 static_cast<void>(retriever);
1407 static_assert(
1408 !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1409 "Mustn't be missing size retriever");
1410 updateMissingSizeInternal(size, extraValues...);
1411 }
1412
1413 template <typename T, typename... TExtraValues>
1414 void updateMissingSizeInternal(
1415 const Field& field,
1416 std::size_t size,
1417 T retriever,
1418 TExtraValues... extraValues) const
1419 {
1420 static_cast<void>(retriever);
1421 static_assert(
1422 !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1423 "Mustn't be missing size retriever");
1424 updateMissingSizeInternal(field, size, extraValues...);
1425 }
1426
1427 static void setMissingSizeInternal(std::size_t val)
1428 {
1429 static_cast<void>(val);
1430 }
1431
1432 template <typename... TExtraValues>
1433 static void setMissingSizeInternal(
1434 std::size_t val,
1435 details::MissingSizeRetriever<> retriever,
1436 TExtraValues... extraValues)
1437 {
1438 retriever.setValue(val);
1439 setMissingSizeInternal(val, extraValues...);
1440 }
1441
1442 template <typename T, typename... TExtraValues>
1443 static void setMissingSizeInternal(
1444 std::size_t val,
1445 T retriever,
1446 TExtraValues... extraValues)
1447 {
1448 static_cast<void>(retriever);
1449 static_assert(
1450 !details::isMissingSizeRetriever<typename std::decay<decltype(retriever)>::type>(),
1451 "Mustn't be missing size retriever");
1452 setMissingSizeInternal(val, extraValues...);
1453 }
1454
1455 template <typename TId>
1456 static void setMsgIdInternal(TId val)
1457 {
1458 static_cast<void>(val);
1459 }
1460
1461 template <typename TId, typename U, typename... TExtraValues>
1462 static void setMsgIdInternal(
1463 TId val,
1464 details::MsgIdRetriever<U> retriever,
1465 TExtraValues... extraValues)
1466 {
1467 retriever.setValue(val);
1468 setMsgIdInternal(val, extraValues...);
1469 }
1470
1471 template <typename TId, typename T, typename... TExtraValues>
1472 static void setMsgIdInternal(
1473 TId val,
1474 T retriever,
1475 TExtraValues... extraValues)
1476 {
1477 static_cast<void>(retriever);
1478 static_assert(
1479 !details::isMsgIdRetriever<typename std::decay<decltype(retriever)>::type>(),
1480 "Mustn't be message id retriever");
1481 setMsgIdInternal(val, extraValues...);
1482 }
1483
1484 static void setMsgIndexInternal(std::size_t val)
1485 {
1486 static_cast<void>(val);
1487 }
1488
1489 template <typename... TExtraValues>
1490 static void setMsgIndexInternal(
1491 std::size_t val,
1492 details::MsgIndexRetriever retriever,
1493 TExtraValues... extraValues)
1494 {
1495 retriever.setValue(val);
1496 setMsgIndexInternal(val, extraValues...);
1497 }
1498
1499 template <typename T, typename... TExtraValues>
1500 static void setMsgIndexInternal(
1501 std::size_t val,
1502 T retriever,
1503 TExtraValues... extraValues)
1504 {
1505 static_cast<void>(retriever);
1506 static_assert(
1507 !details::isMsgIndexRetriever<typename std::decay<decltype(retriever)>::type>(),
1508 "Mustn't be missing size retriever");
1509 setMsgIndexInternal(val, extraValues...);
1510 }
1511
1512 static_assert (comms::util::IsTuple<AllFields>::Value, "Must be tuple");
1513 NextLayer m_nextLayer;
1514};
1515
1518template <
1519 typename TField,
1520 typename TNextLayer,
1521 typename TDerived,
1522 typename... TOptions>
1523FrameLayerBase<TField, TNextLayer, TDerived, TOptions...>&
1528
1531template <
1532 typename TField,
1533 typename TNextLayer,
1534 typename TDerived,
1535 typename... TOptions>
1536constexpr
1537const FrameLayerBase<TField, TNextLayer, TDerived, TOptions...>&
1542
1563inline
1564details::MissingSizeRetriever<> missingSize(std::size_t& val)
1565{
1566 return details::MissingSizeRetriever<>(val);
1567}
1568
1589template <typename TId>
1590details::MsgIdRetriever<TId> msgId(TId& val)
1591{
1592 return details::MsgIdRetriever<TId>(val);
1593}
1594
1626inline
1627details::MsgIndexRetriever msgIndex(std::size_t& val)
1628{
1629 return details::MsgIndexRetriever(val);
1630}
1631
1654template <typename TIter>
1655details::MsgPayloadRetriever<TIter> msgPayload(TIter& iter, std::size_t& len)
1656{
1657 return details::MsgPayloadRetriever<TIter>(iter, len);
1658}
1659
1660} // namespace frame
1661
1662} // namespace comms
1663
1670#define COMMS_FRAME_LAYERS_ACCESS(...) \
1671 COMMS_DO_ACCESS_LAYER_ACC_FUNC(__VA_ARGS__)
1672
1679#define COMMS_FRAME_LAYERS_NAMES(...) \
1680 COMMS_DO_LAYER_TYPE_ALIAS(Base, __VA_ARGS__) \
1681 COMMS_DO_ACCESS_LAYER_ACC_FUNC(__VA_ARGS__)
1682
1685#define COMMS_FRAME_LAYERS_ACCESS_INNER(...) \
1686 COMMS_FRAME_LAYERS_ACCESS(__VA_ARGS__)
1687
1690#define COMMS_FRAME_LAYERS_NAMES_INNER(...) \
1691 COMMS_FRAME_LAYERS_NAMES(__VA_ARGS__)
1692
1701#define COMMS_FRAME_LAYERS_ACCESS_OUTER(...) \
1702 COMMS_FRAME_LAYERS_ACCESS(COMMS_EXPAND(COMMS_REVERSE_MACRO_ARGS(__VA_ARGS__)))
1703
1710#define COMMS_FRAME_LAYERS_NAMES_OUTER(...) \
1711 COMMS_FRAME_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 definition of Message object interface and various base classes for custom messages.
Contains various tuple type manipulation classes and functions.
Base class for all the middle (non MsgDataLayer) protocol transport layers.
Definition FrameLayerBase.h:65
const NextLayer & nextLayer() const
Get "const" access to the next layer object.
Definition FrameLayerBase.h:137
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:490
MsgPtr createMsg(TId &&id, unsigned idx=0)
Create message object given the ID.
Definition FrameLayerBase.h:776
comms::ErrorStatus update(TIter &iter, std::size_t size) const
Update recently written (using write()) message contents data.
Definition FrameLayerBase.h:605
static constexpr std::size_t doFieldLength()
Default implementation of field length retrieval.
Definition FrameLayerBase.h:748
~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:304
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:519
typename NextLayer::MsgFactory MsgFactory
Type of message factory.
Definition FrameLayerBase.h:96
ThisLayer & thisLayer()
Get access to this layer object.
Definition FrameLayerBase.h:143
constexpr std::size_t length(const TMsg &msg) const
Get remaining length of wrapping transport information + length of the provided message.
Definition FrameLayerBase.h:563
static constexpr bool canSplitRead()
Compile time check whether split read "until" and "from" data layer is allowed.
Definition FrameLayerBase.h:156
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:645
details::FrameLayerBaseOptionsParser< TOptions... > ParsedOptions
Parsed options structure.
Definition FrameLayerBase.h:74
static Field & getField(TAllFields &allFields)
Retrieve reference to a layer specific field out of all fields.
Definition FrameLayerBase.h:968
void setMsgIndex(std::size_t val, TExtraValues... extraValues) const
Set the message index information if such is requested.
Definition FrameLayerBase.h:957
void setMissingSize(std::size_t val, TExtraValues... extraValues) const
Set the missing size information if such is requested.
Definition FrameLayerBase.h:927
void updateMissingSize(const Field &field, std::size_t size, TExtraValues... extraValues) const
Update the missing size information if such is requested.
Definition FrameLayerBase.h:911
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:680
static constexpr std::size_t doFieldLength(const TMsg &)
Default implementation of field length retrieval when message is known.
Definition FrameLayerBase.h:761
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:261
typename details::FrameLayerMsgPtr< NextLayer >::Type MsgPtr
Type of pointer to the message.
Definition FrameLayerBase.h:100
static comms::ErrorStatus doWriteField(const TMsg *msgPtr, const Field &field, TIter &iter, std::size_t len)
Write the layer field.
Definition FrameLayerBase.h:823
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:390
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:786
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:732
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:86
void updateMissingSize(std::size_t size, TExtraValues... extraValues) const
Update the missing size information if such is requested.
Definition FrameLayerBase.h:896
TField Field
Type of the field used for this layer.
Definition FrameLayerBase.h:68
comms::ErrorStatus doUpdate(Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Default implementation of the "update" functaionality.
Definition FrameLayerBase.h:711
constexpr std::size_t length() const
Get remaining length of wrapping transport information.
Definition FrameLayerBase.h:545
TDerived ThisLayer
Actual derived class.
Definition FrameLayerBase.h:103
static comms::ErrorStatus doReadField(const TMsg *msgPtr, Field &field, TIter &iter, std::size_t len)
Read the layer field.
Definition FrameLayerBase.h:808
comms::ErrorStatus read(TMsg &msg, TIter &iter, std::size_t size, TExtraValues... extraValues)
Deserialise message from the input data sequence.
Definition FrameLayerBase.h:217
typename NextLayer::AllMessages AllMessages
All supported messages.
Definition FrameLayerBase.h:91
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:882
FrameLayerBase(TArgs &&... args)
Constructor.
Definition FrameLayerBase.h:119
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:440
static void resetMsg(TMsg &msg)
Reset msg in case it is a smart pointer (MsgPtr).
Definition FrameLayerBase.h:843
TNextLayer NextLayer
Type of the next transport layer.
Definition FrameLayerBase.h:71
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:339
void setMsgId(TId val, TExtraValues... extraValues) const
Set the message ID information if such is requested.
Definition FrameLayerBase.h:942
const ThisLayer & thisLayer() const
Get "const" access to this layer object.
Definition FrameLayerBase.h:149
comms::ErrorStatus update(const TMsg &msg, TIter &iter, std::size_t size) const
Update recently written (using write()) message contents data.
Definition FrameLayerBase.h:621
static constexpr bool isMessageObjRef()
Detect whether type is actual message object.
Definition FrameLayerBase.h:834
details::MissingSizeRetriever missingSize(std::size_t &val)
Add "missing size" output parameter to frame's "read" operation.
Definition FrameLayerBase.h:1564
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:1655
details::MsgIndexRetriever msgIndex(std::size_t &val)
Add "message index" output parameter to frame's "read" operation.
Definition FrameLayerBase.h:1627
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:1524
details::MsgIdRetriever< TId > msgId(TId &val)
Add "message ID" output parameter to frame's "read" operation.
Definition FrameLayerBase.h:1590
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
@ 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:39
Replacement to some types from standard type_traits.