COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
MsgIdLayer.h
Go to the documentation of this file.
1//
2// Copyright 2014 - 2025 (C). Alex Robenko. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
10
11#pragma once
12
13#include "comms/Assert.h"
15#include "comms/details/tag.h"
16#include "comms/dispatch.h"
17#include "comms/fields.h"
18#include "comms/frame/details/MsgIdLayerBase.h"
19#include "comms/frame/details/MsgIdLayerOptionsParser.h"
20#include "comms/MessageBase.h"
21#include "comms/MsgFactory.h"
22#include "comms/util/Tuple.h"
24
25#include <algorithm>
26#include <array>
27#include <iterator>
28#include <limits>
29#include <tuple>
30#include <utility>
31
32COMMS_MSVC_WARNING_PUSH
33COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
34COMMS_MSVC_WARNING_DISABLE(4189) // Disable erroneous initialized but not referenced variable warning
35
36namespace comms
37{
38
39namespace frame
40{
41
66template <typename TField,
67 typename TMessage,
68 typename TAllMessages,
69 typename TNextLayer,
70 typename... TOptions>
71class MsgIdLayer : public comms::frame::details::MsgIdLayerBase<TField, TMessage, TAllMessages, TNextLayer, TOptions...>
72{
74 "TAllMessages must be of std::tuple type");
75
76 static_assert(TMessage::hasMsgIdType(),
77 "Usage of MsgIdLayer requires support for ID type. "
78 "Use comms::option::def::MsgIdType option in message interface type definition.");
79
80 using BaseImpl = comms::frame::details::MsgIdLayerBase<TField, TMessage, TAllMessages, TNextLayer, TOptions...>;
81 using ParsedOptionsInternal = details::MsgIdLayerOptionsParser<TOptions...>;
82
83public:
85 using MsgFactory = typename ParsedOptionsInternal::template MsgFactory<TMessage, TAllMessages>;
86
88 using AllMessages = TAllMessages;
89
92 using MsgPtr = typename MsgFactory::MsgPtr;
93
95 using Message = TMessage;
96
98 using MsgIdType = typename Message::MsgIdType;
99
102
104 using Field = typename BaseImpl::Field;
105
108
110 explicit MsgIdLayer() = default;
111
113 MsgIdLayer(const MsgIdLayer&) = default;
114
116 MsgIdLayer(MsgIdLayer&&) = default;
117
119 MsgIdLayer& operator=(const MsgIdLayer&) = default;
120
123
125 ~MsgIdLayer() noexcept = default;
126
129 static constexpr bool hasExtendingClass()
130 {
131 return ParsedOptionsInternal::HasExtendingClass;
132 }
133
137 static constexpr bool hasMsgFactory()
138 {
139 return ParsedOptionsInternal::HasMsgFactory;
140 }
141
180 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
182 Field& field,
183 TMsg& msg,
184 TIter& iter,
185 std::size_t size,
186 TNextLayerReader&& nextLayerReader,
187 TExtraValues... extraValues)
188 {
189 auto beforeReadIter = iter;
190 auto& thisObj = BaseImpl::thisLayer();
191 auto* msgPtr = BaseImpl::toMsgPtr(msg);
192 auto es = thisObj.doReadField(msgPtr, field, iter, size);
194 BaseImpl::updateMissingSize(field, size, extraValues...);
195 }
196
197 if (es != ErrorStatus::Success) {
198 return es;
199 }
200
201 auto fieldLen = static_cast<std::size_t>(std::distance(beforeReadIter, iter));
202
203 using Tag =
204 typename comms::util::LazyShallowConditional<
205 comms::isMessage<typename std::decay<decltype(msg)>::type>()
206 >::template Type<
207 DirectOpTag,
208 PointerOpTag
209 >;
210
211 return
212 doReadInternal(
213 field,
214 msg,
215 iter,
216 size - fieldLen,
217 std::forward<TNextLayerReader>(nextLayerReader),
218 Tag(),
219 extraValues...);
220 }
221
248 template <typename TMsg, typename TIter, typename TNextLayerWriter>
250 Field& field,
251 const TMsg& msg,
252 TIter& iter,
253 std::size_t size,
254 TNextLayerWriter&& nextLayerWriter) const
255 {
256 auto& thisObj = BaseImpl::thisLayer();
257 using MsgType = typename std::decay<decltype(msg)>::type;
258 static_assert(comms::isMessage<MsgType>(), "The message type must extend comms::Message");
259 thisObj.prepareFieldForWrite(
260 getMsgId(msg, IdRetrieveTag<MsgType>()),
261 msg,
262 field);
263
264 auto es = thisObj.doWriteField(&msg, field, iter, size);
265 if (es != ErrorStatus::Success) {
266 return es;
267 }
268
269 COMMS_ASSERT(field.length() <= size);
270
271 using Tag =
272 typename comms::util::LazyShallowConditional<
273 comms::isMessageBase<MsgType>() || MsgType::hasWrite()
274 >::template Type<
275 DirectOpTag,
276 StaticBinSearchOpTag
277 >;
278
279 return writeInternal(field, msg, iter, size - field.length(), std::forward<TNextLayerWriter>(nextLayerWriter), Tag());
280 }
281
292 MsgPtr createMsg(MsgIdParamType id, unsigned idx = 0, CreateFailureReason* reason = nullptr)
293 {
294 return m_factory.createMsg(id, idx, reason);
295 }
296
299 static constexpr bool isDispatchPolymorphic()
300 {
301 return MsgFactory::isDispatchPolymorphic();
302 }
303
306 static constexpr bool isDispatchStaticBinSearch()
307 {
308 return MsgFactory::isDispatchStaticBinSearch();
309 }
310
313 static constexpr bool isDispatchLinearSwitch()
314 {
315 return MsgFactory::isDispatchLinearSwitch();
316 }
317
318protected:
319
324 static MsgIdType getMsgIdFromField(const Field& field)
325 {
326 return static_cast<MsgIdType>(field.getValue());
327 }
328
339 template <typename TMsg>
340 static void beforeRead(const Field& field, TMsg& msg)
341 {
342 static_cast<void>(field);
343 static_cast<void>(msg);
344 }
345
353 template <typename TMsg>
354 static void prepareFieldForWrite(MsgIdParamType id, const TMsg& msg, Field& field)
355 {
356 static_cast<void>(msg);
357 static_cast<void>(field);
358 field.setValue(id);
359 }
360
361private:
362
363 template <typename... TParams>
364 using PolymorphicOpTag = comms::details::tag::Tag1<>;
365
366 template <typename... TParams>
367 using DirectOpTag = comms::details::tag::Tag2<>;
368
369 template <typename... TParams>
370 using PointerOpTag = comms::details::tag::Tag3<>;
371
372 template <typename... TParams>
373 using StaticBinSearchOpTag = comms::details::tag::Tag4<>;
374
375 template <typename TMsg>
376 using IdRetrieveTag =
377 typename comms::util::LazyShallowConditional<
378 comms::isMessageBase<TMsg>()
379 >::template Type<
380 DirectOpTag,
381 PolymorphicOpTag
382 >;
383
384 template <typename... TParams>
385 using IdParamAsIsTag = comms::details::tag::Tag5<>;
386
387 template <typename... TParams>
388 using IdParamCastTag = comms::details::tag::Tag6<>;
389
390 template <typename TId>
391 using IdParamTag =
392 typename comms::util::LazyShallowConditional<
393 std::is_base_of<MsgIdType, TId>::value
394 >::template Type<
395 IdParamAsIsTag,
396 IdParamCastTag
397 >;
398
399 template <typename... TParams>
400 using HasGenericMsgTag = comms::details::tag::Tag7<>;
401
402 template <typename... TParams>
403 using NoGenericMsgTag = comms::details::tag::Tag8<>;
404
405 template <typename TIter, typename TNextLayerReader, typename... TExtraValues>
406 class ReadRedirectionHandler
407 {
408 public:
409 using RetType = comms::ErrorStatus;
410
411 ReadRedirectionHandler(
412 TIter& iter,
413 std::size_t size,
414 TNextLayerReader&& nextLayerReader,
415 TExtraValues... extraValues)
416 : m_iter(iter),
417 m_size(size),
418 m_nextLayerReader(std::forward<TNextLayerReader>(nextLayerReader)),
419 m_extraValues(extraValues...)
420 {
421 }
422
423 template <typename TMsg>
424 RetType handle(TMsg& msg)
425 {
426 static_assert(comms::isMessageBase<TMsg>(), "Expected to be a valid message object");
427 return handleInternal(msg, m_extraValues);
428 }
429
430 RetType handle(TMessage& msg)
431 {
432 static_cast<void>(msg);
433 static constexpr bool Should_not_happen = false;
434 static_cast<void>(Should_not_happen);
435 COMMS_ASSERT(Should_not_happen);
437 }
438
439 private:
440 template <typename TMsg>
441 RetType handleInternal(TMsg& msg, std::tuple<>&)
442 {
443 return m_nextLayerReader.read(msg, m_iter, m_size);
444 }
445
446 template <typename TMsg, typename T0>
447 RetType handleInternal(TMsg& msg, std::tuple<T0>& extraValues)
448 {
449 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues));
450 }
451
452 template <typename TMsg, typename T0, typename T1>
453 RetType handleInternal(TMsg& msg, std::tuple<T0, T1>& extraValues)
454 {
455 return m_nextLayerReader.read(msg, m_iter, m_size, std::get<0>(extraValues), std::get<1>(extraValues));
456 }
457
458 template <typename TMsg, typename T0, typename T1, typename T2>
459 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2>& extraValues)
460 {
461 return
462 m_nextLayerReader.read(
463 msg,
464 m_iter,
465 m_size,
466 std::get<0>(extraValues),
467 std::get<1>(extraValues),
468 std::get<2>(extraValues));
469 }
470
471 template <typename TMsg, typename T0, typename T1, typename T2, typename T3>
472 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3>& extraValues)
473 {
474 return
475 m_nextLayerReader.read(
476 msg,
477 m_iter,
478 m_size,
479 std::get<0>(extraValues),
480 std::get<1>(extraValues),
481 std::get<2>(extraValues),
482 std::get<3>(extraValues));
483 }
484
485 template <typename TMsg, typename T0, typename T1, typename T2, typename T3, typename T4>
486 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4>& extraValues)
487 {
488 return
489 m_nextLayerReader.read(
490 msg,
491 m_iter,
492 m_size,
493 std::get<0>(extraValues),
494 std::get<1>(extraValues),
495 std::get<2>(extraValues),
496 std::get<3>(extraValues),
497 std::get<4>(extraValues));
498 }
499
500 template <typename TMsg, typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
501 RetType handleInternal(TMsg& msg, std::tuple<T0, T1, T2, T3, T4, T5>& extraValues)
502 {
503 return
504 m_nextLayerReader.read(
505 msg,
506 m_iter,
507 m_size,
508 std::get<0>(extraValues),
509 std::get<1>(extraValues),
510 std::get<2>(extraValues),
511 std::get<3>(extraValues),
512 std::get<4>(extraValues),
513 std::get<5>(extraValues));
514 }
515
516 TIter& m_iter;
517 std::size_t m_size = 0U;
518 TNextLayerReader&& m_nextLayerReader;
519 std::tuple<TExtraValues...> m_extraValues;
520 };
521
522 template <typename TIter, typename TNextLayerReader, typename... TExtraValues>
523 ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...> makeReadRedirectionHandler(
524 TIter& iter,
525 std::size_t size,
526 TNextLayerReader&& nextLayerReader,
527 TExtraValues... extraValues)
528 {
529 return ReadRedirectionHandler<TIter, TNextLayerReader, TExtraValues...>(iter, size, std::forward<TNextLayerReader>(nextLayerReader), extraValues...);
530 }
531
532 template <typename TIter, typename TNextLayerWriter>
533 class WriteRedirectionHandler
534 {
535 public:
536 using RetType = comms::ErrorStatus;
537
538 WriteRedirectionHandler(
539 TIter& iter,
540 std::size_t size,
541 TNextLayerWriter&& nextLayerWriter)
542 : m_iter(iter),
543 m_size(size),
544 m_nextLayerWriter(std::forward<TNextLayerWriter>(nextLayerWriter))
545 {
546 }
547
548 template <typename TMsg>
549 RetType handle(const TMsg& msg)
550 {
551 static_assert(comms::isMessageBase<TMsg>(), "Expected to be a valid message object");
552 return m_nextLayerWriter.write(msg, m_iter, m_size);
553 }
554
555 RetType handle(const TMessage& msg)
556 {
557 static_cast<void>(msg);
558 static constexpr bool Should_not_happen = false;
559 static_cast<void>(Should_not_happen);
560 COMMS_ASSERT(Should_not_happen);
562 }
563
564 private:
565 TIter& m_iter;
566 std::size_t m_size = 0U;
567 TNextLayerWriter&& m_nextLayerWriter;
568 };
569
570 template <typename TIter, typename TNextLayerWriter>
571 WriteRedirectionHandler<TIter, TNextLayerWriter> makeWriteRedirectionHandler(
572 TIter& iter,
573 std::size_t size,
574 TNextLayerWriter&& nextLayerWriter)
575 {
576 return WriteRedirectionHandler<TIter, TNextLayerWriter>(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
577 }
578
579 template <typename TMsg, typename... TParams>
580 static MsgIdParamType getMsgId(const TMsg& msg, PolymorphicOpTag<TParams...>)
581 {
582 using MsgType = typename std::decay<decltype(msg)>::type;
583 static_assert(comms::isMessage<MsgType>(),
584 "The message class is expected to inherit from comms::Message");
585 static_assert(MsgType::hasGetId(),
586 "The message interface class must expose polymorphic ID retrieval functionality, "
587 "use comms::option::app::IdInfoInterface option to define it.");
588
589 return msg.getId();
590 }
591
592 template <typename TMsg, typename... TParams>
593 static constexpr MsgIdParamType getMsgId(const TMsg& msg, DirectOpTag<TParams...>)
594 {
595 using MsgType = typename std::decay<decltype(msg)>::type;
596 static_assert(comms::isMessageBase<MsgType>(),
597 "The message class is expected to inherit from comms::MessageBase");
598 static_assert(MsgType::hasDoGetId(),
599 "The message class must expose direct ID retrieval functionality, "
600 "use comms::option::app::StaticNumIdImpl option to define it or "
601 "comms::option::app::HasDoGetId option to mark the class as providing one");
602 return msg.doGetId();
603 }
604
605 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
606 comms::ErrorStatus doReadInternalDirect(
607 Field& field,
608 TMsg& msg,
609 TIter& iter,
610 std::size_t size,
611 TNextLayerReader&& nextLayerReader,
612 TExtraValues... extraValues)
613 {
614 static_assert((!details::hasMsgIndexRetriever<TExtraValues...>()) || (comms::details::allMessagesAreStrongSorted<AllMessages>()),
615 "Message type index cannot be retrieved with direct message object invocation");
616 auto& thisObj = BaseImpl::thisLayer();
617 auto id = thisObj.getMsgIdFromField(field);
618 BaseImpl::setMsgId(id, extraValues...);
619 BaseImpl::setMsgIndex(0U, extraValues...);
620
621 using MsgType = typename std::decay<decltype(msg)>::type;
622 if (id != getMsgId(msg, IdRetrieveTag<MsgType>())) {
623 return ErrorStatus::InvalidMsgId;
624 }
625
626 thisObj.beforeRead(field, msg);
627 return nextLayerReader.read(msg, iter, size, extraValues...);
628 }
629
630 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
631 comms::ErrorStatus doReadInternal(
632 MsgIdParamType id,
633 unsigned idx,
634 TMsg& msg,
635 TIter& iter,
636 std::size_t size,
637 TNextLayerReader&& nextLayerReader,
638 PolymorphicOpTag<>,
639 TExtraValues... extraValues)
640 {
641 static_cast<void>(id);
642 static_cast<void>(idx);
643 return nextLayerReader.read(msg, iter, size, extraValues...);
644 }
645
646 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
647 comms::ErrorStatus doReadInternal(
648 Field& field,
649 TMsg& msg,
650 TIter& iter,
651 std::size_t size,
652 TNextLayerReader&& nextLayerReader,
653 DirectOpTag<>,
654 TExtraValues... extraValues)
655 {
656 return
657 doReadInternalDirect(
658 field,
659 msg,
660 iter,
661 size,
662 std::forward<TNextLayerReader>(nextLayerReader),
663 extraValues...);
664 }
665
666 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
667 comms::ErrorStatus doReadInternal(
668 Field& field,
669 TMsg& msg,
670 TIter& iter,
671 std::size_t size,
672 TNextLayerReader&& nextLayerReader,
673 PointerOpTag<>,
674 TExtraValues... extraValues)
675 {
676 using MsgType = typename std::decay<decltype(msg)>::type;
677 static_assert(comms::details::hasElementType<MsgType>(),
678 "Unsupported type of message object, expected to be either message itself or smart pointer");
679
680 using MsgElementType = typename MsgType::element_type;
681
682 using Tag =
683 typename comms::util::LazyShallowConditional<
684 MsgElementType::hasRead()
685 >::template Type<
686 PolymorphicOpTag,
687 StaticBinSearchOpTag
688 >;
689
690 auto& thisObj = BaseImpl::thisLayer();
691 const auto id = thisObj.getMsgIdFromField(field);
692 BaseImpl::setMsgId(id, extraValues...);
693
695 unsigned idx = 0;
696 CreateFailureReason failureReason = CreateFailureReason::None;
697 while (true) {
698 COMMS_ASSERT(!msg);
699 msg = createMsgInternal(id, idx, &failureReason);
700 if (!msg) {
701 break;
702 }
703
704 using IterType = typename std::decay<decltype(iter)>::type;
705 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
706 "Iterator used for reading is expected to be random access one");
707 IterType readStart = iter;
708
709 thisObj.beforeRead(field, *msg);
710 es = doReadInternal(id, idx, msg, iter, size, std::forward<TNextLayerReader>(nextLayerReader), Tag(), extraValues...);
711 if (es == comms::ErrorStatus::Success) {
712 BaseImpl::setMsgIndex(idx, extraValues...);
713 return es;
714 }
715
716 msg.reset();
717 iter = readStart;
718 ++idx;
719 }
720
721 BaseImpl::setMsgIndex(idx, extraValues...);
722 COMMS_ASSERT(!msg);
723 if (failureReason == CreateFailureReason::AllocFailure) {
725 }
726
727 COMMS_ASSERT(failureReason == CreateFailureReason::InvalidId);
728 using GenericMsgTag =
729 typename comms::util::LazyShallowConditional<
730 MsgFactory::hasGenericMessageSupport()
731 >::template Type<
732 HasGenericMsgTag,
733 NoGenericMsgTag
734 >;
735
736 return
737 createAndReadGenericMsgInternal(
738 field,
739 idx,
740 msg,
741 iter,
742 size,
743 std::forward<TNextLayerReader>(nextLayerReader),
744 es,
745 GenericMsgTag(),
746 extraValues...);
747 }
748
749 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
750 comms::ErrorStatus doReadInternal(
751 MsgIdParamType id,
752 unsigned idx,
753 TMsg& msg,
754 TIter& iter,
755 std::size_t size,
756 TNextLayerReader&& nextLayerReader,
757 StaticBinSearchOpTag<>,
758 TExtraValues... extraValues)
759 {
760 auto handler =
761 makeReadRedirectionHandler(
762 iter,
763 size,
764 std::forward<TNextLayerReader>(nextLayerReader),
765 extraValues...);
766 return comms::dispatchMsgStaticBinSearch<AllMessages>(id, idx, *msg, handler);
767 }
768
769 template <typename TId, typename... TParams>
770 MsgPtr createMsgInternalTagged(TId&& id, unsigned idx, CreateFailureReason* reason, IdParamAsIsTag<TParams...>)
771 {
772 return createMsg(std::forward<TId>(id), idx, reason);
773 }
774
775 template <typename TId, typename... TParams>
776 MsgPtr createMsgInternalTagged(TId&& id, unsigned idx, CreateFailureReason* reason, IdParamCastTag<TParams...>)
777 {
778 return createMsg(static_cast<MsgIdType>(id), idx, reason);
779 }
780
781 template <typename TId>
782 MsgPtr createMsgInternal(TId&& id, unsigned idx, CreateFailureReason* reason)
783 {
784 using IdType = typename std::decay<decltype(id)>::type;
785 return createMsgInternalTagged(std::forward<TId>(id), idx, reason, IdParamTag<IdType>());
786 }
787
788 template <typename TId, typename... TParams>
789 MsgPtr createGenericMsgInternalTagged(TId&& id, unsigned idx, IdParamAsIsTag<TParams...>)
790 {
791 return m_factory.createGenericMsg(std::forward<TId>(id), idx);
792 }
793
794 template <typename TId, typename... TParams>
795 MsgPtr createGenericMsgInternalTagged(TId&& id, unsigned idx, IdParamCastTag<TParams...>)
796 {
797 return m_factory.createGenericMsg(static_cast<MsgIdType>(id), idx);
798 }
799
800 template <typename TId>
801 MsgPtr createGenericMsgInternal(TId&& id, unsigned idx)
802 {
803 using IdType = typename std::decay<decltype(id)>::type;
804 return createGenericMsgInternalTagged(std::forward<TId>(id), idx, IdParamTag<IdType>());
805 }
806
807 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
808 comms::ErrorStatus createAndReadGenericMsgInternal(
809 const Field& field,
810 unsigned msgIdx,
811 TMsg& msg,
812 TIter& iter,
813 std::size_t size,
814 TNextLayerReader&& nextLayerReader,
816 NoGenericMsgTag<>,
817 TExtraValues...)
818 {
819 static_cast<void>(field);
820 static_cast<void>(msgIdx);
821 static_cast<void>(msg);
822 static_cast<void>(iter);
823 static_cast<void>(size);
824 static_cast<void>(nextLayerReader);
825 return es;
826 }
827
828 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
829 comms::ErrorStatus createAndReadGenericMsgInternal(
830 const Field& field,
831 unsigned msgIdx,
832 TMsg& msg,
833 TIter& iter,
834 std::size_t size,
835 TNextLayerReader&& nextLayerReader,
837 HasGenericMsgTag<>,
838 TExtraValues... extraValues)
839 {
840 using GenericMsgType = typename MsgFactory::GenericMessage;
841
842 auto& thisObj = BaseImpl::thisLayer();
843 auto id = thisObj.getMsgIdFromField(field);
844 msg = createGenericMsgInternal(id, msgIdx);
845 if (!msg) {
846 return es;
847 }
848
849 thisObj.beforeRead(field, *msg);
850
851 using Tag =
852 typename comms::util::LazyShallowConditional<
853 GenericMsgType::hasRead()
854 >::template Type<
855 PolymorphicOpTag,
856 DirectOpTag
857 >;
858
859 return
860 readGenericMsg(
861 msg,
862 iter,
863 size,
864 std::forward<TNextLayerReader>(nextLayerReader),
865 Tag(),
866 extraValues...);
867 }
868
869 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
870 comms::ErrorStatus readGenericMsg(
871 TMsg& msg,
872 TIter& iter,
873 std::size_t size,
874 TNextLayerReader&& nextLayerReader,
875 PolymorphicOpTag<>,
876 TExtraValues... extraValues)
877 {
878 return nextLayerReader.read(msg, iter, size, extraValues...);
879 }
880
881 template <typename TMsg, typename TIter, typename TNextLayerReader, typename... TExtraValues>
882 comms::ErrorStatus readGenericMsg(
883 TMsg& msg,
884 TIter& iter,
885 std::size_t size,
886 TNextLayerReader&& nextLayerReader,
887 DirectOpTag<>,
888 TExtraValues... extraValues)
889 {
890 using GenericMsgType = typename MsgFactory::GenericMessage;
891 auto& castedMsgRef = static_cast<GenericMsgType&>(*msg);
892 return nextLayerReader.read(castedMsgRef, iter, size, extraValues...);
893 }
894
895 template <typename TId, typename... TParams>
896 std::size_t msgCountInternalTagged(TId&& id, IdParamAsIsTag<TParams...>)
897 {
898 return m_factory.msgCount(std::forward<TId>(id));
899 }
900
901 template <typename TId, typename... TParams>
902 std::size_t msgCountInternalTagged(TId&& id, IdParamCastTag<TParams...>)
903 {
904 return m_factory.msgCount(static_cast<MsgIdType>(id));
905 }
906
907 template <typename TId>
908 std::size_t msgCountInternal(TId&& id)
909 {
910 using IdType = typename std::decay<decltype(id)>::type;
911 return msgCountInternalTagged(std::forward<TId>(id), IdParamTag<IdType>());
912 }
913
914 template <typename TMsg, typename TIter, typename TNextLayerWriter, typename... TParams>
915 ErrorStatus writeInternal(
916 Field& field,
917 const TMsg& msg,
918 TIter& iter,
919 std::size_t size,
920 TNextLayerWriter&& nextLayerWriter,
921 DirectOpTag<TParams...>) const
922 {
923 static_cast<void>(field);
924 return nextLayerWriter.write(msg, iter, size);
925 }
926
927 template <typename TMsg, typename TIter, typename TNextLayerWriter, typename... TParams>
928 ErrorStatus writeInternal(
929 Field& field,
930 const TMsg& msg,
931 TIter& iter,
932 std::size_t size,
933 TNextLayerWriter&& nextLayerWriter,
934 StaticBinSearchOpTag<TParams...>) const
935 {
936 auto& thisObj = BaseImpl::thisLayer();
937 auto handler = makeWriteRedirectionHandler(iter, size, std::forward<TNextLayerWriter>(nextLayerWriter));
938 auto id = thisObj.getMsgIdFromField(field);
939 return comms::dispatchMsgStaticBinSearch(id, msg, handler);
940 }
941
942 MsgFactory m_factory;
943};
944
945namespace details
946{
947template <typename T>
948struct MsgIdLayerCheckHelper
949{
950 static const bool Value = false;
951};
952
953template <typename TField,
954 typename TMessage,
955 typename TAllMessages,
956 typename TNextLayer,
957 typename... TOptions>
958struct MsgIdLayerCheckHelper<MsgIdLayer<TField, TMessage, TAllMessages, TNextLayer, TOptions...> >
959{
960 static const bool Value = true;
961};
962
963} // namespace details
964
968template <typename T>
969constexpr bool isMsgIdLayer()
970{
971 return details::MsgIdLayerCheckHelper<T>::Value;
972}
973
974} // namespace frame
975
976} // namespace comms
977
978COMMS_MSVC_WARNING_POP
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:168
Contains various compiler related definitions.
Provides common base class for the custom messages with default implementation.
Contains definition of comms::MsgFactory class.
Contains various tuple type manipulation classes and functions.
typename BaseImpl::MsgIdType MsgIdType
Type used for message ID.
Definition Message.h:195
typename BaseImpl::MsgIdParamType MsgIdParamType
Type used for message ID passed as parameter or returned from function.
Definition Message.h:202
typename Base::MsgPtr MsgPtr
Smart pointer to Message which holds allocated message object.
Definition MsgFactory.h:109
Frame layer that uses uses message ID field as a prefix to all the subsequent data written by other (...
Definition MsgIdLayer.h:72
typename Message::MsgIdParamType MsgIdParamType
Type of message ID when passed by the parameter.
Definition MsgIdLayer.h:101
static constexpr bool isDispatchStaticBinSearch()
Compile time inquiry whether static binary search dispatch is generated internally to map message ID ...
Definition MsgIdLayer.h:306
typename Message::MsgIdType MsgIdType
Type of message ID.
Definition MsgIdLayer.h:98
typename MsgFactory::MsgPtr MsgPtr
Type of smart pointer that will hold allocated message object.
Definition MsgIdLayer.h:92
TMessage Message
Type of the input message interface.
Definition MsgIdLayer.h:95
MsgIdLayer(const MsgIdLayer &)=default
Copy constructor.
static void prepareFieldForWrite(MsgIdParamType id, const TMsg &msg, Field &field)
Prepare field for writing.
Definition MsgIdLayer.h:354
typename ParsedOptionsInternal::template MsgFactory< TMessage, TAllMessages > MsgFactory
Message factory class.
Definition MsgIdLayer.h:85
static constexpr bool isDispatchPolymorphic()
Compile time inquiry whether polymorphic dispatch tables are generated internally to map message ID t...
Definition MsgIdLayer.h:299
MsgPtr createMsg(MsgIdParamType id, unsigned idx=0, CreateFailureReason *reason=nullptr)
Create message object given the ID.
Definition MsgIdLayer.h:292
static MsgIdType getMsgIdFromField(const Field &field)
Retrieve message id from the field.
Definition MsgIdLayer.h:324
static constexpr bool hasMsgFactory()
Compile time inquiry of whether custom message factory class has been provided via comms::option::app...
Definition MsgIdLayer.h:137
constexpr bool isMsgIdLayer()
Compile time check of whether the provided type is a variant of MsgIdLayer.
Definition MsgIdLayer.h:969
MsgIdLayer(MsgIdLayer &&)=default
Move constructor.
MsgIdLayer()=default
Default constructor.
comms::ErrorStatus doRead(Field &field, TMsg &msg, TIter &iter, std::size_t size, TNextLayerReader &&nextLayerReader, TExtraValues... extraValues)
Customized read functionality, invoked by read().
Definition MsgIdLayer.h:181
static constexpr bool isDispatchLinearSwitch()
Compile time inquiry whether linear switch dispatch is generated internally to map message ID to actu...
Definition MsgIdLayer.h:313
typename BaseImpl::Field Field
Type of the field object used to read/write message ID value.
Definition MsgIdLayer.h:104
typename MsgFactory::CreateFailureReason CreateFailureReason
Reason for message creation failure.
Definition MsgIdLayer.h:107
MsgIdLayer & operator=(const MsgIdLayer &)=default
Copy assignment.
ErrorStatus doWrite(Field &field, const TMsg &msg, TIter &iter, std::size_t size, TNextLayerWriter &&nextLayerWriter) const
Customized write functionality, invoked by write().
Definition MsgIdLayer.h:249
TAllMessages AllMessages
All supported message types bundled in std::tuple.
Definition MsgIdLayer.h:88
~MsgIdLayer() noexcept=default
Destructor.
MsgIdLayer & operator=(MsgIdLayer &&)=default
Move assignment.
static void beforeRead(const Field &field, TMsg &msg)
Extra operation before read.
Definition MsgIdLayer.h:340
Contains extra logic to help with dispatching message types and objects.
This file provides all the definitions from comms::field namespace.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1498
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition options.h:1484
comms::frame::MsgIdLayer< TField, TMessage, TAllMessages, TNextLayer, TOptions... > MsgIdLayer
Alias to the comms::frame::MsgIdLayer.
Definition MsgIdLayer.h:25
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ MsgAllocFailure
Used to indicate that message allocation has failed.
@ Success
Used to indicate successful outcome of the operation.
@ InvalidMsgId
Used to indicate that received message has unknown id.
auto dispatchMsgStaticBinSearch(TId &&id, std::size_t index, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using static binar...
Definition dispatch.h:167
constexpr bool isMessage()
Compile time check of of whether the type is a message.
Definition Message.h:542
MsgFactoryCreateFailureReason
Definition MsgFactoryCreateFailureReason.h:18
STL namespace.
Check whether provided type is a variant of std::tuple.
Definition Tuple.h:36
Replacement to some types from standard type_traits.