COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
MessageInterfaceBases.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/Assert.h"
13#include "comms/details/tag.h"
14#include "comms/ErrorStatus.h"
15#include "comms/Field.h"
16#include "comms/options.h"
17#include "comms/util/access.h"
18#include "comms/util/Tuple.h"
20
21#include <cstddef>
22#include <tuple>
23#include <type_traits>
24
25namespace comms
26{
27
28namespace details
29{
30
31using MessageInterfaceEmptyBase = comms::util::EmptyStruct<>;
32
33// ------------------------------------------------------
34
35template <typename TEndian>
36class MessageInterfaceEndianBase
37{
38public:
39 using Endian = TEndian;
40
42
43protected:
44 ~MessageInterfaceEndianBase() noexcept = default;
45
46 template <typename T, typename TIter>
47 static void writeData(T value, TIter& iter)
48 {
49 writeData<sizeof(T), T>(value, iter);
50 }
51
52 template <std::size_t TSize, typename T, typename TIter>
53 static void writeData(T value, TIter& iter)
54 {
55 static_assert(TSize <= sizeof(T),
56 "Cannot put more bytes than type contains");
57 return util::writeData<TSize, T>(value, iter, Endian());
58 }
59
60 template <typename T, typename TIter>
61 static T readData(TIter& iter)
62 {
63 return readData<T, sizeof(T)>(iter);
64 }
65
66 template <typename T, std::size_t TSize, typename TIter>
67 static T readData(TIter& iter)
68 {
69 static_assert(TSize <= sizeof(T),
70 "Cannot get more bytes than type contains");
71 return util::readData<T, TSize>(iter, Endian());
72 }
73};
74
75// ------------------------------------------------------
76
77template <typename TBase, typename TId>
78class MessageInterfaceIdTypeBase : public TBase
79{
80public:
81 using MsgIdType = TId;
82 using MsgIdParamType =
84 std::is_integral<MsgIdType>::value || std::is_enum<MsgIdType>::value
85 >::template Type<
87 const MsgIdType&
88 >;
89
90protected:
91 ~MessageInterfaceIdTypeBase() noexcept = default;
92};
93
94// ------------------------------------------------------
95
96template <typename TBase, typename TFields>
97class MessageInterfaceExtraTransportFieldsBase : public TBase
98{
99public:
100 using TransportFields = TFields;
101
102 static_assert(comms::util::isTuple<TransportFields>(),
103 "TransportFields is expected to be tuple");
104
105 TransportFields& transportFields()
106 {
107 return m_transportFields;
108 }
109
110 const TransportFields& transportFields() const
111 {
112 return m_transportFields;
113 }
114
115protected:
116 ~MessageInterfaceExtraTransportFieldsBase() noexcept = default;
117private:
118 TransportFields m_transportFields;
119};
120
121// ------------------------------------------------------
122
123template <typename TBase, std::size_t TIdx>
124class MessageInterfaceVersionInExtraTransportFieldsBase : public TBase
125{
126public:
127 using TransportFields = typename TBase::TransportFields;
128
129 static_assert(comms::util::isTuple<TransportFields>(),
130 "TransportFields is expected to be tuple");
131
132 static_assert(TIdx < std::tuple_size<TransportFields>::value,
133 "Index provided to comms::option::def::VersionInExtraTransportFields exceeds size of the tuple");
134
135 using VersionType = typename std::tuple_element<TIdx, TransportFields>::type::ValueType;
136
138 {
139 return std::get<TIdx>(TBase::transportFields()).value();
140 }
141
142 const VersionType& version() const
143 {
144 return std::get<TIdx>(TBase::transportFields()).value();
145 }
146
147protected:
148 ~MessageInterfaceVersionInExtraTransportFieldsBase() noexcept = default;
149};
150
151// ------------------------------------------------------
152
153template <typename TBase>
154class MessageInterfaceIdInfoBase : public TBase
155{
156public:
157 using MsgIdParamType = typename TBase::MsgIdParamType;
158
159 MsgIdParamType getId() const
160 {
161 return getIdImpl();
162 }
163
164protected:
165 ~MessageInterfaceIdInfoBase() noexcept = default;
166 virtual MsgIdParamType getIdImpl() const = 0;
167};
168
169// ------------------------------------------------------
170
171template <typename TBase, typename TReadIter>
172class MessageInterfaceReadBase : public TBase
173{
174public:
175 using ReadIterator = TReadIter;
176 comms::ErrorStatus read(ReadIterator& iter, std::size_t size)
177 {
178 return this->readImpl(iter, size);
179 }
180
181protected:
182 ~MessageInterfaceReadBase() noexcept = default;
183 virtual comms::ErrorStatus readImpl(ReadIterator& iter, std::size_t size)
184 {
185 static_cast<void>(iter);
186 static_cast<void>(size);
188 }
189};
190
191// ------------------------------------------------------
192
193template <typename TBase, typename TWriteIter>
194class MessageInterfaceWriteBase : public TBase
195{
196public:
197 using WriteIterator = TWriteIter;
198 comms::ErrorStatus write(WriteIterator& iter, std::size_t size) const
199 {
200 return this->writeImpl(iter, size);
201 }
202
203protected:
204 ~MessageInterfaceWriteBase() noexcept = default;
205 virtual comms::ErrorStatus writeImpl(WriteIterator& iter, std::size_t size) const
206 {
207 static_cast<void>(iter);
208 static_cast<void>(size);
210 }
211};
212
213// ------------------------------------------------------
214
215template <typename TBase>
216class MessageInterfaceValidBase : public TBase
217{
218public:
219 bool valid() const
220 {
221 return validImpl();
222 }
223
224protected:
225 ~MessageInterfaceValidBase() noexcept = default;
226 virtual bool validImpl() const
227 {
228 return true;
229 }
230};
231
232// ------------------------------------------------------
233
234template <typename TBase>
235class MessageInterfaceLengthBase : public TBase
236{
237public:
238 std::size_t length() const
239 {
240 return lengthImpl();
241 }
242
243protected:
244 ~MessageInterfaceLengthBase() noexcept = default;
245 virtual std::size_t lengthImpl() const
246 {
247 static constexpr bool Not_overriden = false;
248 static_cast<void>(Not_overriden);
249 COMMS_ASSERT(Not_overriden);
250 return 0;
251 }
252};
253
254// ------------------------------------------------------
255
256template <class T, class R = void>
257struct MessageInterfaceIfHasRetType { using Type = R; };
258
259template <class T, class Enable = void>
260struct MessageInterfaceDispatchRetTypeHelper
261{
262 using Type = void;
263};
264
265template <class T>
266struct MessageInterfaceDispatchRetTypeHelper<T, typename MessageInterfaceIfHasRetType<typename T::RetType>::Type>
267{
268 using Type = typename T::RetType;
269};
270
271template <class T>
272using MessageInterfaceDispatchRetType = typename MessageInterfaceDispatchRetTypeHelper<T>::Type;
273
274template <typename TBase, typename THandler>
275class MessageInterfaceHandlerBase : public TBase
276{
277public:
278 using Handler = THandler;
279 using DispatchRetType = MessageInterfaceDispatchRetType<Handler>;
280
281 DispatchRetType dispatch(Handler& handler)
282 {
283 return dispatchImpl(handler);
284 }
285
286protected:
287 ~MessageInterfaceHandlerBase() noexcept = default;
288 virtual DispatchRetType dispatchImpl(Handler& handler)
289 {
290 static_cast<void>(handler);
291 static constexpr bool Must_not_be_called = false;
292 static_cast<void>(Must_not_be_called);
293 COMMS_ASSERT(Must_not_be_called);
294 using Tag =
296 std::is_void<DispatchRetType>::value
297 >::template Type<
298 VoidHandleRetTypeTag,
299 NonVoidHandleRetTypeTag
300 >;
301 return dispatchInternal(Tag());
302 }
303
304private:
305 using VoidHandleRetTypeTag = comms::details::tag::Tag1<>;
306 using NonVoidHandleRetTypeTag = comms::details::tag::Tag2<>;
307
308 static DispatchRetType dispatchInternal(VoidHandleRetTypeTag)
309 {
310 return;
311 }
312
313 static DispatchRetType dispatchInternal(NonVoidHandleRetTypeTag)
314 {
315 using RetTypeInternal = typename std::decay<DispatchRetType>::type;
316 static const RetTypeInternal Ret = RetTypeInternal();
317 return Ret;
318 }
319};
320
321// ------------------------------------------------------
322
323template <typename TBase>
324class MessageInterfaceRefreshBase : public TBase
325{
326public:
327 bool refresh()
328 {
329 return refreshImpl();
330 }
331
332protected:
333 ~MessageInterfaceRefreshBase() noexcept = default;
334 virtual bool refreshImpl()
335 {
336 return false;
337 }
338};
339
340// ------------------------------------------------------
341
342template <typename TBase>
343class MessageInterfaceNameBase : public TBase
344{
345public:
346 const char* name() const
347 {
348 return nameImpl();
349 }
350
351protected:
352 ~MessageInterfaceNameBase() noexcept = default;
353 virtual const char* nameImpl() const = 0;
354};
355
356// ------------------------------------------------------
357
358template <typename TBase>
359class MessageInterfaceVirtDestructorBase : public TBase
360{
361protected:
362 virtual ~MessageInterfaceVirtDestructorBase() noexcept = default;
363};
364
365} // namespace details
366
367} // namespace comms
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
This file contain definition of error statuses used by comms module.
Contains definition of comms::Field class.
Contains various tuple type manipulation classes and functions.
Contains functions for raw data access / (de)serialization.
Base class to all the field classes.
Definition Field.h:36
comms::option::app::WriteIterator< TIter > WriteIterator
Same as comms::option::app::WriteIterator.
Definition options.h:1983
comms::option::app::Handler< T > Handler
Same as comms::option::app::Handler.
Definition options.h:2008
comms::option::app::ReadIterator< TIter > ReadIterator
Same as comms::option::app::ReadIterator.
Definition options.h:1978
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition options.h:1930
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition options.h:1473
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition options.h:1486
T readData(TIter &iter, const traits::endian::Big &endian)
Same as readBig<T, TIter>()
Definition access.h:775
void writeData(T value, TIter &iter, const traits::endian::Big &endian)
Same as writeBig<T, TIter>()
Definition access.h:707
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
@ NotSupported
The operation is not supported.
constexpr unsigned version()
Version of the COMMS library as single numeric value.
Definition version.h:66
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.