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