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