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"
22 #include "comms/details/tag.h"
25 COMMS_MSVC_WARNING_PUSH
26 COMMS_MSVC_WARNING_DISABLE(4189)
62 template <
typename TField,
typename TCalc,
typename TNextLayer,
typename... TOptions>
67 details::ProtocolLayerExtendingClassT<
68 ChecksumLayer<TField, TCalc, TNextLayer, TOptions...>,
69 details::ChecksumLayerOptionsParser<TOptions...>
71 comms::option::def::ProtocolLayerDisallowReadUntilDataSplit
78 details::ProtocolLayerExtendingClassT<
80 details::ChecksumLayerOptionsParser<TOptions...>
85 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
121 static constexpr
bool hasExtendingClass()
123 return ParsedOptionsInternal::HasExtendingClass;
130 return ParsedOptionsInternal::HasVerifyBeforeRead;
163 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
169 TNextLayerReader&& nextLayerReader,
170 TExtraValues... extraValues)
172 using IterType =
typename std::decay<decltype(iter)>::type;
173 static_assert(std::is_same<
typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
174 "The read operation is expected to use random access iterator");
177 typename comms::util::LazyShallowConditional<
178 ParsedOptionsInternal::HasVerifyBeforeRead
190 std::forward<TNextLayerReader>(nextLayerReader),
220 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
226 TNextLayerWriter&& nextLayerWriter)
const
228 using IterType =
typename std::decay<decltype(iter)>::type;
229 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
231 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
243 template <
typename TIter,
typename TNextLayerUpdater>
248 TNextLayerUpdater&& nextLayerUpdater)
const
250 auto fromIter = iter;
251 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
258 !std::is_void<MsgPtr>::value,
259 "Please use update() overload that accepts message object as its first parameter");
261 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
262 return fieldUpdateInternal(msgPtr, fromIter, iter, size, field);
274 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
280 TNextLayerUpdater&& nextLayerUpdater)
const
282 auto fromIter = iter;
283 auto& thisObj = BaseImpl::thisLayer();
284 auto fieldLen = thisObj.doFieldLength(msg);
285 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
290 return fieldUpdateInternal(&msg, fromIter, iter, size, field);
303 template <
typename TMsg,
typename TIter>
306 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
318 template <
typename TMsg,
typename TIter>
321 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
335 template <
typename TMsg,
typename TIter>
336 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) -> decltype(TCalc()(iter, len))
338 static_cast<void>(msg);
339 checksumValid =
true;
340 return TCalc()(iter, len);
352 return field.getValue();
366 template <
typename TChecksum,
typename TMsg>
369 static_cast<void>(msg);
370 field.setValue(checksum);
374 template <
typename... TParams>
375 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
377 template <
typename... TParams>
378 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
380 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
386 TReader&& nextLayerReader,
387 TExtraValues... extraValues)
389 auto fromIter = iter;
390 auto* msgPtr = BaseImpl::toMsgPtr(msg);
391 auto fieldLen = Field::minLength();
392 auto& thisObj = BaseImpl::thisLayer();
393 if (msgPtr !=
nullptr) {
394 fieldLen = thisObj.doFieldLength(*msgPtr);
396 auto toIter = fromIter + (size - fieldLen);
397 auto len =
static_cast<std::size_t
>(std::distance(fromIter, toIter));
399 auto checksumEs = thisObj.readField(msgPtr, field, toIter, fieldLen);
400 if (checksumEs != ErrorStatus::Success) {
404 bool checksumValid =
false;
406 thisObj.calculateChecksum(
412 if (!checksumValid) {
416 auto expectedValue = thisObj.getChecksumFromField(field);
418 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
419 BaseImpl::resetMsg(msg);
420 return ErrorStatus::ProtocolError;
423 auto es = nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
424 if (es == ErrorStatus::Success) {
431 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
437 TReader&& nextLayerReader,
438 TExtraValues... extraValues)
440 auto fromIter = iter;
442 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
443 if ((es == ErrorStatus::NotEnoughData) ||
444 (es == ErrorStatus::ProtocolError)) {
448 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
450 auto remSize = size - len;
451 auto* msgPtr = BaseImpl::toMsgPtr(msg);
452 auto& thisObj = BaseImpl::thisLayer();
453 auto checksumEs = thisObj.readField(msgPtr, field, iter, remSize);
454 if (checksumEs == ErrorStatus::NotEnoughData) {
455 BaseImpl::updateMissingSize(field, remSize, extraValues...);
458 if (checksumEs != ErrorStatus::Success) {
459 BaseImpl::resetMsg(msg);
463 bool checksumValid =
false;
465 thisObj.calculateChecksum(
466 BaseImpl::toMsgPtr(msg),
471 if (!checksumValid) {
475 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 fromIter = iter;
534 auto es = nextLayerWriter.write(msg, iter, size);
541 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
542 auto remSize = size - len;
543 auto& thisObj = BaseImpl::thisLayer();
546 thisObj.prepareFieldForWrite(0, &msg, field);
547 auto esTmp = thisObj.writeField(&msg, field, iter, remSize);
555 bool checksumValid =
false;
557 thisObj.calculateChecksum(
563 if (!checksumValid) {
567 thisObj.prepareFieldForWrite(checksum, &msg, field);
568 return thisObj.writeField(&msg, field, iter, remSize);
571 template <
typename TMsg,
typename TIter,
typename TWriter>
577 TWriter&& nextLayerWriter)
const
579 auto& thisObj = BaseImpl::thisLayer();
580 auto fieldLen = thisObj.doFieldLength(msg);
581 auto es = nextLayerWriter.write(msg, iter, size - fieldLen);
587 auto esTmp = thisObj.writeField(&msg, field, iter, fieldLen);
588 static_cast<void>(esTmp);
593 template <
typename TMsg,
typename TIter,
typename TWriter>
599 TWriter&& nextLayerWriter,
600 std::random_access_iterator_tag)
const
602 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
605 template <
typename TMsg,
typename TIter,
typename TWriter>
611 TWriter&& nextLayerWriter,
612 std::output_iterator_tag)
const
614 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
617 template <
typename TMsg,
typename TIter>
618 ErrorStatus fieldUpdateInternal(
const TMsg* msgPtr, TIter from, TIter to, std::size_t size, Field& field)
const
621 auto len =
static_cast<std::size_t
>(std::distance(from, to));
622 auto& thisObj = BaseImpl::thisLayer();
623 if (msgPtr !=
nullptr) {
624 COMMS_ASSERT(len == (size - thisObj.doFieldLength(*msgPtr)));
629 auto remSize = size - len;
631 bool checksumValid =
false;
633 thisObj.calculateChecksum(
639 if (!checksumValid) {
643 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
644 return thisObj.writeField(msgPtr, field, to, remSize);
650 template <
typename T>
651 struct ChecksumLayerCheckHelper
653 static const bool Value =
false;
656 template <
typename TField,
typename TCalc,
typename TNextLayer,
typename... TOptions>
657 struct ChecksumLayerCheckHelper<ChecksumLayer<TField, TCalc, TNextLayer, TOptions...> >
659 static const bool Value =
true;
667 template <
typename T>
670 return details::ChecksumLayerCheckHelper<T>::Value;
677 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.
Contains definition of various casts.
Base class to all the field classes.
Definition: Field.h:33
Protocol layer that is responsible to calculate checksum on the data written by all the wrapped inter...
Definition: ChecksumLayer.h:73
TCalc ChecksumCalc
Provided checksum calculation algorithm.
Definition: ChecksumLayer.h:92
static auto calculateChecksum(const TMsg *msg, TIter &iter, std::size_t len, bool &checksumValid) -> decltype(TCalc()(iter, len))
Calculate checksum.
Definition: ChecksumLayer.h:336
comms::ErrorStatus doUpdate(const TMsg &msg, Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Customized update functionality, invoked by update().
Definition: ChecksumLayer.h:275
ErrorStatus doWrite(Field &field, const TMsg &msg, TIter &iter, std::size_t size, TNextLayerWriter &&nextLayerWriter) const
Customized write functionality, invoked by write().
Definition: ChecksumLayer.h:221
ChecksumLayer(ChecksumLayer &&)=default
Move constructor.
static auto getChecksumFromField(const Field &field) -> decltype(field.getValue())
Retrieve checksum value from the field.
Definition: ChecksumLayer.h:350
comms::ErrorStatus readField(const TMsg *msgPtr, Field &field, TIter &iter, std::size_t len)
Read the checksum field.
Definition: ChecksumLayer.h:304
ChecksumLayer(const ChecksumLayer &)=default
Copy constructor.
ErrorStatus doRead(Field &field, TMsg &msg, TIter &iter, std::size_t size, TNextLayerReader &&nextLayerReader, TExtraValues... extraValues)
Customized read functionality, invoked by read().
Definition: ChecksumLayer.h:164
static void prepareFieldForWrite(TChecksum checksum, const TMsg *msg, Field &field)
Prepare field for writing.
Definition: ChecksumLayer.h:367
~ChecksumLayer() noexcept=default
Destructor.
ChecksumLayer()=default
Default constructor.
typename ParsedOptionsInternal::ExtendingClass ExtendingClass
Type of real extending class.
Definition: ChecksumLayer.h:97
comms::ErrorStatus doUpdate(Field &field, TIter &iter, std::size_t size, TNextLayerUpdater &&nextLayerUpdater) const
Customized update functionality, invoked by update().
Definition: ChecksumLayer.h:244
comms::ErrorStatus writeField(const TMsg *msgPtr, const Field &field, TIter &iter, std::size_t len) const
Write the checksum field.
Definition: ChecksumLayer.h:319
static constexpr bool hasVerifyBeforeRead()
Compile time inquiry of whether comms::option::def::ChecksumLayerVerifyBeforeRead options has been us...
Definition: ChecksumLayer.h:128
typename BaseImpl::Field Field
Type of the field object used to read/write checksum value.
Definition: ChecksumLayer.h:89
constexpr bool isChecksumLayer()
Compile time check of whether the provided type is a variant of ChecksumLayer.
Definition: ChecksumLayer.h:668
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.