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