63class ChecksumLayer :
public comms::frame::details::ChecksumLayerBase<TField, TCalc, TNextLayer, TOptions...>
65 using BaseImpl = comms::frame::details::ChecksumLayerBase<TField, TCalc, TNextLayer, TOptions...>;
66 using ParsedOptionsInternal = details::ChecksumLayerOptionsParser<TOptions...>;
70 using Field =
typename BaseImpl::Field;
102 static constexpr
bool hasExtendingClass()
104 return ParsedOptionsInternal::HasExtendingClass;
111 return ParsedOptionsInternal::HasVerifyBeforeRead;
144 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
150 TNextLayerReader&& nextLayerReader,
151 TExtraValues... extraValues)
153 using IterType =
typename std::decay<
decltype(iter)>::type;
154 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
155 "The read operation is expected to use random access iterator");
158 typename comms::util::LazyShallowConditional<
159 ParsedOptionsInternal::HasVerifyBeforeRead
171 std::forward<TNextLayerReader>(nextLayerReader),
201 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
207 TNextLayerWriter&& nextLayerWriter)
const
209 using IterType =
typename std::decay<
decltype(iter)>::type;
210 using Tag =
typename std::iterator_traits<IterType>::iterator_category;
212 return writeInternal(field, msg, iter, size, std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
224 template <
typename TIter,
typename TNextLayerUpdater>
229 TNextLayerUpdater&& nextLayerUpdater)
const
231 auto fromIter = iter;
232 auto es = nextLayerUpdater.update(iter, size - Field::maxLength());
237 using MsgPtr =
typename BaseImpl::MsgPtr;
239 !std::is_void<MsgPtr>::value,
240 "Please use update() overload that accepts message object as its first parameter");
242 auto* msgPtr =
static_cast<typename MsgPtr::element_type*
>(
nullptr);
243 return fieldUpdateInternal(msgPtr, fromIter, iter, size, field);
255 template <
typename TMsg,
typename TIter,
typename TNextLayerUpdater>
261 TNextLayerUpdater&& nextLayerUpdater)
const
263 auto fromIter = iter;
264 auto& thisObj = BaseImpl::thisLayer();
265 auto fieldLen = thisObj.doFieldLength(msg);
266 auto es = nextLayerUpdater.update(msg, iter, size - fieldLen);
271 return fieldUpdateInternal(&msg, fromIter, iter, size, field);
284 template <
typename TMsg,
typename TIter>
287 return BaseImpl::thisLayer().doReadField(msgPtr, field, iter, len);
299 template <
typename TMsg,
typename TIter>
302 return BaseImpl::thisLayer().doWriteField(msgPtr, field, iter, len);
316 template <
typename TMsg,
typename TIter>
317 static auto calculateChecksum(
const TMsg* msg, TIter& iter, std::size_t len,
bool& checksumValid) ->
decltype(TCalc()(iter, len))
319 static_cast<void>(msg);
320 checksumValid =
true;
321 return TCalc()(iter, len);
333 return field.getValue();
347 template <
typename TChecksum,
typename TMsg>
350 static_cast<void>(msg);
351 field.setValue(checksum);
355 template <
typename... TParams>
356 using VerifyBeforeReadTag = comms::details::tag::Tag1<>;
358 template <
typename... TParams>
359 using VerifyAfterReadTag = comms::details::tag::Tag2<>;
361 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
367 TReader&& nextLayerReader,
368 TExtraValues... extraValues)
370 auto fromIter = iter;
371 auto* msgPtr = BaseImpl::toMsgPtr(msg);
372 auto fieldLen = Field::minLength();
373 auto& thisObj = BaseImpl::thisLayer();
374 if (msgPtr !=
nullptr) {
375 fieldLen = thisObj.doFieldLength(*msgPtr);
377 auto toIter = fromIter + (size - fieldLen);
378 auto len =
static_cast<std::size_t
>(std::distance(fromIter, toIter));
380 auto checksumEs = thisObj.readField(msgPtr, field, toIter, fieldLen);
381 if (checksumEs != ErrorStatus::Success) {
385 bool checksumValid =
false;
387 thisObj.calculateChecksum(
393 if (!checksumValid) {
397 auto expectedValue = thisObj.getChecksumFromField(field);
399 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
400 BaseImpl::resetMsg(msg);
401 return ErrorStatus::ProtocolError;
404 auto es = nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
405 if (es == ErrorStatus::Success) {
412 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
418 TReader&& nextLayerReader,
419 TExtraValues... extraValues)
421 auto fromIter = iter;
423 auto es = nextLayerReader.read(msg, iter, size, extraValues...);
424 if ((es == ErrorStatus::NotEnoughData) ||
425 (es == ErrorStatus::ProtocolError)) {
429 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
431 auto remSize = size - len;
432 auto* msgPtr = BaseImpl::toMsgPtr(msg);
433 auto& thisObj = BaseImpl::thisLayer();
434 auto checksumEs = thisObj.readField(msgPtr, field, iter, remSize);
435 if (checksumEs == ErrorStatus::NotEnoughData) {
436 BaseImpl::updateMissingSize(field, remSize, extraValues...);
439 if (checksumEs != ErrorStatus::Success) {
440 BaseImpl::resetMsg(msg);
444 bool checksumValid =
false;
446 thisObj.calculateChecksum(
447 BaseImpl::toMsgPtr(msg),
452 if (!checksumValid) {
456 auto expectedValue = thisObj.getChecksumFromField(field);
458 if (expectedValue !=
static_cast<decltype(expectedValue)
>(checksum)) {
459 BaseImpl::resetMsg(msg);
460 return ErrorStatus::ProtocolError;
466 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
472 TReader&& nextLayerReader,
473 VerifyBeforeReadTag<>,
474 TExtraValues... extraValues)
482 std::forward<TReader>(nextLayerReader),
486 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
492 TReader&& nextLayerReader,
493 VerifyAfterReadTag<>,
494 TExtraValues... extraValues)
502 std::forward<TReader>(nextLayerReader),
506 template <
typename TMsg,
typename TIter,
typename TWriter>
512 TWriter&& nextLayerWriter)
const
514 auto fromIter = iter;
515 auto es = nextLayerWriter.write(msg, iter, size);
522 auto len =
static_cast<std::size_t
>(std::distance(fromIter, iter));
523 auto remSize = size - len;
524 auto& thisObj = BaseImpl::thisLayer();
527 thisObj.prepareFieldForWrite(0, &msg, field);
528 auto esTmp = thisObj.writeField(&msg, field, iter, remSize);
536 bool checksumValid =
false;
538 thisObj.calculateChecksum(
544 if (!checksumValid) {
548 thisObj.prepareFieldForWrite(checksum, &msg, field);
549 return thisObj.writeField(&msg, field, iter, remSize);
552 template <
typename TMsg,
typename TIter,
typename TWriter>
558 TWriter&& nextLayerWriter)
const
560 auto& thisObj = BaseImpl::thisLayer();
561 auto fieldLen = thisObj.doFieldLength(msg);
562 auto es = nextLayerWriter.write(msg, iter, size - fieldLen);
568 auto esTmp = thisObj.writeField(&msg, field, iter, fieldLen);
569 static_cast<void>(esTmp);
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>
599 ErrorStatus fieldUpdateInternal(
const TMsg* msgPtr, TIter from, TIter to, std::size_t size, Field& field)
const
602 auto len =
static_cast<std::size_t
>(std::distance(from, to));
603 auto& thisObj = BaseImpl::thisLayer();
604 if (msgPtr !=
nullptr) {
605 COMMS_ASSERT(len == (size - thisObj.doFieldLength(*msgPtr)));
610 auto remSize = size - len;
612 bool checksumValid =
false;
614 thisObj.calculateChecksum(
620 if (!checksumValid) {
624 thisObj.prepareFieldForWrite(checksum, msgPtr, field);
625 return thisObj.writeField(msgPtr, field, to, remSize);