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