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);