COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
MessageImplOptionsParser.h
1//
2// Copyright 2015 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#pragma once
11
12#include "comms/details/MessageImplBases.h"
13#include "comms/options.h"
15
16#include <limits>
17#include <tuple>
18
19namespace comms
20{
21
22namespace details
23{
24
25template <typename T, T TValue>
26struct MessageImplValueWrapper
27{
28 static constexpr T Value = TValue;
29};
30
31template <typename... TOptions>
32class MessageImplOptionsParser;
33
34template <>
35class MessageImplOptionsParser<>
36{
37public:
38 static constexpr bool HasFieldsImpl = false;
39 static constexpr bool HasMsgType = false;
40 static constexpr bool HasNoReadImpl = false;
41 static constexpr bool HasNoWriteImpl = false;
42 static constexpr bool HasNoValidImpl = false;
43 static constexpr bool HasNoLengthImpl = false;
44 static constexpr bool HasNoRefreshImpl = false;
45 static constexpr bool HasCustomRefresh = false;
46 static constexpr bool HasVersionDependentFields = false;
47 static constexpr bool HasFieldsWithNonDefaultRefresh = false;
48 static constexpr bool HasNoDispatchImpl = false;
49 static constexpr bool HasStaticMsgId = false;
50 static constexpr bool HasDoGetId = false;
51 static constexpr bool HasNoIdImpl = false;
52 static constexpr bool HasName = false;
53 static constexpr bool HasFailOnInvalid = false;
54
55 using Fields = std::tuple<>;
56 using MsgType = void;
57 static constexpr std::intmax_t MsgId = std::numeric_limits<std::intmax_t>::max();
58 using FailOnInvalidStatusWrapper = MessageImplValueWrapper<comms::ErrorStatus, comms::ErrorStatus::InvalidMsgData>;
59
60 template <typename TBase>
61 using BuildFieldsImpl = TBase;
62
63 template <typename TBase>
64 using BuildVersionImpl = TBase;
65
66 template <typename TBase>
67 using BuildReadImpl = TBase;
68
69 template <typename TBase>
70 using BuildWriteImpl = TBase;
71
72 template <typename TBase>
73 using BuildValidImpl = TBase;
74
75 template <typename TBase>
76 using BuildLengthImpl = TBase;
77
78 template <typename TBase>
79 using BuildRefreshImpl = TBase;
80
81 template <typename TBase>
82 using BuildDispatchImpl = TBase;
83
84 template <typename TBase>
85 using BuildStaticMsgId = TBase;
86
87 template <typename TBase>
88 using BuildMsgIdImpl = TBase;
89
90 template <typename TBase>
91 using BuildNameImpl = TBase;
92
93 template <typename TBase>
94 using BuildFailOnInvalidImpl = TBase;
95};
96
97template <std::intmax_t TId,
98 typename... TOptions>
99class MessageImplOptionsParser<
100 comms::option::def::StaticNumIdImpl<TId>,
101 TOptions...> : public MessageImplOptionsParser<TOptions...>
102{
103 using BaseImpl = MessageImplOptionsParser<TOptions...>;
104
105 static_assert(!BaseImpl::HasStaticMsgId,
106 "comms::option::def::StaticNumIdImpl option is used more than once");
107 static_assert(!BaseImpl::HasNoIdImpl,
108 "comms::option::app::NoIdImpl and comms::option::def::StaticNumIdImpl options cannot be used together");
109public:
110 static constexpr bool HasStaticMsgId = true;
111 static constexpr std::intmax_t MsgId = TId;
112
113 template <typename TBase>
114 using BuildStaticMsgId =
116 TBase::hasMsgIdType() // most likely to be true
117 >::template Type<
118 MessageImplStaticNumIdBase<TBase, MsgId>,
119 TBase
120 >;
121
122 template <typename TBase>
123 using BuildMsgIdImpl =
124 typename comms::util::LazyShallowDeepConditional<
125 TBase::hasGetId() && (!BaseImpl::HasNoIdImpl)
126 >::template Type<
127 MessageImplPolymorhpicStaticNumIdBase,
128 comms::util::TypeDeepWrap,
129 TBase, typename BaseImpl::MsgType
130 >;
131};
132
133template <typename... TOptions>
134class MessageImplOptionsParser<
135 comms::option::app::NoDispatchImpl,
136 TOptions...> : public MessageImplOptionsParser<TOptions...>
137{
138public:
139 static constexpr bool HasNoDispatchImpl = true;
140
141 template <typename TBase>
142 using BuildDispatchImpl = TBase;
143};
144
145template <typename TFields,
146 typename... TOptions>
147class MessageImplOptionsParser<
148 comms::option::def::FieldsImpl<TFields>,
149 TOptions...> : public MessageImplOptionsParser<TOptions...>
150{
151 using BaseImpl = MessageImplOptionsParser<TOptions...>;
152
153 static_assert(!BaseImpl::HasFieldsImpl,
154 "comms::option::def::FieldsImpl option is used more than once");
155public:
156 static constexpr bool HasFieldsImpl = true;
157 using Fields = TFields;
158 static constexpr bool HasVersionDependentFields = MessageImplFieldsContainer<Fields>::areFieldsVersionDependent();
159 static constexpr bool HasFieldsWithNonDefaultRefresh = MessageImplFieldsContainer<Fields>::doFieldsHaveNonDefaultRefresh();
160
161 template <typename TBase>
162 using BuildFieldsImpl = MessageImplFieldsBase<TBase, Fields>;
163
164 template <typename TBase>
165 using BuildFailOnInvalidImpl =
166 typename comms::util::LazyShallowDeepConditional<
167 BaseImpl::HasFailOnInvalid
168 >::template Type<
169 MessageImplFailOnInvalidBase,
170 comms::util::TypeDeepWrap,
171 TBase, typename BaseImpl::MsgType, typename BaseImpl::FailOnInvalidStatusWrapper
172 >;
173
174 template <typename TBase>
175 using BuildVersionImpl =
176 typename comms::util::LazyShallowDeepConditional<
177 TBase::hasVersionInTransportFields()
178 >::template Type<
179 MessageImplVersionBase,
180 comms::util::TypeDeepWrap,
181 TBase
182 >;
183
184 template <typename TBase>
185 using BuildReadImpl =
186 typename comms::util::LazyShallowDeepConditional<
187 TBase::hasRead() && (!BaseImpl::HasNoReadImpl)
188 >::template Type<
189 MessageImplFieldsReadImplBase,
190 comms::util::TypeDeepWrap,
191 TBase, typename BaseImpl::MsgType
192 >;
193
194 template <typename TBase>
195 using BuildWriteImpl =
196 typename comms::util::LazyShallowDeepConditional<
197 TBase::hasWrite() && (!BaseImpl::HasNoWriteImpl)
198 >::template Type<
199 MessageImplFieldsWriteImplBase,
200 comms::util::TypeDeepWrap,
201 TBase, typename BaseImpl::MsgType
202 >;
203
204 template <typename TBase>
205 using BuildValidImpl =
206 typename comms::util::LazyShallowDeepConditional<
207 TBase::hasValid() && (!BaseImpl::HasNoValidImpl)
208 >::template Type<
209 MessageImplFieldsValidBase,
210 comms::util::TypeDeepWrap,
211 TBase, typename BaseImpl::MsgType
212 >;
213
214 template <typename TBase>
215 using BuildLengthImpl =
216 typename comms::util::LazyShallowDeepConditional<
217 TBase::hasLength() && (!BaseImpl::HasNoLengthImpl)
218 >::template Type<
219 MessageImplFieldsLengthBase,
220 comms::util::TypeDeepWrap,
221 TBase, typename BaseImpl::MsgType
222 >;
223
224 template <typename TBase>
225 using BuildRefreshImpl =
226 typename comms::util::LazyShallowDeepConditional<
227 (TBase::hasRefresh()) &&
228 (!BaseImpl::HasNoRefreshImpl) &&
229 (
230 BaseImpl::HasCustomRefresh ||
231 HasFieldsWithNonDefaultRefresh ||
232 (TBase::hasVersionInTransportFields() && HasVersionDependentFields)
233 )
234 >::template Type<
235 MessageImplRefreshBase,
236 comms::util::TypeDeepWrap,
237 TBase, typename BaseImpl::MsgType
238 >;
239};
240
241template <typename... TOptions>
242class MessageImplOptionsParser<
243 comms::option::def::NoIdImpl,
244 TOptions...> : public MessageImplOptionsParser<TOptions...>
245{
246 using BaseImpl = MessageImplOptionsParser<TOptions...>;
247
248 static_assert(!BaseImpl::HasNoIdImpl,
249 "comms::option::def::NoIdImpl option is used more than once");
250 static_assert(!BaseImpl::HasStaticMsgId,
251 "comms::option::def::NoIdImpl and comms::option::def::StaticNumIdImpl options cannot be used together");
252public:
253 static constexpr bool HasNoIdImpl = true;
254
255 template <typename TBase>
256 using BuildMsgIdImpl =
257 typename comms::util::LazyShallowDeepConditional<
258 TBase::hasGetId()
259 >::template Type<
260 MessageImplNoIdBase,
261 comms::util::TypeDeepWrap,
262 TBase
263 >;
264};
265
266template <typename... TOptions>
267class MessageImplOptionsParser<
268 comms::option::app::NoReadImpl,
269 TOptions...> : public MessageImplOptionsParser<TOptions...>
270{
271public:
272 static constexpr bool HasNoReadImpl = true;
273
274 template <typename TBase>
275 using BuildReadImpl = TBase;
276};
277
278template <typename... TOptions>
279class MessageImplOptionsParser<
280 comms::option::app::NoWriteImpl,
281 TOptions...> : public MessageImplOptionsParser<TOptions...>
282{
283public:
284 static constexpr bool HasNoWriteImpl = true;
285
286 template <typename TBase>
287 using BuildWriteImpl = TBase;
288};
289
290template <typename... TOptions>
291class MessageImplOptionsParser<
292 comms::option::app::NoLengthImpl,
293 TOptions...> : public MessageImplOptionsParser<TOptions...>
294{
295public:
296 static constexpr bool HasNoLengthImpl = true;
297
298 template <typename TBase>
299 using BuildLengthImpl = TBase;
300};
301
302template <typename... TOptions>
303class MessageImplOptionsParser<
304 comms::option::app::NoValidImpl,
305 TOptions...> : public MessageImplOptionsParser<TOptions...>
306{
307public:
308 static constexpr bool HasNoValidImpl = true;
309
310 template <typename TBase>
311 using BuildValidImpl = TBase;
312};
313
314template <typename... TOptions>
315class MessageImplOptionsParser<
316 comms::option::app::NoRefreshImpl,
317 TOptions...> : public MessageImplOptionsParser<TOptions...>
318{
319public:
320 static constexpr bool HasNoRefreshImpl = true;
321
322 template <typename TBase>
323 using BuildRefreshImpl = TBase;
324};
325
326template <typename... TOptions>
327class MessageImplOptionsParser<
328 comms::option::def::HasCustomRefresh,
329 TOptions...> : public MessageImplOptionsParser<TOptions...>
330{
331 using BaseImpl = MessageImplOptionsParser<TOptions...>;
332public:
333 static constexpr bool HasCustomRefresh = true;
334
335 template <typename TBase>
336 using BuildRefreshImpl =
337 typename comms::util::LazyShallowDeepConditional<
338 (TBase::hasRefresh()) && (!BaseImpl::HasNoRefreshImpl)
339 >::template Type<
340 MessageImplRefreshBase,
341 comms::util::TypeDeepWrap,
342 TBase, typename BaseImpl::MsgType
343 >;
344};
345
346template <typename... TOptions>
347class MessageImplOptionsParser<
348 comms::option::def::HasName,
349 TOptions...> : public MessageImplOptionsParser<TOptions...>
350{
351 using BaseImpl = MessageImplOptionsParser<TOptions...>;
352
353public:
354 static constexpr bool HasName = true;
355
356 template <typename TBase>
357 using BuildNameImpl =
358 typename comms::util::LazyShallowDeepConditional<
359 TBase::hasName() && BaseImpl::HasMsgType
360 >::template Type<
361 MessageImplNameBase,
362 comms::util::TypeDeepWrap,
363 TBase, typename BaseImpl::MsgType
364 >;
365};
366
367template <typename... TOptions>
368class MessageImplOptionsParser<
369 comms::option::def::HasDoGetId,
370 TOptions...> : public MessageImplOptionsParser<TOptions...>
371{
372 using BaseImpl = MessageImplOptionsParser<TOptions...>;
373public:
374 static constexpr bool HasDoGetId = true;
375
376 template <typename TBase>
377 using BuildMsgIdImpl =
378 typename comms::util::LazyShallowDeepConditional<
379 TBase::hasGetId() && (!BaseImpl::HasNoIdImpl) &&
380 (BaseImpl::HasStaticMsgId || BaseImpl::HasMsgType)
381 >::template Type<
382 MessageImplPolymorhpicStaticNumIdBase,
383 comms::util::TypeDeepWrap,
384 TBase, typename BaseImpl::MsgType
385 >;
386};
387
388template <typename TMsgType,
389 typename... TOptions>
390class MessageImplOptionsParser<
391 comms::option::def::MsgType<TMsgType>,
392 TOptions...> : public MessageImplOptionsParser<TOptions...>
393{
394 using BaseImpl = MessageImplOptionsParser<TOptions...>;
395
396 static_assert(!BaseImpl::HasMsgType,
397 "comms::option::def::MsgType option is used more than once");
398public:
399 static constexpr bool HasMsgType = true;
400 using MsgType = TMsgType;
401
402 template <typename TBase>
403 using BuildFailOnInvalidImpl =
404 typename comms::util::LazyShallowDeepConditional<
405 BaseImpl::HasFieldsImpl && BaseImpl::HasFailOnInvalid
406 >::template Type<
407 MessageImplFailOnInvalidBase,
408 comms::util::TypeDeepWrap,
409 TBase, MsgType, typename BaseImpl::FailOnInvalidStatusWrapper
410 >;
411
412 template <typename TBase>
413 using BuildReadImpl =
414 typename comms::util::LazyShallowDeepConditional<
415 TBase::hasRead() && (!BaseImpl::HasNoReadImpl)
416 >::template Type<
417 MessageImplFieldsReadImplBase,
418 comms::util::TypeDeepWrap,
419 TBase, MsgType
420 >;
421
422 template <typename TBase>
423 using BuildWriteImpl =
424 typename comms::util::LazyShallowDeepConditional<
425 TBase::hasWrite() && (!BaseImpl::HasNoWriteImpl)
426 >::template Type<
427 MessageImplFieldsWriteImplBase,
428 comms::util::TypeDeepWrap,
429 TBase, MsgType
430 >;
431
432 template <typename TBase>
433 using BuildValidImpl =
434 typename comms::util::LazyShallowDeepConditional<
435 TBase::hasValid() && (!BaseImpl::HasNoValidImpl)
436 >::template Type<
437 MessageImplFieldsValidBase,
438 comms::util::TypeDeepWrap,
439 TBase, MsgType
440 >;
441
442 template <typename TBase>
443 using BuildLengthImpl =
444 typename comms::util::LazyShallowDeepConditional<
445 TBase::hasLength() && (!BaseImpl::HasNoLengthImpl)
446 >::template Type<
447 MessageImplFieldsLengthBase,
448 comms::util::TypeDeepWrap,
449 TBase, MsgType
450 >;
451
452 template <typename TBase>
453 using BuildRefreshImpl =
454 typename comms::util::LazyShallowDeepConditional<
455 (TBase::hasRefresh()) &&
456 (!BaseImpl::HasNoRefreshImpl) &&
457 (
458 BaseImpl::HasCustomRefresh ||
459 BaseImpl::HasFieldsWithNonDefaultRefresh ||
460 (TBase::hasVersionInTransportFields() && BaseImpl::HasVersionDependentFields)
461 )
462 >::template Type<
463 MessageImplRefreshBase,
464 comms::util::TypeDeepWrap,
465 TBase, MsgType
466 >;
467
468 template <typename TBase>
469 using BuildDispatchImpl =
470 typename comms::util::LazyShallowDeepConditional<
471 TBase::hasDispatch() && (!BaseImpl::HasNoDispatchImpl)
472 >::template Type<
473 MessageImplDispatchBase,
474 comms::util::TypeDeepWrap,
475 TBase, MsgType
476 >;
477
478 template <typename TBase>
479 using BuildMsgIdImpl =
480 typename comms::util::LazyShallowDeepConditional<
481 TBase::hasGetId() && (!BaseImpl::HasNoIdImpl) &&
482 (BaseImpl::HasStaticMsgId || BaseImpl::HasDoGetId)
483 >::template Type<
484 MessageImplPolymorhpicStaticNumIdBase,
485 comms::util::TypeDeepWrap,
486 TBase, MsgType
487 >;
488
489 template <typename TBase>
490 using BuildNameImpl =
491 typename comms::util::LazyShallowDeepConditional<
492 TBase::hasName() && BaseImpl::HasName
493 >::template Type<
494 MessageImplNameBase,
495 comms::util::TypeDeepWrap,
496 TBase, MsgType
497 >;
498};
499
500template <comms::ErrorStatus TStatus, typename... TOptions>
501class MessageImplOptionsParser<
502 comms::option::def::FailOnInvalid<TStatus>,
503 TOptions...> : public MessageImplOptionsParser<TOptions...>
504{
505 using BaseImpl = MessageImplOptionsParser<TOptions...>;
506
507public:
508 static constexpr bool HasFailOnInvalid = true;
509 using FailOnInvalidStatusWrapper = MessageImplValueWrapper<comms::ErrorStatus, TStatus>;
510
511 template <typename TBase>
512 using BuildFailOnInvalidImpl =
513 typename comms::util::LazyShallowDeepConditional<
514 BaseImpl::HasFieldsImpl
515 >::template Type<
516 MessageImplFailOnInvalidBase,
517 comms::util::TypeDeepWrap,
518 TBase, typename BaseImpl::MsgType, FailOnInvalidStatusWrapper
519 >;
520};
521
522template <typename... TOptions>
523class MessageImplOptionsParser<
524 comms::option::app::EmptyOption,
525 TOptions...> : public MessageImplOptionsParser<TOptions...>
526{
527};
528
529template <typename... TBundledOptions, typename... TOptions>
530class MessageImplOptionsParser<
531 std::tuple<TBundledOptions...>,
532 TOptions...> : public MessageImplOptionsParser<TBundledOptions..., TOptions...>
533{
534};
535
536} // namespace details
537
538} // namespace comms
539
comms::option::def::HasName HasName
Same as comms::option::def::HasName.
Definition options.h:1917
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1500
comms::option::def::HasDoGetId HasDoGetId
Same as comms::option::def::HasDoGetId.
Definition options.h:1528
comms::option::def::HasCustomRefresh HasCustomRefresh
Same as comms::option::def::HasCustomRefresh.
Definition options.h:1913
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
STL namespace.
Contains definition of all the options used by the COMMS library.
Replacement to std::conditional.
Definition type_traits.h:32
Replacement to some types from standard type_traits.