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;
98 static constexpr
bool hasExtendingClass()
100 return ParsedOptionsInternal::HasExtendingClass;
107 return ParsedOptionsInternal::HasVerifyBeforeRead;
140 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
146 TNextLayerReader&& nextLayerReader,
147 TExtraValues... extraValues)
149 using IterType =
typename std::decay<
decltype(iter)>::type;
150 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
151 "The read operation is expected to use random access iterator");
153 auto* msgPtr = BaseImpl::toMsgPtr(msg);
154 auto& thisObj = BaseImpl::thisLayer();
155 auto beforeFieldReadIter = iter;
156 auto checksumEs = thisObj.readField(msgPtr, field, iter, size);
157 if (checksumEs == ErrorStatus::NotEnoughData) {
158 BaseImpl::updateMissingSize(field, size, extraValues...);
161 if (checksumEs != ErrorStatus::Success) {
166 typename comms::util::LazyShallowConditional<
167 ParsedOptionsInternal::HasVerifyBeforeRead
173 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeFieldReadIter, iter));
180 std::forward<TNextLayerReader>(nextLayerReader),
212 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
218 TNextLayerWriter&& nextLayerWriter)
const
220 using IterType =
typename std::decay<
decltype(iter)>::type;
221 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
223 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
235 template <
typename TIter,
typename TNextLayerUpdater>
240 TNextLayerUpdater&& nextLayerUpdater)
const
242 auto checksumIter = iter;
243 std::advance(iter, Field::maxLength());
245 auto fromIter = iter;
246 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
251 using MsgPtr =
typename BaseImpl::MsgPtr;
253 !std::is_void<MsgPtr>::value,
254 "Please use update() overload that accepts message object as its first parameter");
256 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
257 return fieldUpdateInternal(msgPtr, checksumIter, fromIter, iter, size, field);
271 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
277 TNextLayerUpdater&& nextLayerUpdater)
const
279 auto& thisObj = BaseImpl::thisLayer();
280 auto checksumIter = iter;
281 auto fieldLen = thisObj.doFieldLength(msg);
282 std::advance(iter, fieldLen);
284 auto fromIter = iter;
285 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
290 return fieldUpdateInternal(&msg, checksumIter, fromIter, iter, size, field);
303 template <
typename TMsg,
typename TIter>
306 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
318 template <
typename TMsg,
typename TIter>
321 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
335 template <
typename TMsg,
typename TIter>
336 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
338 static_cast<void>(msg);
339 checksumValid =
true;
340 return TCalc()(iter, len);
352 return field.getValue();
366 template <
typename TChecksum,
typename TMsg>
369 static_cast<void>(msg);
370 field.setValue(checksum);
375 template <
typename... TParams>
376 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
378 template <
typename... TParams>
379 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
381 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
387 TReader&& nextLayerReader,
388 TExtraValues... extraValues)
390 auto fromIter = iter;
391 auto& thisObj = BaseImpl::thisLayer();
392 auto* msgPtr = BaseImpl::toMsgPtr(msg);
394 bool checksumValid =
false;
396 thisObj.calculateChecksum(
402 if (!checksumValid) {
406 auto expectedValue = thisObj.getChecksumFromField(field);
407 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
408 BaseImpl::resetMsg(msg);
409 return ErrorStatus::ProtocolError;
412 return nextLayerReader.read(msg, iter, size, extraValues...);
415 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
421 TReader&& nextLayerReader,
422 TExtraValues... extraValues)
424 auto fromIter = iter;
426 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
427 if ((es == ErrorStatus::NotEnoughData) ||
428 (es == ErrorStatus::ProtocolError)) {
432 auto* msgPtr = BaseImpl::toMsgPtr(msg);
433 auto& thisObj = BaseImpl::thisLayer();
434 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
435 bool checksumValid =
false;
437 thisObj.calculateChecksum(
443 if (!checksumValid) {
447 auto expectedValue = thisObj.getChecksumFromField(field);
448 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
449 BaseImpl::resetMsg(msg);
450 return ErrorStatus::ProtocolError;
456 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
462 TReader&& nextLayerReader,
463 VerifyBeforeReadTag<>,
464 TExtraValues... extraValues)
472 std::forward<TReader>(nextLayerReader),
476 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
482 TReader&& nextLayerReader,
483 VerifyAfterReadTag<>,
484 TExtraValues... extraValues)
492 std::forward<TReader>(nextLayerReader),
496 template <
typename TMsg,
typename TIter,
typename TWriter>
502 TWriter&& nextLayerWriter)
const
504 auto& thisObj = BaseImpl::thisLayer();
505 auto checksumIter = iter;
506 thisObj.prepareFieldForWrite(0U, &msg, field);
507 auto es = thisObj.writeField(&msg, field, iter, size);
513 static_cast<std::size_t
>(std::distance(checksumIter, iter));
515 auto fromIter = iter;
516 es = nextLayerWriter.write(msg, iter, size - checksumLen);
522 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
524 bool checksumValid =
false;
526 thisObj.calculateChecksum(
532 if (!checksumValid) {
536 thisObj.prepareFieldForWrite(checksum, &msg, field);
537 auto checksumEs = thisObj.writeField(&msg, field, checksumIter, checksumLen);
538 static_cast<void>(checksumEs);
543 template <
typename TMsg,
typename TIter,
typename TWriter>
549 TWriter&& nextLayerWriter)
const
551 auto& thisObj = BaseImpl::thisLayer();
552 thisObj.prepareFieldForWrite(0U, &msg, field);
553 auto es = thisObj.writeField(&msg, field, iter, size);
558 auto fieldLen = thisObj.doFieldLength(msg);
559 es = nextLayerWriter.write(msg, iter, size - fieldLen);
567 template <
typename TMsg,
typename TIter,
typename TWriter>
573 TWriter&& nextLayerWriter,
574 std::random_access_iterator_tag)
const
576 return writeInternalRandomAccess(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
579 template <
typename TMsg,
typename TIter,
typename TWriter>
585 TWriter&& nextLayerWriter,
586 std::output_iterator_tag)
const
588 return writeInternalOutput(field, msg, iter, size, std::forward<TWriter>(nextLayerWriter));
591 template <
typename TMsg,
typename TIter>
600 static_cast<void>(size);
602 auto& thisObj = BaseImpl::thisLayer();
603 auto len =
static_cast<std::size_t
>(std::distance(from, to));
604 auto fieldLen = Field::maxLength();
605 if (msgPtr !=
nullptr) {
606 fieldLen = thisObj.doFieldLength(*msgPtr);
610 bool checksumValid =
false;
612 thisObj.calculateChecksum(
618 if (!checksumValid) {
622 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
623 return thisObj.doWriteField(msgPtr, field, checksumIter, fieldLen);