COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
DispatchMsgStaticBinSearchHelper.h
1//
2// Copyright 2019 - 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/DispatchMsgHelperType.h"
14#include "comms/details/tag.h"
15#include "comms/Message.h"
16#include "comms/MessageBase.h"
18
19#include <cstddef>
20#include <type_traits>
21#include <utility>
22
23namespace comms
24{
25
26namespace details
27{
28
29template <DispatchMsgTypeEnum TType>
30class DispatchMsgStrongStaticBinSearchHelper // <DispatchMsgTypeEnum::Multiple>
31{
32 template <std::size_t TFrom, std::size_t TCount>
33 using MidIdx =
34 std::integral_constant<std::size_t, (TFrom + (TCount / 2))>;
35
36 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
37 using MidElem =
38 typename std::tuple_element<
39 MidIdx<TFrom, TCount>::value,
40 TAllMessages
41 >::type;
42
43 // static_assert(TFrom + TCount <= std::tuple_size<TAllMessages>::value,
44 // "Invalid template params");
45
46 // static_assert(2 <= TCount, "Invalid invocation");
47 // static constexpr std::size_t Mid = TFrom + (TCount / 2);
48 // using MidElem = typename std::tuple_element<Mid, TAllMessages>::type;
49 // static_assert(messageHasStaticNumId<MidElem>(), "Message must define static ID");
50
51public:
52 template <
53 typename TAllMessages,
54 std::size_t TFrom,
55 std::size_t TCount,
56 typename TId,
57 typename TMsg,
58 typename THandler>
59 static auto dispatch(TId&& id, TMsg& msg, THandler& handler) ->
60 MessageInterfaceDispatchRetType<
61 typename std::decay<decltype(handler)>::type>
62 {
63 using RetType =
64 MessageInterfaceDispatchRetType<
65 typename std::decay<decltype(handler)>::type>;
66
67 static constexpr std::size_t Mid = MidIdx<TFrom, TCount>::value;
68 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
69
70 typename TMsg::MsgIdParamType midId = MidElemType::doGetId();
71 if (id < midId) {
72 static constexpr auto NextCount = Mid - TFrom;
73 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
74 return
75 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
76 dispatch<TAllMessages, TFrom, NextCount>(
77 id, msg, handler);
78 }
79
80 if (midId < id) {
81 static constexpr auto NextCount = TCount - (Mid - TFrom);
82 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
83 return
84 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
85 dispatch<TAllMessages, Mid, NextCount>(
86 id, msg, handler);
87 }
88
89 auto& castedMsg = static_cast<MidElemType&>(msg);
90 return static_cast<RetType>(handler.handle(castedMsg));
91 }
92
93 template <
94 typename TAllMessages,
95 std::size_t TFrom,
96 std::size_t TCount,
97 typename TId,
98 typename THandler>
99 static bool dispatchType(TId&& id, THandler& handler)
100 {
101 static constexpr std::size_t Mid = MidIdx<TFrom, TCount>::value;
102 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
103 typename MidElemType::MsgIdParamType midId = MidElemType::doGetId();
104 if (id < midId) {
105 static constexpr auto NextCount = Mid - TFrom;
106 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
107 return
108 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
109 dispatchType<TAllMessages, TFrom, NextCount>(id, handler);
110 }
111
112 if (midId < id) {
113 static constexpr auto NextCount = TCount - (Mid - TFrom);
114 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
115 return
116 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
117 dispatchType<TAllMessages, Mid, NextCount>(id, handler);
118 }
119
120 handler.template handle<MidElemType>();
121 return true;
122 }
123
124 template <
125 typename TAllMessages,
126 std::size_t TFrom,
127 std::size_t TCount,
128 typename TId>
129 static std::size_t dispatchTypeCount(TId&& id)
130 {
131 static constexpr std::size_t Mid = MidIdx<TFrom, TCount>::value;
132 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
133 typename MidElemType::MsgIdParamType midId = MidElemType::doGetId();
134 if (id < midId) {
135 static constexpr auto NextCount = Mid - TFrom;
136 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
137 return
138 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
139 dispatchTypeCount<TAllMessages, TFrom, NextCount>(id);
140 }
141
142 if (midId < id) {
143 static constexpr auto NextCount = TCount - (Mid - TFrom);
144 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
145 return
146 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
147 dispatchTypeCount<TAllMessages, Mid, NextCount>(id);
148 }
149
150 return 1U;
151 }
152};
153
154template <>
155class DispatchMsgStrongStaticBinSearchHelper<DispatchMsgTypeEnum::Single>
156{
157 // static_assert(TFrom + 1 <= std::tuple_size<TAllMessages>::value,
158 // "Invalid template params");
159
160 template <typename TAllMessages, std::size_t TFrom>
161 using Elem = typename std::tuple_element<TFrom, TAllMessages>::type;
162 // static_assert(messageHasStaticNumId<Elem>(), "Message must define static ID");
163
164public:
165 template <
166 typename TAllMessages,
167 std::size_t TFrom,
168 std::size_t TCount,
169 typename TId,
170 typename TMsg,
171 typename THandler>
172 static auto dispatch(TId&& id, TMsg& msg, THandler& handler) ->
173 MessageInterfaceDispatchRetType<
174 typename std::decay<decltype(handler)>::type>
175 {
176 using RetType =
177 MessageInterfaceDispatchRetType<
178 typename std::decay<decltype(handler)>::type>;
179
180 using ElemType = Elem<TAllMessages, TFrom>;
181
182 typename TMsg::MsgIdParamType elemId = ElemType::doGetId();
183 if (id != elemId) {
184 return static_cast<RetType>(handler.handle(msg));
185 }
186
187 auto& castedMsg = static_cast<ElemType&>(msg);
188 return static_cast<RetType>(handler.handle(castedMsg));
189 }
190
191 template <
192 typename TAllMessages,
193 std::size_t TFrom,
194 std::size_t TCount,
195 typename TId,
196 typename THandler>
197 static bool dispatchType(TId&& id, THandler& handler)
198 {
199 using ElemType = Elem<TAllMessages, TFrom>;
200 typename ElemType::MsgIdParamType elemId = ElemType::doGetId();
201 if (id != elemId) {
202 return false;
203 }
204
205 handler.template handle<ElemType>();
206 return true;
207 }
208
209 template <
210 typename TAllMessages,
211 std::size_t TFrom,
212 std::size_t TCount,
213 typename TId>
214 static std::size_t dispatchTypeCount(TId&& id)
215 {
216 using ElemType = Elem<TAllMessages, TFrom>;
217 typename ElemType::MsgIdParamType elemId = ElemType::doGetId();
218 if (id != elemId) {
219 return 0U;
220 }
221
222 return 1U;
223 }
224};
225
226template <>
227class DispatchMsgStrongStaticBinSearchHelper<DispatchMsgTypeEnum::None>
228{
229public:
230 template <
231 typename TAllMessages,
232 std::size_t TFrom,
233 std::size_t TCount,
234 typename TId,
235 typename TMsg,
236 typename THandler>
237 static auto dispatch(TId&& id, TMsg& msg, THandler& handler) ->
238 MessageInterfaceDispatchRetType<
239 typename std::decay<decltype(handler)>::type>
240 {
241 static_cast<void>(id);
242
243 using RetType =
244 MessageInterfaceDispatchRetType<
245 typename std::decay<decltype(handler)>::type>;
246 return static_cast<RetType>(handler.handle(msg));
247 }
248
249 template <
250 typename TAllMessages,
251 std::size_t TFrom,
252 std::size_t TCount,
253 typename TId,
254 typename THandler>
255 static bool dispatchType(TId&& id, THandler& handler)
256 {
257 static_cast<void>(id);
258 static_cast<void>(handler);
259 return false;
260 }
261
262 template <
263 typename TAllMessages,
264 std::size_t TFrom,
265 std::size_t TCount,
266 typename TId>
267 static std::size_t dispatchTypeCount(TId&& id)
268 {
269 static_cast<void>(id);
270 return 0U;
271 }
272};
273
274template <bool TFirst>
275class DispatchMsgWeakStartIdxFinder //<false>
276{
277 template <typename TAllMessages, std::size_t TIdx>
278 using CurrMsgType = typename std::tuple_element<TIdx, TAllMessages>::type;
279
280 template <typename TAllMessages, std::size_t TIdx>
281 using PrevMsgType = typename std::tuple_element<TIdx - 1, TAllMessages>::type;
282
283public:
284 template <typename TAllMessages, std::size_t TIdx>
285 using Type =
287 CurrMsgType<TAllMessages, TIdx>::doGetId() == PrevMsgType<TAllMessages, TIdx>::doGetId()
288 >::template Type<
289 typename DispatchMsgWeakStartIdxFinder<(TIdx <= 1)>::template Type<TAllMessages, TIdx - 1U>,
290 std::integral_constant<std::size_t, TIdx>
291 >;
292};
293
294template <>
295class DispatchMsgWeakStartIdxFinder<true>
296{
297public:
298 template <typename TAllMessages, std::size_t TIdx>
299 using Type = std::integral_constant<std::size_t, TIdx>;
300};
301
302template <bool THasElems>
303class DispatchMsgWeakCountFinder //<true>
304{
305 template <typename TAllMessages, std::size_t TIdx>
306 using OrigMsgType = typename std::tuple_element<TIdx, TAllMessages>::type;
307
308 template <typename TAllMessages, std::size_t TIdx, std::size_t TCount>
309 using CurrMsgType =
310 typename std::tuple_element<
311 std::tuple_size<TAllMessages>::value - TCount,
312 TAllMessages
313 >::type;
314
315public:
316 template <typename TAllMessages, std::size_t TOrigIdx, std::size_t TRem>
317 using Type =
319 OrigMsgType<TAllMessages, TOrigIdx>::doGetId() == CurrMsgType<TAllMessages, TOrigIdx, TRem>::doGetId()
320 >::template Type<
321 std::integral_constant<
322 std::size_t,
323 1U + DispatchMsgWeakCountFinder<(1U < TRem)>::template Type<TAllMessages, TOrigIdx, TRem - 1>::value
324 >,
325 std::integral_constant<std::size_t, 0U>
326 >;
327};
328
329template <>
330class DispatchMsgWeakCountFinder<false>
331{
332public:
333 template <typename TAllMessages, std::size_t TOrigIdx, std::size_t TRem>
334 using Type = std::integral_constant<std::size_t, 0U>;
335};
336
337//template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
338template <DispatchMsgTypeEnum TType>
339class DispatchMsgWeakStaticBinSearchHelper // <DispatchMsgTypeEnum::Multiple>
340{
341 // static_assert(TFrom < std::tuple_size<TAllMessages>::value,
342 // "Invalid template params");
343
344 // static_assert(TFrom + TCount <= std::tuple_size<TAllMessages>::value,
345 // "Invalid template params");
346
347 // static_assert(2 <= TCount, "Invalid invocation");
348
349 template <std::size_t TFrom, std::size_t TCount>
350 using MidIdx =
351 std::integral_constant<std::size_t, (TFrom + (TCount / 2))>;
352
353 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
354 using MidElem =
355 typename std::tuple_element<
356 MidIdx<TFrom, TCount>::value,
357 TAllMessages
358 >::type;
359
360 // static_assert(Mid < std::tuple_size<TAllMessages>::value,
361 // "Invalid template params");
362
363 // static_assert(messageHasStaticNumId<MidElem>(), "Message must define static ID");
364
365 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
366 using MidRangeStartIdxTmp =
367 typename DispatchMsgWeakStartIdxFinder<
368 MidIdx<TFrom, TCount>::value == 0U
369 >::template Type<
370 TAllMessages,
371 MidIdx<TFrom, TCount>::value
372 >;
373
374 // static_assert(MidRangeStartIdxTmp <= Mid, "Invalid calculation");
375 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
376 using MidRangeStartIdx =
377 typename comms::util::IntMaxBinaryOp<>::template Type<
378 MidRangeStartIdxTmp<TAllMessages, TFrom, TCount>,
379 std::integral_constant<std::size_t, TFrom>
380 >;
381
382 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
383 using RemCount =
384 std::integral_constant<
385 std::size_t,
386 std::tuple_size<TAllMessages>::value - MidRangeStartIdx<TAllMessages, TFrom, TCount>::value
387 >;
388
389 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
390 using MidRangeCountTmp =
391 typename DispatchMsgWeakCountFinder<
392 (0U < RemCount<TAllMessages, TFrom, TCount>::value)
393 >::template Type<
394 TAllMessages,
395 MidRangeStartIdx<TAllMessages, TFrom, TCount>::value,
396 RemCount<TAllMessages, TFrom, TCount>::value
397 >;
398
399 template <typename TAllMessages, std::size_t TFrom, std::size_t TCount>
400 using MidRangeCount =
401 typename comms::util::IntMinBinaryOp<>::template Type<
402 std::integral_constant<std::size_t, TCount - MidRangeStartIdx<TAllMessages, TFrom, TCount>::value>,
403 MidRangeCountTmp<TAllMessages, TFrom, TCount>
404 >;
405
406 // static_assert(MidRangeStartIdx < std::tuple_size<TAllMessages>::value,
407 // "Invalid template params");
408
409 // static_assert(MidRangeStartIdx + MidRangeCount <= std::tuple_size<TAllMessages>::value,
410 // "Invalid template params");
411
412public:
413 template <
414 typename TAllMessages,
415 std::size_t TFrom,
416 std::size_t TCount,
417 typename TMsg,
418 typename THandler>
419 static auto dispatch(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler) ->
420 MessageInterfaceDispatchRetType<
421 typename std::decay<decltype(handler)>::type>
422 {
423 using RetType =
424 MessageInterfaceDispatchRetType<
425 typename std::decay<decltype(handler)>::type>;
426
427 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
428
429 typename TMsg::MsgIdParamType midId = MidElemType::doGetId();
430 static constexpr std::size_t StartIdx =
431 MidRangeStartIdx<TAllMessages, TFrom, TCount>::value;
432
433 // static_assert(StartIdx <= MidIdx<TFrom, TCount>::value, "Invalid calculation");
434
435 if (id < midId) {
436 static constexpr std::size_t NextCount = StartIdx - TFrom;
437 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
438 return
439 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
440 dispatch<TAllMessages, TFrom, NextCount>(id, offset, msg, handler);
441 }
442
443 static constexpr std::size_t MidCount = MidRangeCount<TAllMessages, TFrom, TCount>::value;
444
445 if (midId < id) {
446 static constexpr std::size_t NewStart = StartIdx + MidCount;
447 static constexpr std::size_t NextCount = TCount - (NewStart - TFrom);
448 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
449
450 return
451 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
452 dispatch<TAllMessages, NewStart, NextCount>(id, offset, msg, handler);
453 }
454
455 if (MidCount <= offset) {
456 return static_cast<RetType>(handler.handle(msg));
457 }
458
459 static constexpr auto HelperType = DispatchMsgHelperIntType<MidCount>::value;
460 return
461 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
462 dispatchOffset<TAllMessages, StartIdx, MidCount>(offset, msg, handler);
463 }
464
465 template <
466 typename TAllMessages,
467 std::size_t TFrom,
468 std::size_t TCount,
469 typename TMsg,
470 typename THandler>
471 static auto dispatchOffset(std::size_t offset, TMsg& msg, THandler& handler) ->
472 MessageInterfaceDispatchRetType<
473 typename std::decay<decltype(handler)>::type>
474 {
475 using RetType =
476 MessageInterfaceDispatchRetType<
477 typename std::decay<decltype(handler)>::type>;
478
479 static constexpr std::size_t MidOffset = TCount / 2;
480
481 if (offset < MidOffset) {
482 static constexpr auto HelperType = DispatchMsgHelperIntType<MidOffset>::value;
483 return
484 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
485 dispatchOffset<TAllMessages, TFrom, MidOffset>(offset, msg, handler);
486 }
487
488 if (MidOffset < offset) {
489 static constexpr std::size_t NextCount = TCount - (MidOffset - TFrom);
490 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
491 return
492 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
493 dispatchOffset<TAllMessages, MidOffset, NextCount>(offset - MidOffset, msg, handler);
494 }
495
496 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
497 auto& castedMsg = static_cast<MidElemType&>(msg);
498 return static_cast<RetType>(handler.handle(castedMsg));
499 }
500
501 template <
502 typename TAllMessages,
503 std::size_t TFrom,
504 std::size_t TCount,
505 typename TId,
506 typename THandler>
507 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
508 {
509 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
510 static constexpr std::size_t StartIdx =
511 MidRangeStartIdx<TAllMessages, TFrom, TCount>::value;
512
513 static_assert(StartIdx <= MidIdx<TFrom, TCount>::value, "Invalid calculation");
514
515 typename MidElemType::MsgIdParamType midId = MidElemType::doGetId();
516 if (id < midId) {
517 static constexpr std::size_t NextCount = StartIdx - TFrom;
518 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
519 return
520 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
521 dispatchType<TAllMessages, TFrom, NextCount>(id, offset, handler);
522 }
523
524 static constexpr std::size_t MidCount = MidRangeCount<TAllMessages, TFrom, TCount>::value;
525
526 if (midId < id) {
527 static constexpr std::size_t NewStart = StartIdx + MidCount;
528 static constexpr std::size_t NextCount = TCount - (NewStart - TFrom);
529 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
530 return
531 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
532 dispatchType<TAllMessages, NewStart, NextCount>(id, offset, handler);
533 }
534
535 if (MidCount <= offset) {
536 return false;
537 }
538
539 static constexpr auto HelperType = DispatchMsgHelperIntType<MidCount>::value;
540 return
541 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
542 dispatchTypeOffset<TAllMessages, StartIdx, MidCount>(offset, handler);
543 }
544
545 template <
546 typename TAllMessages,
547 std::size_t TFrom,
548 std::size_t TCount,
549 typename THandler>
550 static bool dispatchTypeOffset(std::size_t offset, THandler& handler)
551 {
552 static constexpr std::size_t MidOffset = TCount / 2;
553
554 if (offset < MidOffset) {
555 static constexpr auto HelperType = DispatchMsgHelperIntType<MidOffset>::value;
556 return
557 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
558 dispatchTypeOffset<TAllMessages, TFrom, MidOffset>(offset, handler);
559 }
560
561 if (MidOffset < offset) {
562 static constexpr std::size_t NextCount = TCount - (MidOffset - TFrom);
563 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
564 return
565 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
566 dispatchTypeOffset<TAllMessages, MidOffset, NextCount>(offset - MidOffset, handler);
567 }
568
569 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
570 handler.template handle<MidElemType>();
571 return true;
572 }
573
574 template <
575 typename TAllMessages,
576 std::size_t TFrom,
577 std::size_t TCount,
578 typename TId>
579 static std::size_t dispatchTypeCount(TId&& id)
580 {
581 static constexpr std::size_t StartIdx = MidRangeStartIdx<TAllMessages, TFrom, TCount>::value;
582 static_assert(StartIdx <= MidIdx<TFrom, TCount>::value, "Invalid calculation");
583
584 using MidElemType = MidElem<TAllMessages, TFrom, TCount>;
585 typename MidElemType::MsgIdParamType midId = MidElemType::doGetId();
586 if (id < midId) {
587 static constexpr std::size_t NextCount = StartIdx - TFrom;
588 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
589 return
590 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
591 dispatchTypeCount<TAllMessages, TFrom, NextCount>(id);
592 }
593
594 static constexpr std::size_t MidCount = MidRangeCount<TAllMessages, TFrom, TCount>::value;
595
596 if (midId < id) {
597 static constexpr std::size_t NewStart = StartIdx + MidCount;
598 static constexpr std::size_t NextCount = TCount - (NewStart - TFrom);
599 static constexpr auto HelperType = DispatchMsgHelperIntType<NextCount>::value;
600 return
601 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
602 dispatchTypeCount<TAllMessages, NewStart, NextCount>(id);
603 }
604
605 return MidCount;
606 }
607};
608
609template <>
610class DispatchMsgWeakStaticBinSearchHelper<DispatchMsgTypeEnum::Single>
611{
612 // static_assert(TFrom + 1 <= std::tuple_size<TAllMessages>::value,
613 // "Invalid template params");
614
615 // using Elem = typename std::tuple_element<TFrom, TAllMessages>::type;
616 // static_assert(messageHasStaticNumId<Elem>(), "Message must define static ID");
617
618 template <typename TAllMessages, std::size_t TFrom>
619 using Elem = typename std::tuple_element<TFrom, TAllMessages>::type;
620
621public:
622 template <
623 typename TAllMessages,
624 std::size_t TFrom,
625 std::size_t TCount,
626 typename TMsg,
627 typename THandler>
628 static auto dispatch(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler) ->
629 MessageInterfaceDispatchRetType<
630 typename std::decay<decltype(handler)>::type>
631 {
632 using RetType =
633 MessageInterfaceDispatchRetType<
634 typename std::decay<decltype(handler)>::type>;
635
636 if (offset != 0U) {
637 return static_cast<RetType>(handler.handle(msg));
638 }
639
640 using ElemType = Elem<TAllMessages, TFrom>;
641 typename TMsg::MsgIdParamType elemId = ElemType::doGetId();
642 if (id != elemId) {
643 return static_cast<RetType>(handler.handle(msg));
644 }
645
646 auto& castedMsg = static_cast<ElemType&>(msg);
647 return static_cast<RetType>(handler.handle(castedMsg));
648 }
649
650 template <
651 typename TAllMessages,
652 std::size_t TFrom,
653 std::size_t TCount,
654 typename TMsg,
655 typename THandler>
656 static auto dispatchOffset(std::size_t offset, TMsg& msg, THandler& handler) ->
657 MessageInterfaceDispatchRetType<
658 typename std::decay<decltype(handler)>::type>
659 {
660 using RetType =
661 MessageInterfaceDispatchRetType<
662 typename std::decay<decltype(handler)>::type>;
663
664 if (offset != 0U) {
665 return static_cast<RetType>(handler.handle(msg));
666 }
667
668 using ElemType = Elem<TAllMessages, TFrom>;
669 auto& castedMsg = static_cast<ElemType&>(msg);
670 return static_cast<RetType>(handler.handle(castedMsg));
671 }
672
673 template <
674 typename TAllMessages,
675 std::size_t TFrom,
676 std::size_t TCount,
677 typename TId,
678 typename THandler>
679 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
680 {
681 if (offset != 0U) {
682 return false;
683 }
684
685 using ElemType = Elem<TAllMessages, TFrom>;
686 typename ElemType::MsgIdParamType elemId = ElemType::doGetId();
687 if (id != elemId) {
688 return false;
689 }
690
691 handler.template handle<ElemType>();
692 return true;
693 }
694
695 template <
696 typename TAllMessages,
697 std::size_t TFrom,
698 std::size_t TCount,
699 typename THandler>
700 static bool dispatchTypeOffset(std::size_t offset, THandler& handler)
701 {
702 if (offset != 0U) {
703 return false;
704 }
705
706 using ElemType = Elem<TAllMessages, TFrom>;
707 handler.template handle<ElemType>();
708 return true;
709 }
710
711 template <
712 typename TAllMessages,
713 std::size_t TFrom,
714 std::size_t TCount,
715 typename TId>
716 static std::size_t dispatchTypeCount(TId&& id)
717 {
718 using ElemType = Elem<TAllMessages, TFrom>;
719 typename ElemType::MsgIdParamType elemId = ElemType::doGetId();
720 if (id != elemId) {
721 return 0U;
722 }
723
724 return 1U;
725 }
726};
727
728template <>
729class DispatchMsgWeakStaticBinSearchHelper<DispatchMsgTypeEnum::None>
730{
731public:
732 template <
733 typename TAllMessages,
734 std::size_t TFrom,
735 std::size_t TCount,
736 typename TMsg,
737 typename THandler>
738 static auto dispatch(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler) ->
739 MessageInterfaceDispatchRetType<
740 typename std::decay<decltype(handler)>::type>
741 {
742 static_cast<void>(id);
743 static_cast<void>(offset);
744
745 using RetType =
746 MessageInterfaceDispatchRetType<
747 typename std::decay<decltype(handler)>::type>;
748 return static_cast<RetType>(handler.handle(msg));
749 }
750
751 template <
752 typename TAllMessages,
753 std::size_t TFrom,
754 std::size_t TCount,
755 typename TMsg,
756 typename THandler>
757 static auto dispatchOffset(std::size_t offset, TMsg& msg, THandler& handler) ->
758 MessageInterfaceDispatchRetType<
759 typename std::decay<decltype(handler)>::type>
760 {
761 static_cast<void>(offset);
762
763 using RetType =
764 MessageInterfaceDispatchRetType<
765 typename std::decay<decltype(handler)>::type>;
766 return static_cast<RetType>(handler.handle(msg));
767 }
768
769 template <
770 typename TAllMessages,
771 std::size_t TFrom,
772 std::size_t TCount,
773 typename TId,
774 typename THandler>
775 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
776 {
777 static_cast<void>(id);
778 static_cast<void>(offset);
779 static_cast<void>(handler);
780 return false;
781 }
782
783 template <
784 typename TAllMessages,
785 std::size_t TFrom,
786 std::size_t TCount,
787 typename THandler>
788 static bool dispatchTypeOffset(std::size_t offset, THandler& handler)
789 {
790 static_cast<void>(offset);
791 static_cast<void>(handler);
792 return false;
793 }
794
795 template <
796 typename TAllMessages,
797 std::size_t TFrom,
798 std::size_t TCount,
799 typename TId>
800 static std::size_t dispatchTypeCount(TId&& id)
801 {
802 static_cast<void>(id);
803 return 0U;
804 }
805
806};
807
808template <typename...>
809class DispatchMsgStaticBinSearchHelper
810{
811 template <typename... TParams>
812 using EmptyTag = comms::details::tag::Tag1<>;
813
814 template <typename... TParams>
815 using StrongTag = comms::details::tag::Tag2<>;
816
817 template <typename... TParams>
818 using WeakTag = comms::details::tag::Tag3<>;
819
820 template<typename TAllMessages, typename...>
821 using StrongWeakTag =
822 typename comms::util::LazyShallowConditional<
823 allMessagesAreStrongSorted<TAllMessages>()
824 >::template Type<
825 StrongTag,
826 WeakTag,
827 TAllMessages
828 >;
829
830 template <typename TAllMessages, typename...>
831 using BinSearchTag =
832 typename comms::util::LazyShallowConditional<
833 std::tuple_size<TAllMessages>::value == 0U
834 >::template Type<
835 EmptyTag,
836 StrongWeakTag,
837 TAllMessages
838 >;
839
840 template <typename TAllMessages, typename TMsg>
841 using AdjustedTag =
842 typename comms::util::LazyShallowConditional<
843 comms::isMessageBase<TMsg>()
844 >::template Type<
845 EmptyTag,
846 BinSearchTag,
847 TAllMessages
848 >;
849
850public:
851 template <typename TAllMessages, typename TMsg, typename THandler>
852 static auto dispatch(TMsg& msg, THandler& handler) ->
853 MessageInterfaceDispatchRetType<
854 typename std::decay<decltype(handler)>::type>
855 {
856 using MsgType = typename std::decay<decltype(msg)>::type;
857 static_assert(MsgType::hasGetId(),
858 "The used message object must provide polymorphic ID retrieval function");
859 static_assert(MsgType::hasMsgIdType(),
860 "Message interface class must define its id type");
861 return dispatchInternal<TAllMessages>(msg.getId(), msg, handler, AdjustedTag<TAllMessages, MsgType>());
862 }
863
864 template <
865 typename TAllMessages,
866 typename TId,
867 typename TMsg,
868 typename THandler>
869 static auto dispatch(TId&& id, TMsg& msg, THandler& handler) ->
870 MessageInterfaceDispatchRetType<
871 typename std::decay<decltype(handler)>::type>
872 {
873 using MsgType = typename std::decay<decltype(msg)>::type;
874 static_assert(MsgType::hasMsgIdType(),
875 "Message interface class must define its id type");
876
877 using MsgIdParamType = typename MsgType::MsgIdParamType;
878 return dispatchInternal<TAllMessages>(static_cast<MsgIdParamType>(id), msg, handler, AdjustedTag<TAllMessages, MsgType>());
879 }
880
881 template <
882 typename TAllMessages,
883 typename TId,
884 typename TMsg,
885 typename THandler>
886 static auto dispatch(TId&& id, std::size_t offset, TMsg& msg, THandler& handler) ->
887 MessageInterfaceDispatchRetType<
888 typename std::decay<decltype(handler)>::type>
889 {
890 using MsgType = typename std::decay<decltype(msg)>::type;
891 static_assert(MsgType::hasMsgIdType(),
892 "Message interface class must define its id type");
893
894 using MsgIdParamType = typename MsgType::MsgIdParamType;
895 return dispatchInternal<TAllMessages>(static_cast<MsgIdParamType>(id), offset, msg, handler, AdjustedTag<TAllMessages, MsgType>());
896 }
897
898 template <typename TAllMessages, typename TId, typename THandler>
899 static bool dispatchType(TId&& id, THandler& handler)
900 {
901 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), handler, BinSearchTag<TAllMessages>());
902 }
903
904 template <typename TAllMessages, typename TId, typename THandler>
905 static bool dispatchType(TId&& id, std::size_t offset, THandler& handler)
906 {
907 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), offset, handler, BinSearchTag<TAllMessages>());
908 }
909
910 template <typename TAllMessages, typename TId>
911 static std::size_t dispatchTypeCount(TId&& id)
912 {
913 return dispatchTypeCountInternal<TAllMessages>(std::forward<TId>(id), BinSearchTag<TAllMessages>());
914 }
915
916private:
917 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
918 static auto dispatchInternal(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler, EmptyTag<TParams...>) ->
919 MessageInterfaceDispatchRetType<
920 typename std::decay<decltype(handler)>::type>
921 {
922 return dispatchInternal<TAllMessages>(id, 0U, msg, handler, EmptyTag<>());
923 }
924
925 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
926 static auto dispatchInternal(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler, EmptyTag<TParams...>) ->
927 MessageInterfaceDispatchRetType<
928 typename std::decay<decltype(handler)>::type>
929 {
930 static_cast<void>(id);
931 static_cast<void>(offset);
932 using RetType =
933 MessageInterfaceDispatchRetType<
934 typename std::decay<decltype(handler)>::type>;
935 return static_cast<RetType>(handler.handle(msg));
936 }
937
938 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
939 static auto dispatchInternal(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler, StrongTag<TParams...>) ->
940 MessageInterfaceDispatchRetType<
941 typename std::decay<decltype(handler)>::type>
942 {
943 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
944 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
945 return
946 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
947 dispatch<TAllMessages, 0, Count>(id, msg, handler);
948 }
949
950 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
951 static auto dispatchInternal(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler, StrongTag<TParams...>) ->
952 MessageInterfaceDispatchRetType<
953 typename std::decay<decltype(handler)>::type>
954 {
955 if (offset != 0U) {
956 using RetType =
957 MessageInterfaceDispatchRetType<
958 typename std::decay<decltype(handler)>::type>;
959 return static_cast<RetType>(handler.handle(msg));
960
961 }
962
963 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
964 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
965 return
966 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
967 dispatch<TAllMessages, 0, Count>(id, msg, handler);
968
969 }
970
971 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
972 static auto dispatchInternal(typename TMsg::MsgIdParamType id, TMsg& msg, THandler& handler, WeakTag<TParams...>) ->
973 MessageInterfaceDispatchRetType<
974 typename std::decay<decltype(handler)>::type>
975 {
976 return dispatchInternal<TAllMessages>(id, 0U, msg, handler, WeakTag<>());
977 }
978
979 template <typename TAllMessages, typename TMsg, typename THandler, typename... TParams>
980 static auto dispatchInternal(typename TMsg::MsgIdParamType id, std::size_t offset, TMsg& msg, THandler& handler, WeakTag<TParams...>) ->
981 MessageInterfaceDispatchRetType<
982 typename std::decay<decltype(handler)>::type>
983 {
984 static_assert(allMessagesAreWeakSorted<TAllMessages>(),
985 "The message types in the provided tuple must be sorted by their IDs");
986
987 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
988 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
989 return
990 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
991 dispatch<TAllMessages, 0, Count>(id, offset, msg, handler);
992
993 }
994
995 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
996 static bool dispatchTypeInternal(TId&& id, THandler& handler, EmptyTag<TParams...>)
997 {
998 return dispatchTypeInternal<TAllMessages>(id, 0U, handler, EmptyTag<>());
999 }
1000
1001 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1002 static bool dispatchTypeInternal(TId&& id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
1003 {
1004 static_cast<void>(id);
1005 static_cast<void>(offset);
1006 static_cast<void>(handler);
1007 return false;
1008 }
1009
1010 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1011 static bool dispatchTypeInternal(TId&& id, THandler& handler, StrongTag<TParams...>)
1012 {
1013 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1014 static_assert(comms::isMessageBase<FirstMsgType>(),
1015 "The type in the tuple are expected to be proper messages");
1016 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1017 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1018
1019 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
1020 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
1021 return
1022 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
1023 dispatchType<TAllMessages, 0, Count>(static_cast<MsgIdParamType>(id), handler);
1024 }
1025
1026 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1027 static bool dispatchTypeInternal(TId&& id, std::size_t offset, THandler& handler, StrongTag<TParams...>)
1028 {
1029 if (offset != 0U) {
1030 return false;
1031
1032 }
1033 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), handler, StrongTag<>());
1034 }
1035
1036 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1037 static bool dispatchTypeInternal(TId&& id, THandler& handler, WeakTag<TParams...>)
1038 {
1039 return dispatchTypeInternal<TAllMessages>(std::forward<TId>(id), 0U, handler, WeakTag<>());
1040 }
1041
1042 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1043 static bool dispatchTypeInternal(TId&& id, std::size_t offset, THandler& handler, WeakTag<TParams...>)
1044 {
1045 static_assert(allMessagesAreWeakSorted<TAllMessages>(),
1046 "The message types in the provided tuple must be sorted by their IDs");
1047
1048 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1049 static_assert(comms::isMessageBase<FirstMsgType>(),
1050 "The type in the tuple are expected to be proper messages");
1051 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1052 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1053 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
1054 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
1055 return
1056 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
1057 dispatchType<TAllMessages, 0, Count>(static_cast<MsgIdParamType>(id), offset, handler);
1058
1059 }
1060
1061 template <typename TAllMessages, typename TId, typename... TParams>
1062 static std::size_t dispatchTypeCountInternal(TId&& id, EmptyTag<TParams...>)
1063 {
1064 static_cast<void>(id);
1065 return 0U;
1066 }
1067
1068 template <typename TAllMessages, typename TId, typename... TParams>
1069 static std::size_t dispatchTypeCountInternal(TId&& id, StrongTag<TParams...>)
1070 {
1071 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1072 static_assert(comms::isMessageBase<FirstMsgType>(),
1073 "The type in the tuple are expected to be proper messages");
1074 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1075 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1076
1077 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
1078 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
1079 return
1080 DispatchMsgStrongStaticBinSearchHelper<HelperType>::template
1081 dispatchTypeCount<TAllMessages, 0, Count>(static_cast<MsgIdParamType>(id));
1082 }
1083
1084 template <typename TAllMessages, typename TId, typename... TParams>
1085 static std::size_t dispatchTypeCountInternal(TId&& id, WeakTag<TParams...>)
1086 {
1087 static_assert(allMessagesAreWeakSorted<TAllMessages>(),
1088 "The message types in the provided tuple must be sorted by their IDs");
1089
1090 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1091 static_assert(comms::isMessageBase<FirstMsgType>(),
1092 "The type in the tuple are expected to be proper messages");
1093 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1094 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1095 static constexpr std::size_t Count = std::tuple_size<TAllMessages>::value;
1096 static constexpr auto HelperType = DispatchMsgHelperIntType<Count>::value;
1097 return
1098 DispatchMsgWeakStaticBinSearchHelper<HelperType>::template
1099 dispatchTypeCount<TAllMessages, 0, Count>(static_cast<MsgIdParamType>(id));
1100
1101 }
1102};
1103
1104} // namespace details
1105
1106} // namespace comms
Provides common base class for the custom messages with default implementation.
Contains definition of Message object interface and various base classes for custom messages.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1500
Main namespace for all classes / functions of COMMS library.
Replacement to std::conditional.
Definition type_traits.h:32
Replacement to some types from standard type_traits.