COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
MessageImplBases.h
1//
2// Copyright 2015 - 2024 (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
8#pragma once
9
10#include <tuple>
11#include <cstddef>
12
13#include "comms/ErrorStatus.h"
14#include "comms/util/Tuple.h"
15#include "comms/details/tag.h"
16#include "comms/field/basic/CommonFuncs.h"
17#include "comms/field/details/FieldOpHelpers.h"
18
19namespace comms
20{
21
22namespace details
23{
24
25template <typename TAllFields>
26class MessageImplFieldsContainer;
27
28template <typename... TAllFields>
29class MessageImplFieldsContainer<std::tuple<TAllFields...> >
30{
31public:
32 using AllFields = std::tuple<TAllFields...>;
33
34 AllFields& fields()
35 {
36 return fields_;
37 }
38
39 const AllFields& fields() const
40 {
41 return fields_;
42 }
43
44 static constexpr bool areFieldsVersionDependent()
45 {
46 return comms::field::basic::CommonFuncs::IsAnyFieldVersionDependentBoolType<TAllFields...>::value;
47 }
48
49 static constexpr bool doFieldsHaveNonDefaultRefresh()
50 {
51 return comms::field::basic::CommonFuncs::AnyFieldHasNonDefaultRefreshBoolType<TAllFields...>::value;
52 }
53
54 template <typename TIter>
55 comms::ErrorStatus doRead(TIter& iter, std::size_t size)
56 {
57 using Tag =
58 typename comms::util::LazyShallowConditional<
59 comms::field::basic::CommonFuncs::AllFieldsHaveReadNoStatusBoolType<TAllFields...>::value
60 >::template Type<
61 NoStatusTag,
62 UseStatusTag
63 >;
64
65 return doReadInternal(iter, size, Tag());
66 }
67
68 template <typename TIter>
69 comms::ErrorStatus doWrite(
70 TIter& iter,
71 std::size_t size) const
72 {
73
74 using Tag =
75 typename comms::util::LazyShallowConditional<
76 comms::field::basic::CommonFuncs::AllFieldsHaveWriteNoStatusBoolType<TAllFields...>::value
77 >::template Type<
78 NoStatusTag,
79 UseStatusTag
80 >;
81
82 return doWriteInternal(iter, size, Tag());
83 }
84
85 bool doValid() const
86 {
87 return util::tupleAccumulate(fields(), true, comms::field::details::FieldValidCheckHelper<>());
88 }
89
90 std::size_t doLength() const
91 {
92 return util::tupleAccumulate(fields(), static_cast<std::size_t>(0U), comms::field::details::FieldLengthSumCalcHelper<>());
93 }
94
95 template <std::size_t TFromIdx>
96 std::size_t doLengthFrom() const
97 {
98 return
99 util::tupleAccumulateFromUntil<TFromIdx, std::tuple_size<AllFields>::value>(
100 fields(), static_cast<std::size_t>(0U), comms::field::details::FieldLengthSumCalcHelper<>());
101 }
102
103 template <std::size_t TUntilIdx>
104 std::size_t doLengthUntil() const
105 {
106 return
107 util::tupleAccumulateFromUntil<0, TUntilIdx>(
108 fields(), static_cast<std::size_t>(0U), comms::field::details::FieldLengthSumCalcHelper<>());
109 }
110
111 template <std::size_t TFromIdx, std::size_t TUntilIdx>
112 std::size_t doLengthFromUntil() const
113 {
114 return
115 util::tupleAccumulateFromUntil<TFromIdx, TUntilIdx>(
116 fields(), static_cast<std::size_t>(0U), comms::field::details::FieldLengthSumCalcHelper<>());
117 }
118
119 static constexpr std::size_t doMinLength()
120 {
121 return
122 comms::util::tupleTypeAccumulate<AllFields>(
123 std::size_t(0), comms::field::details::FieldMinLengthSumCalcHelper<>());
124 }
125
126 template <std::size_t TFromIdx>
127 static constexpr std::size_t doMinLengthFrom()
128 {
129 return
130 comms::util::tupleTypeAccumulateFromUntil<TFromIdx, std::tuple_size<AllFields>::value, AllFields>(
131 std::size_t(0), comms::field::details::FieldMinLengthSumCalcHelper<>());
132 }
133
134 template <std::size_t TUntilIdx>
135 static constexpr std::size_t doMinLengthUntil()
136 {
137 return
138 comms::util::tupleTypeAccumulateFromUntil<0, TUntilIdx, AllFields>(
139 std::size_t(0), comms::field::details::FieldMinLengthSumCalcHelper<>());
140 }
141
142 template <std::size_t TFromIdx, std::size_t TUntilIdx>
143 static constexpr std::size_t doMinLengthFromUntil()
144 {
145 return
146 comms::util::tupleTypeAccumulateFromUntil<TFromIdx, TUntilIdx, AllFields>(
147 std::size_t(0), comms::field::details::FieldMinLengthSumCalcHelper<>());
148 }
149
150 static constexpr std::size_t doMaxLength()
151 {
152 return
153 comms::util::tupleTypeAccumulate<AllFields>(
154 std::size_t(0), comms::field::details::FieldMaxLengthSumCalcHelper<>());
155 }
156
157 template <std::size_t TFromIdx>
158 static constexpr std::size_t doMaxLengthFrom()
159 {
160 return
161 comms::util::tupleTypeAccumulateFromUntil<TFromIdx, std::tuple_size<AllFields>::value, AllFields>(
162 std::size_t(0), comms::field::details::FieldMaxLengthSumCalcHelper<>());
163 }
164
165 template <std::size_t TUntilIdx>
166 static constexpr std::size_t doMaxLengthUntil()
167 {
168 return
169 comms::util::tupleTypeAccumulateFromUntil<0, TUntilIdx, AllFields>(
170 std::size_t(0), comms::field::details::FieldMaxLengthSumCalcHelper<>());
171 }
172
173 template <std::size_t TFromIdx, std::size_t TUntilIdx>
174 static constexpr std::size_t doMaxLengthFromUntil()
175 {
176 return
177 comms::util::tupleTypeAccumulateFromUntil<TFromIdx, TUntilIdx, AllFields>(
178 std::size_t(0), comms::field::details::FieldMaxLengthSumCalcHelper<>());
179 }
180
181 bool doRefresh()
182 {
183 return util::tupleAccumulate(fields(), false, comms::field::details::FieldRefreshHelper<>());
184 }
185
186protected:
187 ~MessageImplFieldsContainer() noexcept = default;
188
189 template <std::size_t TIdx, typename TIter>
190 comms::ErrorStatus doReadUntil(
191 TIter& iter,
192 std::size_t len)
193 {
194 return doReadUntilAndUpdateLen<TIdx>(iter, len);
195 }
196
197 template <std::size_t TIdx, typename TIter>
198 comms::ErrorStatus doReadUntilAndUpdateLen(
199 TIter& iter,
200 std::size_t& len)
201 {
202 auto status = comms::ErrorStatus::Success;
203 util::tupleForEachUntil<TIdx>(fields(), makeFieldReader(iter, status, len));
204 return status;
205 }
206
207 template <std::size_t TIdx, typename TIter>
208 void doReadNoStatusUntil(TIter& iter)
209 {
210 util::tupleForEachUntil<TIdx>(fields(), makeFieldNoStatusReader(iter));
211 }
212
213 template <std::size_t TIdx, typename TIter>
214 comms::ErrorStatus doReadFrom(
215 TIter& iter,
216 std::size_t len)
217 {
218 return doReadFromAndUpdateLen<TIdx>(iter, len);
219 }
220
221 template <std::size_t TIdx, typename TIter>
222 comms::ErrorStatus doReadFromAndUpdateLen(
223 TIter& iter,
224 std::size_t& len)
225 {
226 auto status = comms::ErrorStatus::Success;
227 util::tupleForEachFrom<TIdx>(fields(), makeFieldReader(iter, status, len));
228 return status;
229 }
230
231 template <std::size_t TIdx, typename TIter>
232 void doReadNoStatusFrom(TIter& iter)
233 {
234 util::tupleForEachFrom<TIdx>(fields(), makeFieldNoStatusReader(iter));
235 }
236
237 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
238 comms::ErrorStatus doReadFromUntil(
239 TIter& iter,
240 std::size_t len)
241 {
242 return doReadFromUntilAndUpdateLen<TFromIdx, TUntilIdx>(iter, len);
243 }
244
245 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
246 comms::ErrorStatus doReadFromUntilAndUpdateLen(
247 TIter& iter,
248 std::size_t& len)
249 {
250 auto status = comms::ErrorStatus::Success;
251 util::tupleForEachFromUntil<TFromIdx, TUntilIdx>(fields(), makeFieldReader(iter, status, len));
252 return status;
253 }
254
255 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
256 void doReadNoStatusFromUntil(TIter& iter)
257 {
258 util::tupleForEachFromUntil<TFromIdx, TUntilIdx>(fields(), makeFieldNoStatusReader(iter));
259 }
260
261 template <std::size_t TIdx, typename TIter>
262 comms::ErrorStatus doWriteUntil(
263 TIter& iter,
264 std::size_t len) const
265 {
266 return doWriteUntilAndUpdateLen<TIdx>(iter, len);
267 }
268
269 template <std::size_t TIdx, typename TIter>
270 comms::ErrorStatus doWriteUntilAndUpdateLen(
271 TIter& iter,
272 std::size_t& len) const
273 {
274 auto status = comms::ErrorStatus::Success;
275 util::tupleForEachUntil<TIdx>(fields(), makeFieldWriter(iter, status, len));
276 return status;
277 }
278
279 template <std::size_t TIdx, typename TIter>
280 void doWriteNoStatusUntil(TIter& iter) const
281 {
282 util::tupleForEachUntil<TIdx>(fields(), makeFieldNoStatusWriter(iter));
283 }
284
285 template <std::size_t TIdx, typename TIter>
286 comms::ErrorStatus doWriteFrom(
287 TIter& iter,
288 std::size_t len) const
289 {
290 return doWriteFromAndUpdateLen<TIdx>(iter, len);
291 }
292
293 template <std::size_t TIdx, typename TIter>
294 comms::ErrorStatus doWriteFromAndUpdateLen(
295 TIter& iter,
296 std::size_t& len) const
297 {
298 auto status = comms::ErrorStatus::Success;
299 util::tupleForEachFrom<TIdx>(fields(), makeFieldWriter(iter, status, len));
300 return status;
301 }
302
303 template <std::size_t TIdx, typename TIter>
304 void doWriteNoStatusFrom(TIter& iter) const
305 {
306 util::tupleForEachFrom<TIdx>(fields(), makeFieldNoStatusWriter(iter));
307 }
308
309 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
310 comms::ErrorStatus doWriteFromUntil(
311 TIter& iter,
312 std::size_t len) const
313 {
314 return doWriteFromUntilAndUpdateLen<TFromIdx, TUntilIdx>(iter, len);
315 }
316
317 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
318 comms::ErrorStatus doWriteFromUntilAndUpdateLen(
319 TIter& iter,
320 std::size_t& len) const
321 {
322 auto status = comms::ErrorStatus::Success;
323 util::tupleForEachFromUntil<TFromIdx, TUntilIdx>(fields(), makeFieldWriter(iter, status, len));
324 return status;
325 }
326
327 template <std::size_t TFromIdx, std::size_t TUntilIdx, typename TIter>
328 void doWriteNoStatusFromUntil(TIter& iter) const
329 {
330 util::tupleForEachFromUntil<TFromIdx, TUntilIdx>(fields(), makeFieldNoStatusWriter(iter));
331 }
332
333private:
334 template <typename... TParams>
335 using NoStatusTag = comms::details::tag::Tag1<>;
336
337 template <typename... TParams>
338 using UseStatusTag = comms::details::tag::Tag2<>;
339
340 template <typename TIter, typename... TParams>
341 comms::ErrorStatus doReadInternal(
342 TIter& iter,
343 std::size_t size,
344 UseStatusTag<TParams...>)
345 {
346 return doReadFromAndUpdateLen<0>(iter, size);
347 }
348
349 template <typename TIter, typename... TParams>
350 comms::ErrorStatus doReadInternal(
351 TIter& iter,
352 std::size_t size,
353 NoStatusTag<TParams...>)
354 {
355 if (size < doLength()) {
357 }
358
359 doReadNoStatusFrom<0>(iter);
361 }
362
363 template <typename TIter, typename... TParams>
364 comms::ErrorStatus doWriteInternal(
365 TIter& iter,
366 std::size_t size,
367 UseStatusTag<TParams...>) const
368 {
369 return doWriteFromAndUpdateLen<0>(iter, size);
370 }
371
372 template <typename TIter, typename... TParams>
373 comms::ErrorStatus doWriteInternal(
374 TIter& iter,
375 std::size_t size,
376 NoStatusTag<TParams...>) const
377 {
378 if (size < doLength()) {
380 }
381
382 doWriteNoStatusFrom<0>(iter);
384 }
385
386 template <typename TIter>
387 static comms::field::details::FieldReadHelper<TIter> makeFieldReader(
388 TIter& iter,
389 comms::ErrorStatus& status,
390 std::size_t& size)
391 {
392 return comms::field::details::FieldReadHelper<TIter>(status, iter, size);
393 }
394
395 template <typename TIter>
396 static comms::field::details::FieldReadNoStatusHelper<TIter> makeFieldNoStatusReader(TIter& iter)
397 {
398 return comms::field::details::FieldReadNoStatusHelper<TIter>(iter);
399 }
400
401 template <typename TIter>
402 static comms::field::details::FieldWriteHelper<TIter> makeFieldWriter(
403 TIter& iter,
404 comms::ErrorStatus& status,
405 std::size_t& size)
406 {
407 return comms::field::details::FieldWriteHelper<TIter>(status, iter, size);
408 }
409
410 template <typename TIter>
411 static comms::field::details::FieldWriteNoStatusHelper<TIter> makeFieldNoStatusWriter(TIter& iter)
412 {
413 return comms::field::details::FieldWriteNoStatusHelper<TIter>(iter);
414 }
415
416 AllFields fields_;
417};
418
419// ------------------------------------------------------
420
421template <typename TBase, typename TAllFields>
422class MessageImplFieldsBase : public TBase, public MessageImplFieldsContainer<TAllFields>
423{
424 using ContainerBase = MessageImplFieldsContainer<TAllFields>;
425public:
426 using ContainerBase::doRead;
427 using ContainerBase::doWrite;
428 using ContainerBase::doLength;
429 using ContainerBase::doValid;
430 using ContainerBase::doRefresh;
431 using ContainerBase::doLengthFrom;
432 using ContainerBase::doLengthUntil;
433 using ContainerBase::doLengthFromUntil;
434 using ContainerBase::doMinLength;
435 using ContainerBase::doMinLengthFrom;
436 using ContainerBase::doMinLengthUntil;
437 using ContainerBase::doMinLengthFromUntil;
438 using ContainerBase::doMaxLength;
439 using ContainerBase::doMaxLengthFrom;
440 using ContainerBase::doMaxLengthUntil;
441 using ContainerBase::doMaxLengthFromUntil;
442 using ContainerBase::areFieldsVersionDependent;
443
444protected:
445 ~MessageImplFieldsBase() noexcept = default;
446
447 using ContainerBase::doReadUntil;
448 using ContainerBase::doReadUntilAndUpdateLen;
449 using ContainerBase::doReadNoStatusUntil;
450 using ContainerBase::doReadFrom;
451 using ContainerBase::doReadFromAndUpdateLen;
452 using ContainerBase::doReadNoStatusFrom;
453 using ContainerBase::doReadFromUntil;
454 using ContainerBase::doReadFromUntilAndUpdateLen;
455 using ContainerBase::doReadNoStatusFromUntil;
456 using ContainerBase::doWriteUntil;
457 using ContainerBase::doWriteUntilAndUpdateLen;
458 using ContainerBase::doWriteNoStatusUntil;
459 using ContainerBase::doWriteFrom;
460 using ContainerBase::doWriteFromAndUpdateLen;
461 using ContainerBase::doWriteNoStatusFrom;
462 using ContainerBase::doWriteFromUntil;
463 using ContainerBase::doWriteFromUntilAndUpdateLen;
464 using ContainerBase::doWriteNoStatusFromUntil;
465};
466
467// ------------------------------------------------------
468
469template <typename TBase>
470class MessageImplVersionBase : public TBase
471{
472public:
473 using VersionType = typename TBase::VersionType;
474
475 bool doFieldsVersionUpdate()
476 {
477 return comms::field::basic::CommonFuncs::setVersionForMembers(TBase::fields(), TBase::version());
478 }
479
480 template <typename TIter>
481 comms::ErrorStatus doRead(TIter& iter, std::size_t len)
482 {
483 doFieldsVersionUpdate();
484 return TBase::doRead(iter, len);
485 }
486
487 bool doRefresh()
488 {
489 bool updated = doFieldsVersionUpdate();
490 return TBase::doRefresh() || updated;
491 }
492
493protected:
494 MessageImplVersionBase()
495 {
496 doFieldsVersionUpdate();
497 }
498
499 MessageImplVersionBase(const MessageImplVersionBase&) = default;
500 MessageImplVersionBase(MessageImplVersionBase&&) = default;
501 ~MessageImplVersionBase() noexcept = default;
502
503 MessageImplVersionBase& operator=(const MessageImplVersionBase&) = default;
504 MessageImplVersionBase& operator=(MessageImplVersionBase&&) = default;
505};
506
507// ------------------------------------------------------
508
509template <typename TBase, typename TActual = void>
510class MessageImplFieldsReadImplBase : public TBase
511{
512 using BaseImpl = TBase;
513protected:
514 ~MessageImplFieldsReadImplBase() noexcept = default;
515 virtual comms::ErrorStatus readImpl(
516 typename BaseImpl::ReadIterator& iter,
517 std::size_t size) override
518 {
519 using Tag =
520 typename comms::util::LazyShallowConditional<
521 std::is_same<TActual, void>::value
522 >::template Type<
523 NoActual,
524 HasActual
525 >;
526 return readImplInternal(iter, size, Tag());
527 }
528
529private:
530 template <typename... TParams>
531 using HasActual = comms::details::tag::Tag1<>;
532
533 template <typename... TParams>
534 using NoActual = comms::details::tag::Tag2<>;
535
536 template <typename... TParams>
537 comms::ErrorStatus readImplInternal(
538 typename BaseImpl::ReadIterator& iter,
539 std::size_t size,
540 NoActual<TParams...>)
541 {
542 return BaseImpl::doRead(iter, size);
543 }
544
545 template <typename... TParams>
546 comms::ErrorStatus readImplInternal(
547 typename BaseImpl::ReadIterator& iter,
548 std::size_t size,
549 HasActual<TParams...>)
550 {
551 return static_cast<TActual*>(this)->doRead(iter, size);
552 }
553};
554
555// ------------------------------------------------------
556
557template <typename TBase, typename TActual = void>
558class MessageImplFieldsWriteImplBase : public TBase
559{
560 using BaseImpl = TBase;
561
562protected:
563 ~MessageImplFieldsWriteImplBase() noexcept = default;
564 virtual comms::ErrorStatus writeImpl(
565 typename BaseImpl::WriteIterator& iter,
566 std::size_t size) const override
567 {
568 using Tag =
569 typename comms::util::LazyShallowConditional<
570 std::is_same<TActual, void>::value
571 >::template Type<
572 NoActual,
573 HasActual
574 >;
575 return writeImplInternal(iter, size, Tag());
576 }
577
578private:
579 template <typename... TParams>
580 using HasActual = comms::details::tag::Tag1<>;
581
582 template <typename... TParams>
583 using NoActual = comms::details::tag::Tag2<>;
584
585 template <typename... TParams>
586 comms::ErrorStatus writeImplInternal(
587 typename BaseImpl::WriteIterator& iter,
588 std::size_t size,
589 NoActual<TParams...>) const
590 {
591 return BaseImpl::doWrite(iter, size);
592 }
593
594 template <typename... TParams>
595 comms::ErrorStatus writeImplInternal(
596 typename BaseImpl::WriteIterator& iter,
597 std::size_t size,
598 HasActual<TParams...>) const
599 {
600 return static_cast<const TActual*>(this)->doWrite(iter, size);
601 }
602};
603
604// ------------------------------------------------------
605
606template <typename TBase, typename TActual = void>
607class MessageImplFieldsValidBase : public TBase
608{
609 using BaseImpl = TBase;
610
611protected:
612 ~MessageImplFieldsValidBase() noexcept = default;
613 virtual bool validImpl() const override
614 {
615 using Tag =
616 typename comms::util::LazyShallowConditional<
617 std::is_same<TActual, void>::value
618 >::template Type<
619 NoActual,
620 HasActual
621 >;
622 return validImplInternal(Tag());
623 }
624
625private:
626 template <typename... TParams>
627 using HasActual = comms::details::tag::Tag1<>;
628
629 template <typename... TParams>
630 using NoActual = comms::details::tag::Tag2<>;
631
632 template <typename... TParams>
633 bool validImplInternal(NoActual<TParams...>) const
634 {
635 return BaseImpl::doValid();
636 }
637
638 template <typename... TParams>
639 bool validImplInternal(HasActual<TParams...>) const
640 {
641 return static_cast<const TActual*>(this)->doValid();
642 }
643};
644
645// ------------------------------------------------------
646
647template <typename TBase, typename TActual = void>
648class MessageImplFieldsLengthBase : public TBase
649{
650 using BaseImpl = TBase;
651
652protected:
653 ~MessageImplFieldsLengthBase() noexcept = default;
654 virtual std::size_t lengthImpl() const override
655 {
656 using Tag =
657 typename comms::util::LazyShallowConditional<
658 std::is_same<TActual, void>::value
659 >::template Type<
660 NoActual,
661 HasActual
662 >;
663 return lengthImplInternal(Tag());
664 }
665
666private:
667 template <typename... TParams>
668 using HasActual = comms::details::tag::Tag1<>;
669
670 template <typename... TParams>
671 using NoActual = comms::details::tag::Tag2<>;
672
673 template <typename... TParams>
674 std::size_t lengthImplInternal(NoActual<TParams...>) const
675 {
676 return BaseImpl::doLength();
677 }
678
679 template <typename... TParams>
680 std::size_t lengthImplInternal(HasActual<TParams...>) const
681 {
682 return static_cast<const TActual*>(this)->doLength();
683 }
684};
685
686// ------------------------------------------------------
687
688template <typename TBase, typename TActual, typename TFailOnInvalidStatusWrapper>
689class MessageImplFailOnInvalidBase : public TBase
690{
691 using BaseImpl = TBase;
692
693public:
694 template <typename TIter>
695 comms::ErrorStatus doRead(TIter& iter, std::size_t len)
696 {
697 auto es = TBase::doRead(iter, len);
698 if (es != comms::ErrorStatus::Success) {
699 return es;
700 }
701
702 if (!doValidInternal()) {
703 return TFailOnInvalidStatusWrapper::Value;
704 }
705
707 }
708
709protected:
710 ~MessageImplFailOnInvalidBase() noexcept = default;
711
712private:
713 template <typename... TParams>
714 using HasActual = comms::details::tag::Tag1<>;
715
716 template <typename... TParams>
717 using NoActual = comms::details::tag::Tag2<>;
718
719 template <typename... TParams>
720 bool doValidInternal(NoActual<TParams...>) const
721 {
722 return BaseImpl::doValid();
723 }
724
725 template <typename... TParams>
726 bool doValidInternal(HasActual<TParams...>) const
727 {
728 return static_cast<const TActual*>(this)->doValid();
729 }
730
731 bool doValidInternal() const
732 {
733 using Tag =
734 typename comms::util::LazyShallowConditional<
735 std::is_same<TActual, void>::value
736 >::template Type<
737 NoActual,
738 HasActual
739 >;
740
741 return doValidInternal(Tag());
742 }
743};
744
745
746// ------------------------------------------------------
747
748template <typename TBase, typename TActual = void>
749class MessageImplRefreshBase : public TBase
750{
751protected:
752 ~MessageImplRefreshBase() noexcept = default;
753 virtual bool refreshImpl() override
754 {
755 using Tag =
756 typename comms::util::LazyShallowConditional<
757 std::is_same<TActual, void>::value
758 >::template Type<
759 NoDowncast,
760 Downcast
761 >;
762 return refreshInternal(Tag());
763 }
764
765private:
766 template <typename... TParams>
767 using Downcast = comms::details::tag::Tag1<>;
768
769 template <typename... TParams>
770 using NoDowncast = comms::details::tag::Tag2<>;
771
772 template <typename... TParams>
773 bool refreshInternal(Downcast<TParams...>)
774 {
775 return static_cast<TActual*>(this)->doRefresh();
776 }
777
778 template <typename... TParams>
779 bool refreshInternal(NoDowncast<TParams...>)
780 {
781 return TBase::doRefresh();
782 }
783};
784
785// ------------------------------------------------------
786
787template <typename TBase, typename TActual>
788class MessageImplDispatchBase : public TBase
789{
790 using BaseImpl = TBase;
791protected:
792 ~MessageImplDispatchBase() noexcept = default;
793 virtual typename TBase::DispatchRetType dispatchImpl(typename TBase::Handler& handler) override
794 {
795 static_assert(std::is_base_of<TBase, TActual>::value,
796 "TActual is not derived class");
797 return handler.handle(static_cast<TActual&>(*this));
798 }
799};
800
801// ------------------------------------------------------
802
803template <typename TBase, std::intmax_t TId>
804class MessageImplStaticNumIdBase : public TBase
805{
806public:
807 static const typename TBase::MsgIdType MsgId =
808 static_cast<typename TBase::MsgIdType>(TId);
809
810 static constexpr typename TBase::MsgIdParamType doGetId()
811 {
812 return MsgId;
813 }
814
815protected:
816 ~MessageImplStaticNumIdBase() noexcept = default;
817};
818
819// ------------------------------------------------------
820
821template <typename TBase, typename TActual = void>
822class MessageImplPolymorhpicStaticNumIdBase : public TBase
823{
824protected:
825 ~MessageImplPolymorhpicStaticNumIdBase() noexcept = default;
826 virtual typename TBase::MsgIdParamType getIdImpl() const override
827 {
828 using Tag =
829 typename comms::util::LazyShallowConditional<
830 std::is_same<TActual, void>::value
831 >::template Type<
832 NoDowncastTag,
833 DowncastTag
834 >;
835 return getIdInternal(Tag());
836 }
837
838private:
839 template <typename... TParams>
840 using DowncastTag = comms::details::tag::Tag1<>;
841
842 template <typename... TParams>
843 using NoDowncastTag = comms::details::tag::Tag2<>;
844
845 template <typename... TParams>
846 typename TBase::MsgIdParamType getIdInternal(NoDowncastTag<TParams...>) const
847 {
848 return TBase::doGetId();
849 }
850
851 template <typename... TParams>
852 typename TBase::MsgIdParamType getIdInternal(DowncastTag<TParams...>) const
853 {
854 return static_cast<const TActual*>(this)->doGetId();
855 }
856};
857
858// ------------------------------------------------------
859
860template <typename TBase>
861class MessageImplNoIdBase : public TBase
862{
863protected:
864 ~MessageImplNoIdBase() noexcept = default;
865 virtual typename TBase::MsgIdParamType getIdImpl() const override
866 {
867 static const typename TBase::MsgIdType MsgId = typename TBase::MsgIdType();
868 static constexpr bool The_message_id_is_not_supposed_to_be_retrieved = false;
869 static_cast<void>(The_message_id_is_not_supposed_to_be_retrieved);
870 COMMS_ASSERT(The_message_id_is_not_supposed_to_be_retrieved);
871 return MsgId;
872 }
873};
874
875// ------------------------------------------------------
876
877template <typename TBase, typename TActual>
878class MessageImplNameBase : public TBase
879{
880protected:
881 ~MessageImplNameBase() noexcept = default;
882 virtual const char* nameImpl() const override
883 {
884 return static_cast<const TActual*>(this)->doName();
885 }
886};
887
888
889} // namespace details
890
891} // namespace comms
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
This file contain definition of error statuses used by comms module.
Contains various tuple type manipulation classes and functions.
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1797
constexpr TValue tupleAccumulate(TTuple &&tuple, const TValue &value, TFunc &&func)
Performs "accumulate" algorithm on every element of the tuple.
Definition Tuple.h:586
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ Success
Used to indicate successful outcome of the operation.
STL namespace.