14 #include <type_traits>
18 #include "comms/protocol/details/ProtocolLayerBase.h"
19 #include "comms/protocol/details/ChecksumLayerOptionsParser.h"
20 #include "comms/protocol/details/ProtocolLayerExtendingClassHelper.h"
23 COMMS_MSVC_WARNING_PUSH
24 COMMS_MSVC_WARNING_DISABLE(4189)
63 template <
typename TField,
typename TCalc,
typename TNextLayer,
typename... TOptions>
68 details::ProtocolLayerExtendingClassT<
69 ChecksumPrefixLayer<TField, TCalc, TNextLayer, TOptions...>,
70 details::ChecksumLayerOptionsParser<TOptions...>
72 typename details::template ChecksumLayerOptionsParser<TOptions...>::template SuppressForVerifyBeforeRead<
73 comms::option::def::ProtocolLayerDisallowReadUntilDataSplit
81 details::ProtocolLayerExtendingClassT<
83 details::ChecksumLayerOptionsParser<TOptions...>
85 typename details::template ChecksumLayerOptionsParser<TOptions...>::template SuppressForVerifyBeforeRead<
90 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
127 static constexpr
bool hasExtendingClass()
129 return ParsedOptionsInternal::HasExtendingClass;
136 return ParsedOptionsInternal::HasVerifyBeforeRead;
169 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
175 TNextLayerReader&& nextLayerReader,
176 TExtraValues... extraValues)
178 using IterType =
typename std::decay<decltype(iter)>::type;
179 static_assert(std::is_same<
typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
180 "The read operation is expected to use random access iterator");
182 auto* msgPtr = BaseImpl::toMsgPtr(msg);
183 auto& thisObj = BaseImpl::thisLayer();
184 auto beforeFieldReadIter = iter;
185 auto checksumEs = thisObj.readField(msgPtr, field, iter, size);
186 if (checksumEs == ErrorStatus::NotEnoughData) {
187 BaseImpl::updateMissingSize(field, size, extraValues...);
190 if (checksumEs != ErrorStatus::Success) {
195 typename comms::util::LazyShallowConditional<
196 ParsedOptionsInternal::HasVerifyBeforeRead
202 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeFieldReadIter, iter));
209 std::forward<TNextLayerReader>(nextLayerReader),
241 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
247 TNextLayerWriter&& nextLayerWriter)
const
249 using IterType =
typename std::decay<decltype(iter)>::type;
250 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
252 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
264 template <
typename TIter,
typename TNextLayerUpdater>
269 TNextLayerUpdater&& nextLayerUpdater)
const
271 auto checksumIter = iter;
272 std::advance(iter, Field::maxLength());
274 auto fromIter = iter;
275 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
282 !std::is_void<MsgPtr>::value,
283 "Please use update() overload that accepts message object as its first parameter");
285 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
286 return fieldUpdateInternal(msgPtr, checksumIter, fromIter, iter, size, field);
300 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
306 TNextLayerUpdater&& nextLayerUpdater)
const
308 auto& thisObj = BaseImpl::thisLayer();
309 auto checksumIter = iter;
310 auto fieldLen = thisObj.doFieldLength(msg);
311 std::advance(iter, fieldLen);
313 auto fromIter = iter;
314 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
319 return fieldUpdateInternal(&msg, checksumIter, fromIter, iter, size, field);
332 template <
typename TMsg,
typename TIter>
335 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
347 template <
typename TMsg,
typename TIter>
350 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
364 template <
typename TMsg,
typename TIter>
365 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) -> decltype(TCalc()(iter, len))
367 static_cast<void>(msg);
368 checksumValid =
true;
369 return TCalc()(iter, len);
381 return field.getValue();
395 template <
typename TChecksum,
typename TMsg>
398 static_cast<void>(msg);
399 field.setValue(checksum);
404 template <
typename... TParams>
405 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
407 template <
typename... TParams>
408 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
410 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
416 TReader&& nextLayerReader,
417 TExtraValues... extraValues)
419 auto fromIter = iter;
420 auto& thisObj = BaseImpl::thisLayer();
421 auto* msgPtr = BaseImpl::toMsgPtr(msg);
423 bool checksumValid =
false;
425 thisObj.calculateChecksum(
431 if (!checksumValid) {
435 auto expectedValue = thisObj.getChecksumFromField(field);
436 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
437 BaseImpl::resetMsg(msg);
438 return ErrorStatus::ProtocolError;
441 return nextLayerReader.read(msg, iter, size, extraValues...);
444 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
450 TReader&& nextLayerReader,
451 TExtraValues... extraValues)
453 auto fromIter = iter;
455 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
456 if ((es == ErrorStatus::NotEnoughData) ||
457 (es == ErrorStatus::ProtocolError)) {
461 auto* msgPtr = BaseImpl::toMsgPtr(msg);
462 auto& thisObj = BaseImpl::thisLayer();
463 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
464 bool checksumValid =
false;
466 thisObj.calculateChecksum(
472 if (!checksumValid) {
476 auto expectedValue = thisObj.getChecksumFromField(field);
477 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
478 BaseImpl::resetMsg(msg);
479 return ErrorStatus::ProtocolError;
485 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
491 TReader&& nextLayerReader,
492 VerifyBeforeReadTag<>,
493 TExtraValues... extraValues)
501 std::forward<TReader>(nextLayerReader),
505 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
511 TReader&& nextLayerReader,
512 VerifyAfterReadTag<>,
513 TExtraValues... extraValues)
521 std::forward<TReader>(nextLayerReader),
525 template <
typename TMsg,
typename TIter,
typename TWriter>
531 TWriter&& nextLayerWriter)
const
533 auto& thisObj = BaseImpl::thisLayer();
534 auto checksumIter = iter;
535 thisObj.prepareFieldForWrite(0U, &msg, field);
536 auto es = thisObj.writeField(&msg, field, iter, size);
542 static_cast<std::size_t
>(std::distance(checksumIter, iter));
544 auto fromIter = iter;
545 es = nextLayerWriter.write(msg, iter, size - checksumLen);
551 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
553 bool checksumValid =
false;
555 thisObj.calculateChecksum(
561 if (!checksumValid) {
565 thisObj.prepareFieldForWrite(checksum, &msg, field);
566 auto checksumEs = thisObj.writeField(&msg, field, checksumIter, checksumLen);
567 static_cast<void>(checksumEs);
572 template <
typename TMsg,
typename TIter,
typename TWriter>
578 TWriter&& nextLayerWriter)
const
580 auto& thisObj = BaseImpl::thisLayer();
581 thisObj.prepareFieldForWrite(0U, &msg, field);
582 auto es = thisObj.writeField(&msg, field, iter, size);
587 auto fieldLen = thisObj.doFieldLength(msg);
588 es = nextLayerWriter.write(msg, iter, size - fieldLen);
596 template <
typename TMsg,
typename TIter,
typename TWriter>
602 TWriter&& nextLayerWriter,
603 std::random_access_iterator_tag)
const
605 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
608 template <
typename TMsg,
typename TIter,
typename TWriter>
614 TWriter&& nextLayerWriter,
615 std::output_iterator_tag)
const
617 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
620 template <
typename TMsg,
typename TIter>
629 static_cast<void>(size);
631 auto& thisObj = BaseImpl::thisLayer();
632 auto len =
static_cast<std::size_t
>(std::distance(from, to));
633 auto fieldLen = Field::maxLength();
634 if (msgPtr !=
nullptr) {
635 fieldLen = thisObj.doFieldLength(*msgPtr);
639 bool checksumValid =
false;
641 thisObj.calculateChecksum(
647 if (!checksumValid) {
651 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
652 return thisObj.doWriteField(msgPtr, field, checksumIter, fieldLen);
659 template <
typename T>
660 struct ChecksumPrefixLayerCheckHelper
662 static const bool Value =
false;
665 template <
typename TField,
typename TCalc,
typename TNextLayer,
typename... TOptions>
666 struct ChecksumPrefixLayerCheckHelper<ChecksumPrefixLayer<TField, TCalc, TNextLayer, TOptions...> >
668 static const bool Value =
true;
676 template <
typename T>
679 return details::ChecksumPrefixLayerCheckHelper<T>::Value;
686 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.
Base class to all the field classes.
Definition: Field.h:33
constexpr bool isChecksumPrefixLayer()
Compile time check of whether the provided type is a variant of ChecksumPrefixLayer.
Definition: ChecksumPrefixLayer.h:677
Protocol layer that is responsible to calculate checksum on the data written by all the wrapped inter...
Definition: ChecksumPrefixLayer.h:76
comms::ErrorStatus doUpdate(const TMsg &msg, Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Customized update functionality, invoked by update().
Definition: ChecksumPrefixLayer.h:301
comms::ErrorStatus doRead(Field &field, TMsg &msg, TIter &iter, std::size_t size, TNextLayerReader &&nextLayerReader, TExtraValues... extraValues)
Customized read functionality, invoked by read().
Definition: ChecksumPrefixLayer.h:170
comms::ErrorStatus writeField(const TMsg *msgPtr, const Field &field, TIter &iter, std::size_t len) const
Write the checksum field.
Definition: ChecksumPrefixLayer.h:348
typename ParsedOptionsInternal::ExtendingClass ExtendingClass
Type of real extending class.
Definition: ChecksumPrefixLayer.h:103
static constexpr bool hasVerifyBeforeRead()
Compile time inquiry of whether comms::option::def::ChecksumLayerVerifyBeforeRead options has been us...
Definition: ChecksumPrefixLayer.h:134
ChecksumPrefixLayer(const ChecksumPrefixLayer &)=default
Copy constructor.
comms::ErrorStatus readField(const TMsg *msgPtr, Field &field, TIter &iter, std::size_t len)
Read the checksum field.
Definition: ChecksumPrefixLayer.h:333
comms::ErrorStatus doWrite(Field &field, const TMsg &msg, TIter &iter, std::size_t size, TNextLayerWriter &&nextLayerWriter) const
Customized write functionality, invoked by write().
Definition: ChecksumPrefixLayer.h:242
static auto getChecksumFromField(const Field &field) -> decltype(field.getValue())
Retrieve checksum value from the field.
Definition: ChecksumPrefixLayer.h:379
comms::ErrorStatus doUpdate(Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Customized update functionality, invoked by update().
Definition: ChecksumPrefixLayer.h:265
TCalc ChecksumCalc
Provided checksum calculation algorithm.
Definition: ChecksumPrefixLayer.h:98
~ChecksumPrefixLayer() noexcept=default
Destructor.
typename BaseImpl::Field Field
Type of the field object used to read/write checksum value.
Definition: ChecksumPrefixLayer.h:95
ChecksumPrefixLayer()=default
Default constructor.
ChecksumPrefixLayer(ChecksumPrefixLayer &&)=default
Move constructor.
static void prepareFieldForWrite(TChecksum checksum, const TMsg *msg, Field &field)
Prepare field for writing.
Definition: ChecksumPrefixLayer.h:396
static auto calculateChecksum(const TMsg *msg, TIter &iter, std::size_t len, bool &checksumValid) -> decltype(TCalc()(iter, len))
Calculate checksum.
Definition: ChecksumPrefixLayer.h:365
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
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.
Disallow usage of ProtocolLayerForceReadUntilDataSplit option in earlier (outer wrapping) layers.
Definition: options.h:1122
Replacement to some types from standard type_traits.