65class ChecksumPrefixLayer :
public comms::frame::details::ChecksumPrefixLayerBase<TField, TCalc, TNextLayer, TOptions...>
67 using BaseImpl = comms::frame::details::ChecksumPrefixLayerBase<TField, TCalc, TNextLayer, TOptions...>;
68 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
73 using Field =
typename BaseImpl::Field;
105 static constexpr
bool hasExtendingClass()
107 return ParsedOptionsInternal::HasExtendingClass;
114 return ParsedOptionsInternal::HasVerifyBeforeRead;
147 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
153 TNextLayerReader&& nextLayerReader,
154 TExtraValues... extraValues)
156 using IterType =
typename std::decay<
decltype(iter)>::type;
157 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
158 "The read operation is expected to use random access iterator");
160 auto* msgPtr = BaseImpl::toMsgPtr(msg);
161 auto& thisObj = BaseImpl::thisLayer();
162 auto beforeFieldReadIter = iter;
163 auto checksumEs = thisObj.readField(msgPtr, field, iter, size);
164 if (checksumEs == ErrorStatus::NotEnoughData) {
165 BaseImpl::updateMissingSize(field, size, extraValues...);
168 if (checksumEs != ErrorStatus::Success) {
173 typename comms::util::LazyShallowConditional<
174 ParsedOptionsInternal::HasVerifyBeforeRead
180 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeFieldReadIter, iter));
187 std::forward<TNextLayerReader>(nextLayerReader),
219 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
225 TNextLayerWriter&& nextLayerWriter)
const
227 using IterType =
typename std::decay<
decltype(iter)>::type;
228 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
230 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
242 template <
typename TIter,
typename TNextLayerUpdater>
247 TNextLayerUpdater&& nextLayerUpdater)
const
249 auto checksumIter = iter;
250 std::advance(iter, Field::maxLength());
252 auto fromIter = iter;
253 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
258 using MsgPtr =
typename BaseImpl::MsgPtr;
260 !std::is_void<MsgPtr>::value,
261 "Please use update() overload that accepts message object as its first parameter");
263 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
264 return fieldUpdateInternal(msgPtr, checksumIter, fromIter, iter, size, field);
278 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
284 TNextLayerUpdater&& nextLayerUpdater)
const
286 auto& thisObj = BaseImpl::thisLayer();
287 auto checksumIter = iter;
288 auto fieldLen = thisObj.doFieldLength(msg);
289 std::advance(iter, fieldLen);
291 auto fromIter = iter;
292 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
297 return fieldUpdateInternal(&msg, checksumIter, fromIter, iter, size, field);
310 template <
typename TMsg,
typename TIter>
313 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
325 template <
typename TMsg,
typename TIter>
328 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
342 template <
typename TMsg,
typename TIter>
343 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
345 static_cast<void>(msg);
346 checksumValid =
true;
347 return TCalc()(iter, len);
359 return field.getValue();
373 template <
typename TChecksum,
typename TMsg>
376 static_cast<void>(msg);
377 field.setValue(checksum);
382 template <
typename... TParams>
383 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
385 template <
typename... TParams>
386 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
388 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
394 TReader&& nextLayerReader,
395 TExtraValues... extraValues)
397 auto fromIter = iter;
398 auto& thisObj = BaseImpl::thisLayer();
399 auto* msgPtr = BaseImpl::toMsgPtr(msg);
401 bool checksumValid =
false;
403 thisObj.calculateChecksum(
409 if (!checksumValid) {
413 auto expectedValue = thisObj.getChecksumFromField(field);
414 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
415 BaseImpl::resetMsg(msg);
416 return ErrorStatus::ProtocolError;
419 return nextLayerReader.read(msg, iter, size, extraValues...);
422 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
428 TReader&& nextLayerReader,
429 TExtraValues... extraValues)
431 auto fromIter = iter;
433 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
434 if ((es == ErrorStatus::NotEnoughData) ||
435 (es == ErrorStatus::ProtocolError)) {
439 auto* msgPtr = BaseImpl::toMsgPtr(msg);
440 auto& thisObj = BaseImpl::thisLayer();
441 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
442 bool checksumValid =
false;
444 thisObj.calculateChecksum(
450 if (!checksumValid) {
454 auto expectedValue = thisObj.getChecksumFromField(field);
455 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
456 BaseImpl::resetMsg(msg);
457 return ErrorStatus::ProtocolError;
463 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
469 TReader&& nextLayerReader,
470 VerifyBeforeReadTag<>,
471 TExtraValues... extraValues)
479 std::forward<TReader>(nextLayerReader),
483 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
489 TReader&& nextLayerReader,
490 VerifyAfterReadTag<>,
491 TExtraValues... extraValues)
499 std::forward<TReader>(nextLayerReader),
503 template <
typename TMsg,
typename TIter,
typename TWriter>
509 TWriter&& nextLayerWriter)
const
511 auto& thisObj = BaseImpl::thisLayer();
512 auto checksumIter = iter;
513 thisObj.prepareFieldForWrite(0U, &msg, field);
514 auto es = thisObj.writeField(&msg, field, iter, size);
520 static_cast<std::size_t
>(std::distance(checksumIter, iter));
522 auto fromIter = iter;
523 es = nextLayerWriter.write(msg, iter, size - checksumLen);
529 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
531 bool checksumValid =
false;
533 thisObj.calculateChecksum(
539 if (!checksumValid) {
543 thisObj.prepareFieldForWrite(checksum, &msg, field);
544 auto checksumEs = thisObj.writeField(&msg, field, checksumIter, checksumLen);
545 static_cast<void>(checksumEs);
550 template <
typename TMsg,
typename TIter,
typename TWriter>
556 TWriter&& nextLayerWriter)
const
558 auto& thisObj = BaseImpl::thisLayer();
559 thisObj.prepareFieldForWrite(0U, &msg, field);
560 auto es = thisObj.writeField(&msg, field, iter, size);
565 auto fieldLen = thisObj.doFieldLength(msg);
566 es = nextLayerWriter.write(msg, iter, size - fieldLen);
574 template <
typename TMsg,
typename TIter,
typename TWriter>
580 TWriter&& nextLayerWriter,
581 std::random_access_iterator_tag)
const
583 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
586 template <
typename TMsg,
typename TIter,
typename TWriter>
592 TWriter&& nextLayerWriter,
593 std::output_iterator_tag)
const
595 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
598 template <
typename TMsg,
typename TIter>
607 static_cast<void>(size);
609 auto& thisObj = BaseImpl::thisLayer();
610 auto len =
static_cast<std::size_t
>(std::distance(from, to));
611 auto fieldLen = Field::maxLength();
612 if (msgPtr !=
nullptr) {
613 fieldLen = thisObj.doFieldLength(*msgPtr);
617 bool checksumValid =
false;
619 thisObj.calculateChecksum(
625 if (!checksumValid) {
629 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
630 return thisObj.doWriteField(msgPtr, field, checksumIter, fieldLen);