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;
96 static constexpr
bool hasExtendingClass()
98 return ParsedOptionsInternal::HasExtendingClass;
105 return ParsedOptionsInternal::HasVerifyBeforeRead;
138 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
144 TNextLayerReader&& nextLayerReader,
145 TExtraValues... extraValues)
147 using IterType =
typename std::decay<
decltype(iter)>::type;
148 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
149 "The read operation is expected to use random access iterator");
152 typename comms::util::LazyShallowConditional<
153 ParsedOptionsInternal::HasVerifyBeforeRead
165 std::forward<TNextLayerReader>(nextLayerReader),
195 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
201 TNextLayerWriter&& nextLayerWriter)
const
203 using IterType =
typename std::decay<
decltype(iter)>::type;
204 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
206 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
218 template <
typename TIter,
typename TNextLayerUpdater>
223 TNextLayerUpdater&& nextLayerUpdater)
const
225 auto fromIter = iter;
226 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
231 using MsgPtr =
typename BaseImpl::MsgPtr;
233 !std::is_void<MsgPtr>::value,
234 "Please use update() overload that accepts message object as its first parameter");
236 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
237 return fieldUpdateInternal(msgPtr, fromIter, iter, size, field);
249 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
255 TNextLayerUpdater&& nextLayerUpdater)
const
257 auto fromIter = iter;
258 auto& thisObj = BaseImpl::thisLayer();
259 auto fieldLen = thisObj.doFieldLength(msg);
260 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
265 return fieldUpdateInternal(&msg, fromIter, iter, size, field);
278 template <
typename TMsg,
typename TIter>
281 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
293 template <
typename TMsg,
typename TIter>
296 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
310 template <
typename TMsg,
typename TIter>
311 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
313 static_cast<void>(msg);
314 checksumValid =
true;
315 return TCalc()(iter, len);
327 return field.getValue();
341 template <
typename TChecksum,
typename TMsg>
344 static_cast<void>(msg);
345 field.setValue(checksum);
349 template <
typename... TParams>
350 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
352 template <
typename... TParams>
353 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
355 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
361 TReader&& nextLayerReader,
362 TExtraValues... extraValues)
364 auto fromIter = iter;
365 auto* msgPtr = BaseImpl::toMsgPtr(msg);
366 auto fieldLen = Field::minLength();
367 auto& thisObj = BaseImpl::thisLayer();
368 if (msgPtr !=
nullptr) {
369 fieldLen = thisObj.doFieldLength(*msgPtr);
371 auto toIter = fromIter + (size - fieldLen);
372 auto len =
static_cast<std::size_t
>(std::distance(fromIter, toIter));
374 auto checksumEs = thisObj.readField(msgPtr, field, toIter, fieldLen);
375 if (checksumEs != ErrorStatus::Success) {
379 bool checksumValid =
false;
381 thisObj.calculateChecksum(
387 if (!checksumValid) {
391 auto expectedValue = thisObj.getChecksumFromField(field);
393 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
394 BaseImpl::resetMsg(msg);
395 return ErrorStatus::ProtocolError;
398 auto es = nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
399 if (es == ErrorStatus::Success) {
406 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
412 TReader&& nextLayerReader,
413 TExtraValues... extraValues)
415 auto fromIter = iter;
417 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
418 if ((es == ErrorStatus::NotEnoughData) ||
419 (es == ErrorStatus::ProtocolError)) {
423 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
425 auto remSize = size - len;
426 auto* msgPtr = BaseImpl::toMsgPtr(msg);
427 auto& thisObj = BaseImpl::thisLayer();
428 auto checksumEs = thisObj.readField(msgPtr, field, iter, remSize);
429 if (checksumEs == ErrorStatus::NotEnoughData) {
430 BaseImpl::updateMissingSize(field, remSize, extraValues...);
433 if (checksumEs != ErrorStatus::Success) {
434 BaseImpl::resetMsg(msg);
438 bool checksumValid =
false;
440 thisObj.calculateChecksum(
441 BaseImpl::toMsgPtr(msg),
446 if (!checksumValid) {
450 auto expectedValue = thisObj.getChecksumFromField(field);
452 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
453 BaseImpl::resetMsg(msg);
454 return ErrorStatus::ProtocolError;
460 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
466 TReader&& nextLayerReader,
467 VerifyBeforeReadTag<>,
468 TExtraValues... extraValues)
476 std::forward<TReader>(nextLayerReader),
480 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
486 TReader&& nextLayerReader,
487 VerifyAfterReadTag<>,
488 TExtraValues... extraValues)
496 std::forward<TReader>(nextLayerReader),
500 template <
typename TMsg,
typename TIter,
typename TWriter>
506 TWriter&& nextLayerWriter)
const
508 auto fromIter = iter;
509 auto es = nextLayerWriter.write(msg, iter, size);
516 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
517 auto remSize = size - len;
518 auto& thisObj = BaseImpl::thisLayer();
521 thisObj.prepareFieldForWrite(0, &msg, field);
522 auto esTmp = thisObj.writeField(&msg, field, iter, remSize);
530 bool checksumValid =
false;
532 thisObj.calculateChecksum(
538 if (!checksumValid) {
542 thisObj.prepareFieldForWrite(checksum, &msg, field);
543 return thisObj.writeField(&msg, field, iter, remSize);
546 template <
typename TMsg,
typename TIter,
typename TWriter>
552 TWriter&& nextLayerWriter)
const
554 auto& thisObj = BaseImpl::thisLayer();
555 auto fieldLen = thisObj.doFieldLength(msg);
556 auto es = nextLayerWriter.write(msg, iter, size - fieldLen);
562 auto esTmp = thisObj.writeField(&msg, field, iter, fieldLen);
563 static_cast<void>(esTmp);
568 template <
typename TMsg,
typename TIter,
typename TWriter>
574 TWriter&& nextLayerWriter,
575 std::random_access_iterator_tag)
const
577 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
580 template <
typename TMsg,
typename TIter,
typename TWriter>
586 TWriter&& nextLayerWriter,
587 std::output_iterator_tag)
const
589 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
592 template <
typename TMsg,
typename TIter>
593 ErrorStatus fieldUpdateInternal(
const TMsg* msgPtr, TIter from, TIter to, std::size_t size, Field& field)
const
596 auto len =
static_cast<std::size_t
>(std::distance(from, to));
597 auto& thisObj = BaseImpl::thisLayer();
598 if (msgPtr !=
nullptr) {
599 COMMS_ASSERT(len == (size - thisObj.doFieldLength(*msgPtr)));
604 auto remSize = size - len;
606 bool checksumValid =
false;
608 thisObj.calculateChecksum(
614 if (!checksumValid) {
618 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
619 return thisObj.writeField(msgPtr, field, to, remSize);