COMMS
Template library intended to help with implementation of communication protocols.
Message.h
Go to the documentation of this file.
1 //
2 // Copyright 2014 - 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 
11 
12 #pragma once
13 
14 #include <cstdint>
15 #include <memory>
16 #include <type_traits>
17 
18 #include "comms/ErrorStatus.h"
19 #include "comms/Assert.h"
20 #include "comms/Field.h"
21 
22 #include "comms/util/type_traits.h"
23 #include "comms/details/MessageInterfaceBuilder.h"
24 #include "comms/details/transport_fields_access.h"
25 #include "comms/details/detect.h"
26 #include "comms/details/MessageIdTypeRetriever.h"
27 #include "comms/details/field_alias.h"
28 
29 namespace comms
30 {
31 
78 template <typename... TOptions>
79 class Message : public details::MessageInterfaceBuilderT<TOptions...>
80 {
81  using BaseImpl = details::MessageInterfaceBuilderT<TOptions...>;
82 public:
83 
86  using InterfaceOptions = details::MessageInterfaceOptionsParser<TOptions...>;
87 
93  ~Message() noexcept = default;
94 
97  static constexpr bool hasMsgIdType()
98  {
99  return InterfaceOptions::HasMsgIdType;
100  }
101 
104  static constexpr bool hasEndian()
105  {
106  return InterfaceOptions::HasEndian;
107  }
108 
111  static constexpr bool hasGetId()
112  {
113  return hasMsgIdType() && InterfaceOptions::HasMsgIdInfo;
114  }
115 
119  static constexpr bool hasRead()
120  {
121  return InterfaceOptions::HasReadIterator;
122  }
123 
127  static constexpr bool hasWrite()
128  {
129  return InterfaceOptions::HasWriteIterator;
130  }
131 
134  static constexpr bool hasValid()
135  {
136  return InterfaceOptions::HasValid;
137  }
138 
141  static constexpr bool hasLength()
142  {
143  return InterfaceOptions::HasLength;
144  }
145 
148  static constexpr bool hasRefresh()
149  {
150  return InterfaceOptions::HasRefresh;
151  }
152 
156  static constexpr bool hasDispatch()
157  {
158  return InterfaceOptions::HasHandler;
159  }
160 
164  static constexpr bool hasTransportFields()
165  {
166  return InterfaceOptions::HasExtraTransportFields;
167  }
168 
171  static constexpr bool hasVersionInTransportFields()
172  {
173  return InterfaceOptions::HasVersionInExtraTransportFields;
174  }
175 
179  static constexpr std::size_t versionIdxInTransportFields()
180  {
182  }
183 
186  static constexpr bool hasName()
187  {
189  }
190 
191 #ifdef FOR_DOXYGEN_DOC_ONLY
196  using MsgIdType = typename BaseImpl::MsgIdType;
197 
203  using MsgIdParamType = typename BaseImpl::MsgIdParamType;
204 
209  using Endian = typename BaseImpl::Endian;
210 
215  using Field = BaseImpl::Field;
216 
224 
230  using ReadIterator = TypeProvidedWithOption;
231 
243  ErrorStatus read(ReadIterator& iter, std::size_t size);
244 
250  using WriteIterator = TypeProvidedWithOption;
251 
263  ErrorStatus write(WriteIterator& iter, std::size_t size) const;
264 
270  bool valid() const;
271 
277  std::size_t length() const;
278 
295  bool refresh();
296 
302  const char* name() const;
303 
307  using Handler = TypeProvidedWithOption;
308 
311  using DispatchRetType = typename Handler::RetType;
312 
319 
325  using TransportFields = FieldsProvidedWithOption;
326 
340 
346 
351 
356 
360  const VersionType& version() const;
361 #endif // #ifdef FOR_DOXYGEN_DOC_ONLY
362 
363 protected:
364 
365 #ifdef FOR_DOXYGEN_DOC_ONLY
373  virtual MsgIdParamType getIdImpl() const = 0;
374 
384  virtual comms::ErrorStatus readImpl(ReadIterator& iter, std::size_t size);
385 
395  virtual comms::ErrorStatus writeImpl(WriteIterator& iter, std::size_t size) const;
396 
404  virtual bool validImpl() const;
405 
415  virtual std::size_t lengthImpl() const;
416 
426  virtual bool refreshImpl();
427 
437 
442  virtual const char* nameImpl() const = 0;
443 
458  template <typename T, typename TIter>
459  static void writeData(T value, TIter& iter);
460 
477  template <std::size_t TSize, typename T, typename TIter>
478  static void writeData(T value, TIter& iter);
479 
495  template <typename T, typename TIter>
496  static T readData(TIter& iter);
497 
514  template <typename T, std::size_t TSize, typename TIter>
515  static T readData(TIter& iter);
516 
517 #endif // #ifdef FOR_DOXYGEN_DOC_ONLY
518 };
519 
522 template <typename... TOptions>
523 inline
525 {
526  return msg;
527 }
528 
531 template <typename... TOptions>
532 inline
533 const Message<TOptions...>& toMessage(const Message<TOptions...>& msg)
534 {
535  return msg;
536 }
537 
542 template <typename T>
543 constexpr bool isMessage()
544 {
545  return details::hasInterfaceOptions<T>();
546 }
547 
556 template <typename TMsg, typename TDefaultType = std::intmax_t>
558  typename comms::util::LazyDeepConditional<
559  TMsg::InterfaceOptions::HasMsgIdType
560  >::template Type<
561  comms::details::MessageIdTypeRetriever,
562  comms::util::AliasType,
563  TDefaultType, TMsg
564  >;
565 } // namespace comms
566 
575 #define COMMS_MSG_TRANSPORT_FIELDS_ACCESS(...) \
576  COMMS_EXPAND(COMMS_DEFINE_TRANSPORT_FIELD_ENUM(__VA_ARGS__)) \
577  COMMS_MSG_TRANSPORT_FIELDS_ACCESS_FUNC { \
578  auto& msgBase = comms::toMessage(*this); \
579  using MsgBase = typename std::decay<decltype(msgBase)>::type; \
580  static_assert(MsgBase::hasTransportFields(), \
581  "Message interface class doesn't define extra transport fields."); \
582  using TransportFieldsTuple = typename MsgBase::TransportFields; \
583  static_assert(std::tuple_size<TransportFieldsTuple>::value == TransportFieldIdx_numOfValues, \
584  "Invalid number of names for transport fields tuple"); \
585  return msgBase.transportFields(); \
586  } \
587  COMMS_MSG_TRANSPORT_FIELDS_ACCESS_CONST_FUNC { \
588  return comms::toMessage(*this).transportFields(); \
589  } \
590  COMMS_EXPAND(COMMS_DO_TRANSPORT_FIELD_ACC_FUNC(TransportFields, transportFields(), __VA_ARGS__))
591 
716 #define COMMS_MSG_TRANSPORT_FIELDS_NAMES(...) \
717  COMMS_EXPAND(COMMS_MSG_TRANSPORT_FIELDS_ACCESS(__VA_ARGS__)) \
718  COMMS_EXPAND(COMMS_DO_FIELD_TYPEDEF(typename Base::TransportFields, TransportField_, TransportFieldIdx_, __VA_ARGS__))
719 
733 #define COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS(f_, ...) COMMS_EXPAND(COMMS_DO_ALIAS(transportField_, f_, __VA_ARGS__))
734 
742 #define COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS_NOTEMPLATE(f_, ...) COMMS_EXPAND(COMMS_DO_ALIAS_NOTEMPLATE(transportField_, f_, __VA_ARGS__))
743 
845 #define COMMS_MSG_TRANSPORT_FIELD_ALIAS(f_, ...) \
846  COMMS_EXPAND(COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS(f_, __VA_ARGS__)) \
847  COMMS_EXPAND(COMMS_DO_ALIAS_TYPEDEF(TransportField_, f_, __VA_ARGS__))
848 
856 #define COMMS_MSG_TRANSPORT_FIELD_ALIAS_NOTEMPLATE(f_, ...) \
857  COMMS_EXPAND(COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS_NOTEMPLATE(f_, __VA_ARGS__)) \
858  COMMS_EXPAND(COMMS_DO_ALIAS_TYPEDEF(TransportField_, f_, __VA_ARGS__))
This file contains classes required for generic custom assertion functionality.
This file contain definition of error statuses used by comms module.
Contains definition of comms::Field class.
Main interface class for all the messages.
Definition: Message.h:80
static constexpr bool hasValid()
Compile type inquiry whether message interface class defines valid() and validImpl() member functions...
Definition: Message.h:134
static constexpr bool hasEndian()
Compile type inquiry whether message interface class defines Endian and Field types.
Definition: Message.h:104
FieldsProvidedWithOption TransportFields
std::tuple of extra fields from transport layers that may affect the way the message fields get seria...
Definition: Message.h:325
typename BaseImpl::Endian Endian
Serialisation endian type.
Definition: Message.h:209
static constexpr bool hasRead()
Compile type inquiry whether message interface class defines read() and readImpl() member functions a...
Definition: Message.h:119
static constexpr std::size_t versionIdxInTransportFields()
Compile type inquiry of version field index in transport field.
Definition: Message.h:179
~Message() noexcept=default
Destructor.
TypeProvidedWithOption Handler
Type of the message handler object.
Definition: Message.h:307
virtual const char * nameImpl() const =0
Pure virtual function used to retrieve actual message name.
static constexpr bool hasMsgIdType()
Compile type inquiry whether message interface class defines MsgIdType and MsgIdParamType types.
Definition: Message.h:97
typename Handler::RetType DispatchRetType
Return type of the dispatch() member function.
Definition: Message.h:311
TypeProvidedWithOption ReadIterator
Type of the iterator used for reading message contents from sequence of bytes stored somewhere.
Definition: Message.h:230
const VersionType & version() const
Const access to version information.
BaseImpl::Field Field
Type of default base class for all the fields.
Definition: Message.h:215
static T readData(TIter &iter)
Read partial data from input area.
static constexpr bool hasTransportFields()
Compile type inquiry whether message interface class defines transportFields() member functions as we...
Definition: Message.h:164
VersionType & version()
Access to version information.
static void writeData(T value, TIter &iter)
Write data into the output area.
details::MessageInterfaceOptionsParser< TOptions... > InterfaceOptions
All the options bundled into struct.
Definition: Message.h:86
TransportFields & transportFields()
Get access to extra transport fields.
ErrorStatus read(ReadIterator &iter, std::size_t size)
Read message contents using provided iterator.
virtual bool validImpl() const
Pure virtual function used to implement contents validity check.
virtual comms::ErrorStatus readImpl(ReadIterator &iter, std::size_t size)
Virtual function used to implement read operation.
std::size_t length() const
Get number of bytes required to serialise this message.
static constexpr bool hasGetId()
Compile type inquiry whether message interface class defines getId() and getIdImpl() member functions...
Definition: Message.h:111
const TransportFields & transportFields() const
Const version of transportFields.
static constexpr bool hasWrite()
Compile type inquiry whether message interface class defines write() and writeImpl() member functions...
Definition: Message.h:127
typename BaseImpl::MsgIdType MsgIdType
Type used for message ID.
Definition: Message.h:196
virtual MsgIdParamType getIdImpl() const =0
Pure virtual function used to retrieve ID of the message.
typename BaseImpl::MsgIdParamType MsgIdParamType
Type used for message ID passed as parameter or returned from function.
Definition: Message.h:203
MsgIdParamType getId() const
Retrieve ID of the message.
static constexpr bool hasLength()
Compile type inquiry whether message interface class defines length() and lengthImpl() member functio...
Definition: Message.h:141
virtual DispatchRetType dispatchImpl(Handler &handler)
Virtual function used to dispatch message to the handler object for processing.
static constexpr bool hasName()
Compile type inquiry whether message interface class defines name() and nameImpl() member functions.
Definition: Message.h:186
static void writeData(T value, TIter &iter)
Write partial data into the output area.
static T readData(TIter &iter)
Read data from input area.
ErrorStatus write(WriteIterator &iter, std::size_t size) const
Write message contents using provided iterator.
const char * name() const
Get name of the message.
virtual std::size_t lengthImpl() const
Virtual function used to retrieve number of bytes required to serialise this message.
typename BaseImpl::VersionType VersionType
Type used for version info.
Definition: Message.h:350
bool refresh()
Refresh to contents of the message.
static constexpr bool hasRefresh()
Compile type inquiry whether message interface class defines refresh() and refreshImpl() member funct...
Definition: Message.h:148
virtual comms::ErrorStatus writeImpl(WriteIterator &iter, std::size_t size) const
Virtual function used to implement write operation.
bool valid() const
Check validity of message contents.
static constexpr bool hasDispatch()
Compile type inquiry whether message interface class defines dispatch() and dispatchImpl() member fun...
Definition: Message.h:156
TypeProvidedWithOption WriteIterator
Type of the iterator used for writing message contents into sequence of bytes stored somewhere.
Definition: Message.h:250
DispatchRetType dispatch(Handler &handler)
Dispatch message to the handler for processing.
virtual bool refreshImpl()
Virtual function used to bring contents of the message into a consistent state.
static constexpr bool hasVersionInTransportFields()
Compile type inquiry whether there is version information inside transport fields.
Definition: Message.h:171
comms::option::def::HasName HasName
Same as comms::option::def::HasName.
Definition: options.h:1786
comms::option::def::VersionType< T > VersionType
Same as comms::option::def::VersionType.
Definition: options.h:1797
comms::option::def::VersionInExtraTransportFields< TIdx > VersionInExtraTransportFields
Same as comms::option::def::VersionInExtraTransportFields.
Definition: options.h:1471
comms::option::def::Endian< TEndian > Endian
Same as comms::option::def::Endian.
Definition: options.h:1438
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition: options.h:1448
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition: ErrorStatus.h:17
constexpr bool isMessage()
Compile time check of of whether the type is a message.
Definition: Message.h:543
Message< TOptions... > & toMessage(Message< TOptions... > &msg)
Upcast type of the message object to comms::Message in order to have access to its internal types.
Definition: Message.h:524
typename comms::util::LazyDeepConditional< TMsg::InterfaceOptions::HasMsgIdType >::template Type< comms::details::MessageIdTypeRetriever, comms::util::AliasType, TDefaultType, TMsg > MessageIdType
Get type of message ID used by interface class.
Definition: Message.h:564
Replacement to some types from standard type_traits.