68class ChecksumPrefixLayer :
public comms::frame::details::ChecksumPrefixLayerBase<TField, TCalc, TNextLayer, TOptions...>
70 using BaseImpl = comms::frame::details::ChecksumPrefixLayerBase<TField, TCalc, TNextLayer, TOptions...>;
71 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
76 using Field =
typename BaseImpl::Field;
101 static constexpr
bool hasExtendingClass()
103 return ParsedOptionsInternal::HasExtendingClass;
110 return ParsedOptionsInternal::HasVerifyBeforeRead;
143 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
149 TNextLayerReader&& nextLayerReader,
150 TExtraValues... extraValues)
152 using IterType =
typename std::decay<
decltype(iter)>::type;
153 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
154 "The read operation is expected to use random access iterator");
156 auto* msgPtr = BaseImpl::toMsgPtr(msg);
157 auto& thisObj = BaseImpl::thisLayer();
158 auto beforeFieldReadIter = iter;
159 auto checksumEs = thisObj.readField(msgPtr, field, iter, size);
160 if (checksumEs == ErrorStatus::NotEnoughData) {
161 BaseImpl::updateMissingSize(field, size, extraValues...);
164 if (checksumEs != ErrorStatus::Success) {
169 typename comms::util::LazyShallowConditional<
170 ParsedOptionsInternal::HasVerifyBeforeRead
176 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeFieldReadIter, iter));
183 std::forward<TNextLayerReader>(nextLayerReader),
215 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
221 TNextLayerWriter&& nextLayerWriter)
const
223 using IterType =
typename std::decay<
decltype(iter)>::type;
224 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
226 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
238 template <
typename TIter,
typename TNextLayerUpdater>
243 TNextLayerUpdater&& nextLayerUpdater)
const
245 auto checksumIter = iter;
246 std::advance(iter, Field::maxLength());
248 auto fromIter = iter;
249 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
254 using MsgPtr =
typename BaseImpl::MsgPtr;
256 !std::is_void<MsgPtr>::value,
257 "Please use update() overload that accepts message object as its first parameter");
259 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
260 return fieldUpdateInternal(msgPtr, checksumIter, fromIter, iter, size, field);
274 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
280 TNextLayerUpdater&& nextLayerUpdater)
const
282 auto& thisObj = BaseImpl::thisLayer();
283 auto checksumIter = iter;
284 auto fieldLen = thisObj.doFieldLength(msg);
285 std::advance(iter, fieldLen);
287 auto fromIter = iter;
288 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
293 return fieldUpdateInternal(&msg, checksumIter, fromIter, iter, size, field);
306 template <
typename TMsg,
typename TIter>
309 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
321 template <
typename TMsg,
typename TIter>
324 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
338 template <
typename TMsg,
typename TIter>
339 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
341 static_cast<void>(msg);
342 checksumValid =
true;
343 return TCalc()(iter, len);
355 return field.getValue();
369 template <
typename TChecksum,
typename TMsg>
372 static_cast<void>(msg);
373 field.setValue(checksum);
378 template <
typename... TParams>
379 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
381 template <
typename... TParams>
382 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
384 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
390 TReader&& nextLayerReader,
391 TExtraValues... extraValues)
393 auto fromIter = iter;
394 auto& thisObj = BaseImpl::thisLayer();
395 auto* msgPtr = BaseImpl::toMsgPtr(msg);
397 bool checksumValid =
false;
399 thisObj.calculateChecksum(
405 if (!checksumValid) {
409 auto expectedValue = thisObj.getChecksumFromField(field);
410 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
411 BaseImpl::resetMsg(msg);
412 return ErrorStatus::ProtocolError;
415 return nextLayerReader.read(msg, iter, size, extraValues...);
418 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
424 TReader&& nextLayerReader,
425 TExtraValues... extraValues)
427 auto fromIter = iter;
429 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
430 if ((es == ErrorStatus::NotEnoughData) ||
431 (es == ErrorStatus::ProtocolError)) {
435 auto* msgPtr = BaseImpl::toMsgPtr(msg);
436 auto& thisObj = BaseImpl::thisLayer();
437 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
438 bool checksumValid =
false;
440 thisObj.calculateChecksum(
446 if (!checksumValid) {
450 auto expectedValue = thisObj.getChecksumFromField(field);
451 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
452 BaseImpl::resetMsg(msg);
453 return ErrorStatus::ProtocolError;
459 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
465 TReader&& nextLayerReader,
466 VerifyBeforeReadTag<>,
467 TExtraValues... extraValues)
475 std::forward<TReader>(nextLayerReader),
479 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
485 TReader&& nextLayerReader,
486 VerifyAfterReadTag<>,
487 TExtraValues... extraValues)
495 std::forward<TReader>(nextLayerReader),
499 template <
typename TMsg,
typename TIter,
typename TWriter>
505 TWriter&& nextLayerWriter)
const
507 auto& thisObj = BaseImpl::thisLayer();
508 auto checksumIter = iter;
509 thisObj.prepareFieldForWrite(0U, &msg, field);
510 auto es = thisObj.writeField(&msg, field, iter, size);
516 static_cast<std::size_t
>(std::distance(checksumIter, iter));
518 auto fromIter = iter;
519 es = nextLayerWriter.write(msg, iter, size - checksumLen);
525 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
527 bool checksumValid =
false;
529 thisObj.calculateChecksum(
535 if (!checksumValid) {
539 thisObj.prepareFieldForWrite(checksum, &msg, field);
540 auto checksumEs = thisObj.writeField(&msg, field, checksumIter, checksumLen);
541 static_cast<void>(checksumEs);
546 template <
typename TMsg,
typename TIter,
typename TWriter>
552 TWriter&& nextLayerWriter)
const
554 auto& thisObj = BaseImpl::thisLayer();
555 thisObj.prepareFieldForWrite(0U, &msg, field);
556 auto es = thisObj.writeField(&msg, field, iter, size);
561 auto fieldLen = thisObj.doFieldLength(msg);
562 es = nextLayerWriter.write(msg, iter, size - fieldLen);
570 template <
typename TMsg,
typename TIter,
typename TWriter>
576 TWriter&& nextLayerWriter,
577 std::random_access_iterator_tag)
const
579 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
582 template <
typename TMsg,
typename TIter,
typename TWriter>
588 TWriter&& nextLayerWriter,
589 std::output_iterator_tag)
const
591 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
594 template <
typename TMsg,
typename TIter>
603 static_cast<void>(size);
605 auto& thisObj = BaseImpl::thisLayer();
606 auto len =
static_cast<std::size_t
>(std::distance(from, to));
607 auto fieldLen = Field::maxLength();
608 if (msgPtr !=
nullptr) {
609 fieldLen = thisObj.doFieldLength(*msgPtr);
613 bool checksumValid =
false;
615 thisObj.calculateChecksum(
621 if (!checksumValid) {
625 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
626 return thisObj.doWriteField(msgPtr, field, checksumIter, fieldLen);