64class ChecksumLayer :
public comms::frame::details::ChecksumLayerBase<TField, TCalc, TNextLayer, TOptions...>
66 using BaseImpl = comms::frame::details::ChecksumLayerBase<TField, TCalc, TNextLayer, TOptions...>;
67 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
71 using Field =
typename BaseImpl::Field;
103 static constexpr
bool hasExtendingClass()
105 return ParsedOptionsInternal::HasExtendingClass;
112 return ParsedOptionsInternal::HasVerifyBeforeRead;
145 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
151 TNextLayerReader&& nextLayerReader,
152 TExtraValues... extraValues)
154 using IterType =
typename std::decay<
decltype(iter)>::type;
155 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
156 "The read operation is expected to use random access iterator");
159 typename comms::util::LazyShallowConditional<
160 ParsedOptionsInternal::HasVerifyBeforeRead
172 std::forward<TNextLayerReader>(nextLayerReader),
202 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
208 TNextLayerWriter&& nextLayerWriter)
const
210 using IterType =
typename std::decay<
decltype(iter)>::type;
211 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
213 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
225 template <
typename TIter,
typename TNextLayerUpdater>
230 TNextLayerUpdater&& nextLayerUpdater)
const
232 auto fromIter = iter;
233 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
238 using MsgPtr =
typename BaseImpl::MsgPtr;
240 !std::is_void<MsgPtr>::value,
241 "Please use update() overload that accepts message object as its first parameter");
243 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
244 return fieldUpdateInternal(msgPtr, fromIter, iter, size, field);
256 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
262 TNextLayerUpdater&& nextLayerUpdater)
const
264 auto fromIter = iter;
265 auto& thisObj = BaseImpl::thisLayer();
266 auto fieldLen = thisObj.doFieldLength(msg);
267 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
272 return fieldUpdateInternal(&msg, fromIter, iter, size, field);
285 template <
typename TMsg,
typename TIter>
288 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
300 template <
typename TMsg,
typename TIter>
303 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
317 template <
typename TMsg,
typename TIter>
318 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
320 static_cast<void>(msg);
321 checksumValid =
true;
322 return TCalc()(iter, len);
334 return field.getValue();
348 template <
typename TChecksum,
typename TMsg>
351 static_cast<void>(msg);
352 field.setValue(checksum);
356 template <
typename... TParams>
357 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
359 template <
typename... TParams>
360 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
362 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
368 TReader&& nextLayerReader,
369 TExtraValues... extraValues)
371 auto fromIter = iter;
372 auto* msgPtr = BaseImpl::toMsgPtr(msg);
373 auto fieldLen = Field::minLength();
374 auto& thisObj = BaseImpl::thisLayer();
375 if (msgPtr !=
nullptr) {
376 fieldLen = thisObj.doFieldLength(*msgPtr);
378 auto toIter = fromIter + (size - fieldLen);
379 auto len =
static_cast<std::size_t
>(std::distance(fromIter, toIter));
381 auto checksumEs = thisObj.readField(msgPtr, field, toIter, fieldLen);
382 if (checksumEs != ErrorStatus::Success) {
386 bool checksumValid =
false;
388 thisObj.calculateChecksum(
394 if (!checksumValid) {
398 auto expectedValue = thisObj.getChecksumFromField(field);
400 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
401 BaseImpl::resetMsg(msg);
402 return ErrorStatus::ProtocolError;
405 auto es = nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
406 if (es == ErrorStatus::Success) {
413 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
419 TReader&& nextLayerReader,
420 TExtraValues... extraValues)
422 auto fromIter = iter;
424 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
425 if ((es == ErrorStatus::NotEnoughData) ||
426 (es == ErrorStatus::ProtocolError)) {
430 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
432 auto remSize = size - len;
433 auto* msgPtr = BaseImpl::toMsgPtr(msg);
434 auto& thisObj = BaseImpl::thisLayer();
435 auto checksumEs = thisObj.readField(msgPtr, field, iter, remSize);
436 if (checksumEs == ErrorStatus::NotEnoughData) {
437 BaseImpl::updateMissingSize(field, remSize, extraValues...);
440 if (checksumEs != ErrorStatus::Success) {
441 BaseImpl::resetMsg(msg);
445 bool checksumValid =
false;
447 thisObj.calculateChecksum(
448 BaseImpl::toMsgPtr(msg),
453 if (!checksumValid) {
457 auto expectedValue = thisObj.getChecksumFromField(field);
459 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
460 BaseImpl::resetMsg(msg);
461 return ErrorStatus::ProtocolError;
467 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
473 TReader&& nextLayerReader,
474 VerifyBeforeReadTag<>,
475 TExtraValues... extraValues)
483 std::forward<TReader>(nextLayerReader),
487 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
493 TReader&& nextLayerReader,
494 VerifyAfterReadTag<>,
495 TExtraValues... extraValues)
503 std::forward<TReader>(nextLayerReader),
507 template <
typename TMsg,
typename TIter,
typename TWriter>
513 TWriter&& nextLayerWriter)
const
515 auto fromIter = iter;
516 auto es = nextLayerWriter.write(msg, iter, size);
523 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
524 auto remSize = size - len;
525 auto& thisObj = BaseImpl::thisLayer();
528 thisObj.prepareFieldForWrite(0, &msg, field);
529 auto esTmp = thisObj.writeField(&msg, field, iter, remSize);
537 bool checksumValid =
false;
539 thisObj.calculateChecksum(
545 if (!checksumValid) {
549 thisObj.prepareFieldForWrite(checksum, &msg, field);
550 return thisObj.writeField(&msg, field, iter, remSize);
553 template <
typename TMsg,
typename TIter,
typename TWriter>
559 TWriter&& nextLayerWriter)
const
561 auto& thisObj = BaseImpl::thisLayer();
562 auto fieldLen = thisObj.doFieldLength(msg);
563 auto es = nextLayerWriter.write(msg, iter, size - fieldLen);
569 auto esTmp = thisObj.writeField(&msg, field, iter, fieldLen);
570 static_cast<void>(esTmp);
575 template <
typename TMsg,
typename TIter,
typename TWriter>
581 TWriter&& nextLayerWriter,
582 std::random_access_iterator_tag)
const
584 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
587 template <
typename TMsg,
typename TIter,
typename TWriter>
593 TWriter&& nextLayerWriter,
594 std::output_iterator_tag)
const
596 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
599 template <
typename TMsg,
typename TIter>
600 ErrorStatus fieldUpdateInternal(
const TMsg* msgPtr, TIter from, TIter to, std::size_t size, Field& field)
const
603 auto len =
static_cast<std::size_t
>(std::distance(from, to));
604 auto& thisObj = BaseImpl::thisLayer();
605 if (msgPtr !=
nullptr) {
606 COMMS_ASSERT(len == (size - thisObj.doFieldLength(*msgPtr)));
611 auto remSize = size - len;
613 bool checksumValid =
false;
615 thisObj.calculateChecksum(
621 if (!checksumValid) {
625 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
626 return thisObj.writeField(msgPtr, field, to, remSize);