64class ChecksumPrefixLayer :
public comms::frame::details::ChecksumPrefixLayerBase<TField, TCalc, TNextLayer, TOptions...>
66 using BaseImpl = comms::frame::details::ChecksumPrefixLayerBase<TField, TCalc, TNextLayer, TOptions...>;
67 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
72 using Field =
typename BaseImpl::Field;
104 static constexpr
bool hasExtendingClass()
106 return ParsedOptionsInternal::HasExtendingClass;
113 return ParsedOptionsInternal::HasVerifyBeforeRead;
146 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
152 TNextLayerReader&& nextLayerReader,
153 TExtraValues... extraValues)
155 using IterType =
typename std::decay<
decltype(iter)>::type;
156 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
157 "The read operation is expected to use random access iterator");
159 auto* msgPtr = BaseImpl::toMsgPtr(msg);
160 auto& thisObj = BaseImpl::thisLayer();
161 auto beforeFieldReadIter = iter;
162 auto checksumEs = thisObj.readField(msgPtr, field, iter, size);
163 if (checksumEs == ErrorStatus::NotEnoughData) {
164 BaseImpl::updateMissingSize(field, size, extraValues...);
167 if (checksumEs != ErrorStatus::Success) {
172 typename comms::util::LazyShallowConditional<
173 ParsedOptionsInternal::HasVerifyBeforeRead
179 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeFieldReadIter, iter));
186 std::forward<TNextLayerReader>(nextLayerReader),
218 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
224 TNextLayerWriter&& nextLayerWriter)
const
226 using IterType =
typename std::decay<
decltype(iter)>::type;
227 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
229 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
241 template <
typename TIter,
typename TNextLayerUpdater>
246 TNextLayerUpdater&& nextLayerUpdater)
const
248 auto checksumIter = iter;
249 std::advance(iter, Field::maxLength());
251 auto fromIter = iter;
252 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
257 using MsgPtr =
typename BaseImpl::MsgPtr;
259 !std::is_void<MsgPtr>::value,
260 "Please use update() overload that accepts message object as its first parameter");
262 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
263 return fieldUpdateInternal(msgPtr, checksumIter, fromIter, iter, size, field);
277 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
283 TNextLayerUpdater&& nextLayerUpdater)
const
285 auto& thisObj = BaseImpl::thisLayer();
286 auto checksumIter = iter;
287 auto fieldLen = thisObj.doFieldLength(msg);
288 std::advance(iter, fieldLen);
290 auto fromIter = iter;
291 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
296 return fieldUpdateInternal(&msg, checksumIter, fromIter, iter, size, field);
309 template <
typename TMsg,
typename TIter>
312 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
324 template <
typename TMsg,
typename TIter>
327 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
341 template <
typename TMsg,
typename TIter>
342 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
344 static_cast<void>(msg);
345 checksumValid =
true;
346 return TCalc()(iter, len);
358 return field.getValue();
372 template <
typename TChecksum,
typename TMsg>
375 static_cast<void>(msg);
376 field.setValue(checksum);
381 template <
typename... TParams>
382 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
384 template <
typename... TParams>
385 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
387 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
393 TReader&& nextLayerReader,
394 TExtraValues... extraValues)
396 auto fromIter = iter;
397 auto& thisObj = BaseImpl::thisLayer();
398 auto* msgPtr = BaseImpl::toMsgPtr(msg);
400 bool checksumValid =
false;
402 thisObj.calculateChecksum(
408 if (!checksumValid) {
412 auto expectedValue = thisObj.getChecksumFromField(field);
413 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
414 BaseImpl::resetMsg(msg);
415 return ErrorStatus::ProtocolError;
418 return nextLayerReader.read(msg, iter, size, extraValues...);
421 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
427 TReader&& nextLayerReader,
428 TExtraValues... extraValues)
430 auto fromIter = iter;
432 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
433 if ((es == ErrorStatus::NotEnoughData) ||
434 (es == ErrorStatus::ProtocolError)) {
438 auto* msgPtr = BaseImpl::toMsgPtr(msg);
439 auto& thisObj = BaseImpl::thisLayer();
440 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
441 bool checksumValid =
false;
443 thisObj.calculateChecksum(
449 if (!checksumValid) {
453 auto expectedValue = thisObj.getChecksumFromField(field);
454 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
455 BaseImpl::resetMsg(msg);
456 return ErrorStatus::ProtocolError;
462 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
468 TReader&& nextLayerReader,
469 VerifyBeforeReadTag<>,
470 TExtraValues... extraValues)
478 std::forward<TReader>(nextLayerReader),
482 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
488 TReader&& nextLayerReader,
489 VerifyAfterReadTag<>,
490 TExtraValues... extraValues)
498 std::forward<TReader>(nextLayerReader),
502 template <
typename TMsg,
typename TIter,
typename TWriter>
508 TWriter&& nextLayerWriter)
const
510 auto& thisObj = BaseImpl::thisLayer();
511 auto checksumIter = iter;
512 thisObj.prepareFieldForWrite(0U, &msg, field);
513 auto es = thisObj.writeField(&msg, field, iter, size);
519 static_cast<std::size_t
>(std::distance(checksumIter, iter));
521 auto fromIter = iter;
522 es = nextLayerWriter.write(msg, iter, size - checksumLen);
528 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
530 bool checksumValid =
false;
532 thisObj.calculateChecksum(
538 if (!checksumValid) {
542 thisObj.prepareFieldForWrite(checksum, &msg, field);
543 auto checksumEs = thisObj.writeField(&msg, field, checksumIter, checksumLen);
544 static_cast<void>(checksumEs);
549 template <
typename TMsg,
typename TIter,
typename TWriter>
555 TWriter&& nextLayerWriter)
const
557 auto& thisObj = BaseImpl::thisLayer();
558 thisObj.prepareFieldForWrite(0U, &msg, field);
559 auto es = thisObj.writeField(&msg, field, iter, size);
564 auto fieldLen = thisObj.doFieldLength(msg);
565 es = nextLayerWriter.write(msg, iter, size - fieldLen);
573 template <
typename TMsg,
typename TIter,
typename TWriter>
579 TWriter&& nextLayerWriter,
580 std::random_access_iterator_tag)
const
582 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
585 template <
typename TMsg,
typename TIter,
typename TWriter>
591 TWriter&& nextLayerWriter,
592 std::output_iterator_tag)
const
594 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
597 template <
typename TMsg,
typename TIter>
606 static_cast<void>(size);
608 auto& thisObj = BaseImpl::thisLayer();
609 auto len =
static_cast<std::size_t
>(std::distance(from, to));
610 auto fieldLen = Field::maxLength();
611 if (msgPtr !=
nullptr) {
612 fieldLen = thisObj.doFieldLength(*msgPtr);
616 bool checksumValid =
false;
618 thisObj.calculateChecksum(
624 if (!checksumValid) {
628 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
629 return thisObj.doWriteField(msgPtr, field, checksumIter, fieldLen);