14 #include <type_traits>
19 #include "comms/details/tag.h"
20 #include "comms/protocol/details/ProtocolLayerBase.h"
21 #include "comms/protocol/details/MsgSizeLayerOptionsParser.h"
22 #include "comms/protocol/details/ProtocolLayerExtendingClassHelper.h"
25 COMMS_MSVC_WARNING_PUSH
26 COMMS_MSVC_WARNING_DISABLE(4189)
36 template <
bool TVal
idPtr>
37 struct MsgSizeLayerConstNullPtrCastHelper
39 template <
typename TPtr>
40 using Type =
const typename TPtr::element_type*;
44 struct MsgSizeLayerConstNullPtrCastHelper<false>
46 template <
typename TPtr>
47 using Type =
const void*;
64 template <
typename TField,
typename TNextLayer,
typename... TOptions>
69 details::ProtocolLayerExtendingClassT<
70 MsgSizeLayer<TField, TNextLayer, TOptions...>,
71 details::MsgSizeLayerOptionsParser<TOptions...>
73 comms::option::ProtocolLayerDisallowReadUntilDataSplit
80 details::ProtocolLayerExtendingClassT<
82 details::MsgSizeLayerOptionsParser<TOptions...>
87 using ParsedOptionsInternal = details::MsgSizeLayerOptionsParser<TOptions...>;
119 static constexpr
bool hasExtendingClass()
121 return ParsedOptionsInternal::HasExtendingClass;
126 static constexpr std::size_t doFieldLength()
128 return BaseImpl::doFieldLength();
131 template <
typename TMsg>
132 constexpr std::size_t doFieldLength(
const TMsg& msg)
const
134 return fieldLengthInternal(msg, LengthTag<>());
170 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
176 TNextLayerReader&& nextLayerReader,
177 TExtraValues... extraValues)
179 using IterType =
typename std::decay<decltype(iter)>::type;
180 using IterTag =
typename std::iterator_traits<IterType>::iterator_category;
182 std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
183 "Current implementation of MsgSizeLayer requires iterator used for reading to be random-access one.");
186 auto* msgPtr = BaseImpl::toMsgPtr(msg);
187 auto& thisObj = BaseImpl::thisLayer();
188 auto es = thisObj.doReadField(msgPtr, field, iter, size);
189 if (es == ErrorStatus::NotEnoughData) {
190 BaseImpl::updateMissingSize(field, size, extraValues...);
193 if (es != ErrorStatus::Success) {
197 auto fromIter = iter;
198 auto readFieldLength =
static_cast<std::size_t
>(std::distance(begIter, iter));
199 std::size_t actualRemainingSize = (size - readFieldLength);
200 std::size_t requiredRemainingSize = thisObj.getRemainingSizeFromField(field);
202 if (actualRemainingSize < requiredRemainingSize) {
203 BaseImpl::setMissingSize(requiredRemainingSize - actualRemainingSize, extraValues...);
204 return ErrorStatus::NotEnoughData;
207 thisObj.beforeRead(field, msgPtr);
208 es = nextLayerReader.read(msg, iter, requiredRemainingSize, extraValues...);
209 if (es == ErrorStatus::NotEnoughData) {
210 BaseImpl::resetMsg(msg);
211 return ErrorStatus::ProtocolError;
214 if (es != ErrorStatus::ProtocolError) {
216 std::advance(iter, requiredRemainingSize);
220 static_cast<std::size_t
>(std::distance(fromIter, iter));
221 if (consumed < requiredRemainingSize) {
222 auto diff = requiredRemainingSize - consumed;
223 std::advance(iter, diff);
248 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
254 TNextLayerWriter&& nextLayerWriter)
const
256 using MsgType =
typename std::decay<decltype(msg)>::type;
257 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), MsgLengthTag<MsgType>());
269 template <
typename TIter,
typename TNextLayerUpdater>
274 TNextLayerUpdater&& nextLayerUpdater)
const
277 using ConstNullptrType =
278 typename details::MsgSizeLayerConstNullPtrCastHelper<
279 !std::is_void<LocalMsgPtr>::value
280 >::template Type<LocalMsgPtr>;
281 auto noMsgPtr =
static_cast<ConstNullptrType
>(
nullptr);
282 return doUpdateInternal(noMsgPtr, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), NoMsgTypeTag<>());
294 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
300 TNextLayerUpdater&& nextLayerUpdater)
const
302 return doUpdateInternal(&msg, field, iter, size, std::forward<TNextLayerUpdater>(nextLayerUpdater), ValidMsgTypeTag<>());
311 return static_cast<std::size_t
>(field.getValue());
322 template <
typename TMsg>
325 static_cast<void>(field);
326 static_cast<void>(msg);
337 template <
typename TMsg>
340 static_cast<void>(msg);
341 field.setValue(size);
345 template <
typename... TParams>
346 using FixedLengthTag =
typename BaseImpl::template FixedLengthTag<TParams...>;
348 template <
typename...TParams>
349 using VarLengthTag =
typename BaseImpl::template VarLengthTag<TParams...>;
351 template <
typename... TParams>
352 using LengthTag =
typename BaseImpl::template LengthTag<TParams...>;
354 template <
typename... TParams>
355 using MsgHasLengthTag = comms::details::tag::Tag3<>;
357 template <
typename... TParams>
358 using MsgNoLengthTag = comms::details::tag::Tag4<>;
360 template <
typename... TParams>
361 using ValidMsgTypeTag = comms::details::tag::Tag5<>;
363 template <
typename... TParams>
364 using NoMsgTypeTag = comms::details::tag::Tag6<>;
366 template<
typename TMsg>
368 typename comms::util::LazyShallowConditional<
369 details::ProtocolLayerHasFieldsImpl<TMsg>::Value || TMsg::hasLength()
375 template <
typename TMsg,
typename TIter,
typename TWriter>
381 TWriter&& nextLayerWriter)
const
383 std::size_t lenValue = BaseImpl::nextLayer().length(msg);
384 auto& thisObj = BaseImpl::thisLayer();
386 thisObj.prepareFieldForWrite(lenValue, &msg, field);
387 auto es = thisObj.doWriteField(&msg, field, iter, size);
388 if (es != ErrorStatus::Success) {
393 return nextLayerWriter.write(msg, iter, size - field.length());
396 template <
typename TMsg,
typename TIter,
typename TWriter>
402 TWriter&& nextLayerWriter)
const
404 auto valueIter = iter;
405 auto& thisObj = BaseImpl::thisLayer();
406 thisObj.prepareFieldForWrite(0U, &msg, field);
407 auto es = thisObj.doWriteField(&msg, field, iter, size);
408 if (es != ErrorStatus::Success) {
412 auto dataIter = iter;
414 auto sizeLen = field.length();
415 es = nextLayerWriter.write(msg, iter, size - sizeLen);
416 if (es != ErrorStatus::Success) {
420 auto dist =
static_cast<std::size_t
>(std::distance(dataIter, iter));
421 thisObj.prepareFieldForWrite(dist, &msg, field);
423 return thisObj.doWriteField(&msg, field, valueIter, sizeLen);
426 template <
typename TMsg,
typename TIter,
typename TWriter>
432 TWriter&& nextLayerWriter)
const
434 auto& thisObj = BaseImpl::thisLayer();
435 thisObj.prepareFieldForWrite(0U, &msg, field);
436 auto es = thisObj.doWriteField(&msg, field, iter, size);
437 if (es != ErrorStatus::Success) {
441 es = nextLayerWriter.write(msg, iter, size - field.length());
442 if ((es != ErrorStatus::Success) &&
443 (es != ErrorStatus::UpdateRequired)) {
447 return ErrorStatus::UpdateRequired;
450 template <
typename TMsg,
typename TIter,
typename TWriter>
456 TWriter&& nextLayerWriter,
457 std::random_access_iterator_tag)
const
459 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
462 template <
typename TMsg,
typename TIter,
typename TWriter>
468 TWriter&& nextLayerWriter,
469 std::output_iterator_tag)
const
471 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
474 template <
typename TMsg,
typename TIter,
typename TWriter>
480 TWriter&& nextLayerWriter)
const
483 (BaseImpl::MinFieldLength == BaseImpl::MaxFieldLength) ||
485 "Unable to perform write with size field having variable length and "
486 "no polymorphic length calculation available.");
487 using IterType =
typename std::decay<decltype(iter)>::type;
488 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
489 return writeInternalNoLengthTagged(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter), Tag());
492 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
498 TWriter&& nextLayerWriter,
499 MsgHasLengthTag<TParams...>)
const
501 return writeInternalHasLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
504 template <
typename TMsg,
typename TIter,
typename TWriter,
typename... TParams>
510 TWriter&& nextLayerWriter,
511 MsgNoLengthTag<TParams...>)
const
513 return writeInternalNoLength(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
516 template <
typename TMsg,
typename... TParams>
517 constexpr std::size_t fieldLengthInternal(
const TMsg& msg, FixedLengthTag<TParams...>)
const
519 return BaseImpl::doFieldLength(msg);
522 template <
typename TMsg,
typename... TParams>
523 std::size_t fieldLengthInternal(
const TMsg& msg, VarLengthTag<TParams...>)
const
525 auto& thisObj = BaseImpl::thisLayer();
526 auto remSize = BaseImpl::nextLayer().length(msg);
528 thisObj.prepareFieldForWrite(remSize, &msg, fieldTmp);
529 return fieldTmp.length();
532 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename TForwardTag>
538 TNextLayerUpdater&& nextLayerUpdater,
539 TForwardTag&& tag)
const
541 std::size_t lenValue = size - Field::maxLength();
542 auto& thisObj = BaseImpl::thisLayer();
543 thisObj.prepareFieldForWrite(lenValue, msg, field);
545 if (field.length() != Field::maxLength()) {
546 lenValue = size - field.length();
547 thisObj.prepareFieldForWrite(lenValue, msg, field);
550 auto es = thisObj.doWriteField(msg, field, iter, size);
551 if (es != ErrorStatus::Success) {
555 return doUpdateForward(msg, iter, size - field.length(), std::forward<TNextLayerUpdater>(nextLayerUpdater), tag);
558 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
563 TNextLayerUpdater&& nextLayerUpdater,
564 NoMsgTypeTag<TParams...>)
const
566 static_cast<void>(msg);
567 return nextLayerUpdater.update(iter, size);
570 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater,
typename... TParams>
575 TNextLayerUpdater&& nextLayerUpdater,
576 ValidMsgTypeTag<TParams...>)
const
579 return nextLayerUpdater.update(*msg, iter, size);
585 template <
typename T>
586 struct MsgSizeLayerCheckHelper
588 static const bool Value =
false;
591 template <
typename TField,
typename TNextLayer>
592 struct MsgSizeLayerCheckHelper<MsgSizeLayer<TField, TNextLayer> >
594 static const bool Value =
true;
602 template <
typename T>
605 return details::MsgSizeLayerCheckHelper<T>::Value;
612 COMMS_MSVC_WARNING_POP
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition: Assert.h:170
Contains various compiler related definitions.
Contains definition of comms::field::IntValue.
Provides common base class for the custom messages with default implementation.
Base class to all the field classes.
Definition: Field.h:33
Protocol layer that uses size field as a prefix to all the subsequent data written by other (next) la...
Definition: MsgSizeLayer.h:75
static void prepareFieldForWrite(std::size_t size, const TMsg *msg, Field &field)
Prepare field for writing.
Definition: MsgSizeLayer.h:338
static std::size_t getRemainingSizeFromField(const Field &field)
Retrieve remaining size (length) from the field.
Definition: MsgSizeLayer.h:309
comms::ErrorStatus doRead(Field &field, TMsg &msg, TIter &iter, std::size_t size, TNextLayerReader &&nextLayerReader, TExtraValues... extraValues)
Customized read functionality, invoked by read().
Definition: MsgSizeLayer.h:171
~MsgSizeLayer() noexcept=default
Destructor.
comms::ErrorStatus doUpdate(const TMsg &msg, Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Customized update functionality, invoked by update().
Definition: MsgSizeLayer.h:295
ErrorStatus doWrite(Field &field, const TMsg &msg, TIter &iter, std::size_t size, TNextLayerWriter &&nextLayerWriter) const
Customized write functionality, invoked by write().
Definition: MsgSizeLayer.h:249
constexpr bool isMsgSizeLayer()
Compile time check of whether the provided type is a variant of MsgSizeLayer.
Definition: MsgSizeLayer.h:603
MsgSizeLayer(const MsgSizeLayer &)=default
Copy constructor.
MsgSizeLayer(MsgSizeLayer &&)=default
Move constructor.
comms::ErrorStatus doUpdate(Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Customized update functionality, invoked by update().
Definition: MsgSizeLayer.h:270
static void beforeRead(const Field &field, TMsg *msg)
Extra operation before read is forwarded to the next layer.
Definition: MsgSizeLayer.h:323
typename ParsedOptionsInternal::ExtendingClass ExtendingClass
Type of real extending class.
Definition: MsgSizeLayer.h:95
typename BaseImpl::Field Field
Type of the field object used to read/write remaining size value.
Definition: MsgSizeLayer.h:90
MsgSizeLayer()=default
Default constructor.
Base class for all the middle (non MsgDataLayer) protocol transport layers.
Definition: ProtocolLayerBase.h:61
typename details::ProtocolLayerMsgPtr< NextLayer >::Type MsgPtr
Type of pointer to the message.
Definition: ProtocolLayerBase.h:96
TField Field
Type of the field used for this layer.
Definition: ProtocolLayerBase.h:64
comms::option::def::ExtendingClass< T > ExtendingClass
Same as comms::option::def::ExtendingClass.
Definition: options.h:1822
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition: options.h:1459
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition: ErrorStatus.h:17
constexpr bool isMessageBase()
Compile time check of of whether the type is a message extending comms::MessageBase.
Definition: MessageBase.h:899
Disallow usage of ProtocolLayerForceReadUntilDataSplit option in earlier (outer wrapping) layers.
Definition: options.h:1122
Replacement to some types from standard type_traits.