67class ChecksumLayer :
public comms::frame::details::ChecksumLayerBase<TField, TCalc, TNextLayer, TOptions...>
69 using BaseImpl = comms::frame::details::ChecksumLayerBase<TField, TCalc, TNextLayer, TOptions...>;
70 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
74 using Field =
typename BaseImpl::Field;
99 static constexpr
bool hasExtendingClass()
101 return ParsedOptionsInternal::HasExtendingClass;
108 return ParsedOptionsInternal::HasVerifyBeforeRead;
141 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
147 TNextLayerReader&& nextLayerReader,
148 TExtraValues... extraValues)
150 using IterType =
typename std::decay<
decltype(iter)>::type;
151 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
152 "The read operation is expected to use random access iterator");
155 typename comms::util::LazyShallowConditional<
156 ParsedOptionsInternal::HasVerifyBeforeRead
168 std::forward<TNextLayerReader>(nextLayerReader),
198 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
204 TNextLayerWriter&& nextLayerWriter)
const
206 using IterType =
typename std::decay<
decltype(iter)>::type;
207 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
209 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
221 template <
typename TIter,
typename TNextLayerUpdater>
226 TNextLayerUpdater&& nextLayerUpdater)
const
228 auto fromIter = iter;
229 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
234 using MsgPtr =
typename BaseImpl::MsgPtr;
236 !std::is_void<MsgPtr>::value,
237 "Please use update() overload that accepts message object as its first parameter");
239 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
240 return fieldUpdateInternal(msgPtr, fromIter, iter, size, field);
252 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
258 TNextLayerUpdater&& nextLayerUpdater)
const
260 auto fromIter = iter;
261 auto& thisObj = BaseImpl::thisLayer();
262 auto fieldLen = thisObj.doFieldLength(msg);
263 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
268 return fieldUpdateInternal(&msg, fromIter, iter, size, field);
281 template <
typename TMsg,
typename TIter>
284 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
296 template <
typename TMsg,
typename TIter>
299 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
313 template <
typename TMsg,
typename TIter>
314 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
316 static_cast<void>(msg);
317 checksumValid =
true;
318 return TCalc()(iter, len);
330 return field.getValue();
344 template <
typename TChecksum,
typename TMsg>
347 static_cast<void>(msg);
348 field.setValue(checksum);
352 template <
typename... TParams>
353 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
355 template <
typename... TParams>
356 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
358 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
364 TReader&& nextLayerReader,
365 TExtraValues... extraValues)
367 auto fromIter = iter;
368 auto* msgPtr = BaseImpl::toMsgPtr(msg);
369 auto fieldLen = Field::minLength();
370 auto& thisObj = BaseImpl::thisLayer();
371 if (msgPtr !=
nullptr) {
372 fieldLen = thisObj.doFieldLength(*msgPtr);
374 auto toIter = fromIter + (size - fieldLen);
375 auto len =
static_cast<std::size_t
>(std::distance(fromIter, toIter));
377 auto checksumEs = thisObj.readField(msgPtr, field, toIter, fieldLen);
378 if (checksumEs != ErrorStatus::Success) {
382 bool checksumValid =
false;
384 thisObj.calculateChecksum(
390 if (!checksumValid) {
394 auto expectedValue = thisObj.getChecksumFromField(field);
396 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
397 BaseImpl::resetMsg(msg);
398 return ErrorStatus::ProtocolError;
401 auto es = nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
402 if (es == ErrorStatus::Success) {
409 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
415 TReader&& nextLayerReader,
416 TExtraValues... extraValues)
418 auto fromIter = iter;
420 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
421 if ((es == ErrorStatus::NotEnoughData) ||
422 (es == ErrorStatus::ProtocolError)) {
426 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
428 auto remSize = size - len;
429 auto* msgPtr = BaseImpl::toMsgPtr(msg);
430 auto& thisObj = BaseImpl::thisLayer();
431 auto checksumEs = thisObj.readField(msgPtr, field, iter, remSize);
432 if (checksumEs == ErrorStatus::NotEnoughData) {
433 BaseImpl::updateMissingSize(field, remSize, extraValues...);
436 if (checksumEs != ErrorStatus::Success) {
437 BaseImpl::resetMsg(msg);
441 bool checksumValid =
false;
443 thisObj.calculateChecksum(
444 BaseImpl::toMsgPtr(msg),
449 if (!checksumValid) {
453 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 fromIter = iter;
512 auto es = nextLayerWriter.write(msg, iter, size);
519 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
520 auto remSize = size - len;
521 auto& thisObj = BaseImpl::thisLayer();
524 thisObj.prepareFieldForWrite(0, &msg, field);
525 auto esTmp = thisObj.writeField(&msg, field, iter, remSize);
533 bool checksumValid =
false;
535 thisObj.calculateChecksum(
541 if (!checksumValid) {
545 thisObj.prepareFieldForWrite(checksum, &msg, field);
546 return thisObj.writeField(&msg, field, iter, remSize);
549 template <
typename TMsg,
typename TIter,
typename TWriter>
555 TWriter&& nextLayerWriter)
const
557 auto& thisObj = BaseImpl::thisLayer();
558 auto fieldLen = thisObj.doFieldLength(msg);
559 auto es = nextLayerWriter.write(msg, iter, size - fieldLen);
565 auto esTmp = thisObj.writeField(&msg, field, iter, fieldLen);
566 static_cast<void>(esTmp);
571 template <
typename TMsg,
typename TIter,
typename TWriter>
577 TWriter&& nextLayerWriter,
578 std::random_access_iterator_tag)
const
580 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
583 template <
typename TMsg,
typename TIter,
typename TWriter>
589 TWriter&& nextLayerWriter,
590 std::output_iterator_tag)
const
592 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
595 template <
typename TMsg,
typename TIter>
596 ErrorStatus fieldUpdateInternal(
const TMsg* msgPtr, TIter from, TIter to, std::size_t size, Field& field)
const
599 auto len =
static_cast<std::size_t
>(std::distance(from, to));
600 auto& thisObj = BaseImpl::thisLayer();
601 if (msgPtr !=
nullptr) {
602 COMMS_ASSERT(len == (size - thisObj.doFieldLength(*msgPtr)));
607 auto remSize = size - len;
609 bool checksumValid =
false;
611 thisObj.calculateChecksum(
617 if (!checksumValid) {
621 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
622 return thisObj.writeField(msgPtr, field, to, remSize);