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