COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Static Public Member Functions | Protected Member Functions | Static Protected Member Functions | Related Symbols | List of all members
comms::Message< TOptions > Class Template Referenceabstract

#include "comms/Message.h"

Detailed Description

template<typename... TOptions>
class comms::Message< TOptions >

Main interface class for all the messages.

Provides basic interface for all the messages.

Template Parameters
TOptionsVariadic template parameter that contain any number of options to define functionality/behaviour of the message. The options may be comma separated as well as bundled into std::tuple. Supported options are:
See also
COMMS_MSG_TRANSPORT_FIELDS_NAMES()
COMMS_MSG_TRANSPORT_FIELDS_ACCESS()
Inheritance diagram for comms::Message< TOptions >:
comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption > comms::MessageBase< TMessage, TOptions > comms::GenericMessage< TMessage, TFieldOpts, TExtraOpts >

Public Types

using DispatchRetType = typename Handler::RetType
 Return type of the dispatch() member function.
 
using Endian = typename BaseImpl::Endian
 Serialisation endian type.
 
using Field = BaseImpl::Field
 Type of default base class for all the fields.
 
using Handler = TypeProvidedWithOption
 Type of the message handler object.
 
using InterfaceOptions = details::MessageInterfaceOptionsParser< TOptions... >
 All the options bundled into struct.
 
using MsgIdParamType = typename BaseImpl::MsgIdParamType
 Type used for message ID passed as parameter or returned from function.
 
using MsgIdType = typename BaseImpl::MsgIdType
 Type used for message ID.
 
using ReadIterator = TypeProvidedWithOption
 Type of the iterator used for reading message contents from sequence of bytes stored somewhere.
 
using TransportFields = FieldsProvidedWithOption
 std::tuple of extra fields from transport layers that may affect the way the message fields get serialized / deserialized.
 
using VersionType = typename BaseImpl::VersionType
 Type used for version info.
 
using WriteIterator = TypeProvidedWithOption
 Type of the iterator used for writing message contents into sequence of bytes stored somewhere.
 

Public Member Functions

 ~Message () noexcept=default
 Destructor.
 
DispatchRetType dispatch (Handler &handler)
 Dispatch message to the handler for processing.
 
MsgIdParamType getId () const
 Retrieve ID of the message.
 
std::size_t length () const
 Get number of bytes required to serialise this message.
 
const char * name () const
 Get name of the message.
 
ErrorStatus read (ReadIterator &iter, std::size_t size)
 Read message contents using provided iterator.
 
bool refresh ()
 Refresh to contents of the message.
 
TransportFieldstransportFields ()
 Get access to extra transport fields.
 
const TransportFieldstransportFields () const
 Const version of transportFields.
 
bool valid () const
 Check validity of message contents.
 
VersionTypeversion ()
 Access to version information.
 
const VersionTypeversion () const
 Const access to version information.
 
ErrorStatus write (WriteIterator &iter, std::size_t size) const
 Write message contents using provided iterator.
 

Static Public Member Functions

static constexpr bool hasDispatch ()
 Compile type inquiry whether message interface class defines dispatch() and dispatchImpl() member functions as well as Handler and DispatchRetType types.
 
static constexpr bool hasEndian ()
 Compile type inquiry whether message interface class defines Endian and Field types.
 
static constexpr bool hasGetId ()
 Compile type inquiry whether message interface class defines getId() and getIdImpl() member functions.
 
static constexpr bool hasLength ()
 Compile type inquiry whether message interface class defines length() and lengthImpl() member functions.
 
static constexpr bool hasMsgIdType ()
 Compile type inquiry whether message interface class defines MsgIdType and MsgIdParamType types.
 
static constexpr bool hasName ()
 Compile type inquiry whether message interface class defines name() and nameImpl() member functions.
 
static constexpr bool hasRead ()
 Compile type inquiry whether message interface class defines read() and readImpl() member functions as well as ReadIterator type.
 
static constexpr bool hasRefresh ()
 Compile type inquiry whether message interface class defines refresh() and refreshImpl() member functions.
 
static constexpr bool hasTransportFields ()
 Compile type inquiry whether message interface class defines transportFields() member functions as well as TransportFields type.
 
static constexpr bool hasValid ()
 Compile type inquiry whether message interface class defines valid() and validImpl() member functions.
 
static constexpr bool hasVersionInTransportFields ()
 Compile type inquiry whether there is version information inside transport fields.
 
static constexpr bool hasWrite ()
 Compile type inquiry whether message interface class defines write() and writeImpl() member functions as well as WriteIterator type.
 
static constexpr std::size_t versionIdxInTransportFields ()
 Compile type inquiry of version field index in transport field.
 

Protected Member Functions

virtual DispatchRetType dispatchImpl (Handler &handler)
 Virtual function used to dispatch message to the handler object for processing.
 
virtual MsgIdParamType getIdImpl () const =0
 Pure virtual function used to retrieve ID of the message.
 
virtual std::size_t lengthImpl () const
 Virtual function used to retrieve number of bytes required to serialise this message.
 
virtual const char * nameImpl () const =0
 Pure virtual function used to retrieve actual message name.
 
virtual comms::ErrorStatus readImpl (ReadIterator &iter, std::size_t size)
 Virtual function used to implement read operation.
 
virtual bool refreshImpl ()
 Virtual function used to bring contents of the message into a consistent state.
 
virtual bool validImpl () const
 Pure virtual function used to implement contents validity check.
 
virtual comms::ErrorStatus writeImpl (WriteIterator &iter, std::size_t size) const
 Virtual function used to implement write operation.
 

Static Protected Member Functions

template<typename T , typename TIter >
static T readData (TIter &iter)
 Read data from input area.
 
template<typename T , std::size_t TSize, typename TIter >
static T readData (TIter &iter)
 Read partial data from input area.
 
template<typename T , typename TIter >
static void writeData (T value, TIter &iter)
 Write data into the output area.
 
template<std::size_t TSize, typename T , typename TIter >
static void writeData (T value, TIter &iter)
 Write partial data into the output area.
 

Related Symbols

(Note that these are not member symbols.)

#define COMMS_MSG_TRANSPORT_FIELD_ALIAS(f_, ...)
 Generate convinience alias access member functions for extra member transport fields.
 
#define COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS(f_, ...)   COMMS_EXPAND(COMMS_DO_ALIAS(transportField_, f_, __VA_ARGS__))
 Generate convinience alias access member functions for extra member transport fields.
 
#define COMMS_MSG_TRANSPORT_FIELDS_ACCESS(...)
 Add convenience access enum and functions to extra transport fields.
 
#define COMMS_MSG_TRANSPORT_FIELDS_NAMES(...)
 Provide names for extra transport fields.
 

Member Typedef Documentation

◆ DispatchRetType

template<typename... TOptions>
using comms::Message< TOptions >::DispatchRetType = typename Handler::RetType

Return type of the dispatch() member function.

Equal to Handler::RetType if such exists, void otherwise.

◆ Endian

template<typename... TOptions>
using comms::Message< TOptions >::Endian = typename BaseImpl::Endian

Serialisation endian type.

The type exists only if comms::option::def::BigEndian or comms::option::def::LittleEndian options were used to specify it.

See also
hasEndian()

◆ Field

template<typename... TOptions>
using comms::Message< TOptions >::Field = BaseImpl::Field

Type of default base class for all the fields.

Requires definition of the Endian type, i.e. the type exist only if comms::option::def::BigEndian or comms::option::def::LittleEndian options were used.

◆ Handler

template<typename... TOptions>
using comms::Message< TOptions >::Handler = TypeProvidedWithOption

Type of the message handler object.

The type exists only if comms::option::app::Handler option was provided to comms::Message to specify one.

◆ InterfaceOptions

template<typename... TOptions>
using comms::Message< TOptions >::InterfaceOptions = details::MessageInterfaceOptionsParser<TOptions...>

All the options bundled into struct.

For internal use only.

◆ MsgIdParamType

template<typename... TOptions>
using comms::Message< TOptions >::MsgIdParamType = typename BaseImpl::MsgIdParamType

Type used for message ID passed as parameter or returned from function.

It is equal to MsgIdType for numeric types and becomes "const-reference-to" MsgIdType for more complex types. The type exists only if MsgIdType exists, i.e. the comms::option::def::MsgIdType option was used.

◆ MsgIdType

template<typename... TOptions>
using comms::Message< TOptions >::MsgIdType = typename BaseImpl::MsgIdType

Type used for message ID.

The type exists only if comms::option::def::MsgIdType option was provided to comms::Message to specify it.

See also
hasMsgIdType()

◆ ReadIterator

template<typename... TOptions>
using comms::Message< TOptions >::ReadIterator = TypeProvidedWithOption

Type of the iterator used for reading message contents from sequence of bytes stored somewhere.

The type exists only if comms::option::app::ReadIterator option was provided to comms::Message to specify one.

See also
hasRead()

◆ TransportFields

template<typename... TOptions>
using comms::Message< TOptions >::TransportFields = FieldsProvidedWithOption

std::tuple of extra fields from transport layers that may affect the way the message fields get serialized / deserialized.

The type exists only if comms::option::def::ExtraTransportFields option has been provided to comms::Message class to specify them.

See also
hasTransportFields()

◆ VersionType

template<typename... TOptions>
using comms::Message< TOptions >::VersionType = typename BaseImpl::VersionType

Type used for version info.

The type exists only if comms::option::def::VersionInExtraTransportFields option has been provided.

◆ WriteIterator

template<typename... TOptions>
using comms::Message< TOptions >::WriteIterator = TypeProvidedWithOption

Type of the iterator used for writing message contents into sequence of bytes stored somewhere.

The type exists only if comms::option::app::WriteIterator option was provided to comms::Message to specify one.

See also
hasWrite()

Constructor & Destructor Documentation

◆ ~Message()

template<typename... TOptions>
comms::Message< TOptions >::~Message ( )
defaultnoexcept

Destructor.

Becomes virtual if the message interface is defined to expose any polymorphic behavior, i.e. if there is at least one virtual function. It is possible to explicitly suppress virtual declaration by using comms::option::app::NoVirtualDestructor option.

Member Function Documentation

◆ dispatch()

template<typename... TOptions>
DispatchRetType comms::Message< TOptions >::dispatch ( Handler handler)

Dispatch message to the handler for processing.

The function exists only if comms::option::app::Handler option was provided to comms::Message to specify type of the handler. The function invokes virtual dispatchImpl() function.

Parameters
handlerHandler object to dispatch message to.

◆ dispatchImpl()

template<typename... TOptions>
virtual DispatchRetType comms::Message< TOptions >::dispatchImpl ( Handler handler)
protectedvirtual

Virtual function used to dispatch message to the handler object for processing.

Called by dispatch(), must be implemented in the derived class. The function exists only if comms::option::app::Handler option was provided to comms::Message to specify type of the handler. If not overridden unconditionally fails on assert in DEBUG build and does nothing in RELEASE.

Parameters
handlerHandler object to dispatch message to.

Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.

◆ getId()

template<typename... TOptions>
MsgIdParamType comms::Message< TOptions >::getId ( ) const

Retrieve ID of the message.

Invokes pure virtual getIdImpl(). This function exists only if comms::option::def::MsgIdType option was used to specify type of the ID value and comms::option::app::IdInfoInterface option are used.

Returns
ID of the message.
See also
hasGetId();

◆ getIdImpl()

template<typename... TOptions>
virtual MsgIdParamType comms::Message< TOptions >::getIdImpl ( ) const
protectedpure virtual

◆ length()

template<typename... TOptions>
std::size_t comms::Message< TOptions >::length ( ) const

Get number of bytes required to serialise this message.

The function exists only if comms::option::app::LengthInfoInterface option was provided to comms::Message. The function invokes virtual lengthImpl() function.

Returns
Number of bytes required to serialise this message.
See also
hasLength()

◆ lengthImpl()

template<typename... TOptions>
virtual std::size_t comms::Message< TOptions >::lengthImpl ( ) const
protectedvirtual

Virtual function used to retrieve number of bytes required to serialise this message.

Called by length(), must be implemented in the derived class. The function exists only if comms::option::app::LengthInfoInterface option was provided to comms::Message.

Returns
Number of bytes required to serialise this message. If not overriden unconditionally fails on assert in DEBUG build and returns 0 in RELEASE.
See also
hasLength()

Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.

◆ name()

template<typename... TOptions>
const char * comms::Message< TOptions >::name ( ) const

Get name of the message.

The function exists only if comms::option::app::NameInterface option was provided to comms::Message. The function invokes virtual nameImpl() function.

See also
hasName()

◆ nameImpl()

template<typename... TOptions>
virtual const char * comms::Message< TOptions >::nameImpl ( ) const
protectedpure virtual

◆ read()

template<typename... TOptions>
ErrorStatus comms::Message< TOptions >::read ( ReadIterator iter,
std::size_t  size 
)

Read message contents using provided iterator.

The function exists only if comms::option::app::ReadIterator option was provided to comms::Message to specify type of the ReadIterator. The contents of the message are updated with bytes being read. The buffer is external and maintained by the caller. The provided iterator is advanced. The function invokes virtual readImpl() function.

Parameters
[in,out]iterIterator used for reading the data.
[in]sizeMaximum number of bytes that can be read.
Returns
Status of the operation.
See also
hasRead()

◆ readData() [1/2]

template<typename... TOptions>
template<typename T , typename TIter >
static T comms::Message< TOptions >::readData ( TIter &  iter)
staticprotected

Read data from input area.

Use this function to read data from the input area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.

Template Parameters
TReturn type
TIterType of input iterator
Parameters
[in,out]iterInput iterator.
Returns
The integral type value.
Precondition
TSize <= sizeof(T)
The iterator must be valid and can be successfully dereferenced and incremented at least sizeof(T) times.
Postcondition
The iterator is advanced.
Note
Thread safety: Safe for distinct stream buffers, unsafe otherwise.

◆ readData() [2/2]

template<typename... TOptions>
template<typename T , std::size_t TSize, typename TIter >
static T comms::Message< TOptions >::readData ( TIter &  iter)
staticprotected

Read partial data from input area.

Use this function to read partial data from the input area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.

Template Parameters
TReturn type
TSizenumber of bytes to read
TIterType of input iterator
Parameters
[in,out]iterInput iterator.
Returns
The integral type value.
Precondition
TSize <= sizeof(T)
The iterator must be valid and can be successfully dereferenced and incremented at least TSize times.
Postcondition
The internal pointer of the stream buffer is advanced.
Note
Thread safety: Safe for distinct stream buffers, unsafe otherwise.

◆ readImpl()

template<typename... TOptions>
virtual comms::ErrorStatus comms::Message< TOptions >::readImpl ( ReadIterator iter,
std::size_t  size 
)
protectedvirtual

Virtual function used to implement read operation.

Called by read(), expected be implemented in the derived class. The function exists only if comms::option::app::ReadIterator option was provided to comms::Message to specify type of the ReadIterator.

Parameters
[in,out]iterIterator used for reading the data.
[in]sizeMaximum number of bytes that can be read.
Returns
Status of the operation. If not overridden returns comms::ErrorStatus::NotSupported.
See also
hasRead()

Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.

◆ refresh()

template<typename... TOptions>
bool comms::Message< TOptions >::refresh ( )

Refresh to contents of the message.

Many protocols define their messages in a way that the content of some fields may depend on the value of the other field(s). For example, providing in one field the information about number of elements in the list that will follow later. Another example is having bits in a bitmask field specifying whether other optional fields exist. In this case, directly modifying value of some fields may leave a message contents in an inconsistent state. Having refresh() member function allows the developer to bring the message into a consistent state prior to sending it over I/O link .
The function exists only if comms::option::app::RefreshInterface option was provided to comms::Message. The function invokes virtual refreshImpl() function.

Returns
true in case the contents of the message were modified, false if all the fields of the message remained unchanged.

◆ refreshImpl()

template<typename... TOptions>
virtual bool comms::Message< TOptions >::refreshImpl ( )
protectedvirtual

Virtual function used to bring contents of the message into a consistent state.

Called by refresh(), can be overridden in the derived class. If not overridden, does nothing and returns false indicating that contents of the message haven't been changed. The function exists only if comms::option::app::RefreshInterface option was provided to comms::Message.

Returns
true in case the contents of the message were modified, false if all the fields of the message remained unchanged.

Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.

◆ transportFields() [1/2]

template<typename... TOptions>
TransportFields & comms::Message< TOptions >::transportFields ( )

Get access to extra transport fields.

The function exists only if comms::option::def::ExtraTransportFields option has been provided to comms::Message class to specify them. Some protocols may use additional values in transport information, such as message version for example. Such values may influence the way message data is being serialized / deserialized. The provided extra transport fields are NOT serialised as part of message payload. Their values are expected to be set by transport layer(s) when such information is read. The transport layers are also responsible to take the updated information from the relevant field and write it when message contents being written.

See also
hasTransportFields()

◆ transportFields() [2/2]

template<typename... TOptions>
const TransportFields & comms::Message< TOptions >::transportFields ( ) const

Const version of transportFields.

The function exists only if comms::option::def::ExtraTransportFields option has been provided to comms::Message class to specify them.

See also
hasTransportFields()

◆ valid()

template<typename... TOptions>
bool comms::Message< TOptions >::valid ( ) const

Check validity of message contents.

The function exists only if comms::option::app::ValidCheckInterface option was provided to comms::Message. The function invokes virtual validImpl() function.

Returns
true for valid contents, false otherwise.
See also
hasValid()

◆ validImpl()

template<typename... TOptions>
virtual bool comms::Message< TOptions >::validImpl ( ) const
protectedvirtual

◆ version() [1/2]

template<typename... TOptions>
VersionType & comms::Message< TOptions >::version ( )

Access to version information.

The function exists only if comms::option::def::VersionInExtraTransportFields option has been provided.

◆ version() [2/2]

template<typename... TOptions>
const VersionType & comms::Message< TOptions >::version ( ) const

Const access to version information.

The function exists only if comms::option::def::VersionInExtraTransportFields option has been provided.

◆ versionIdxInTransportFields()

template<typename... TOptions>
static constexpr std::size_t comms::Message< TOptions >::versionIdxInTransportFields ( )
staticconstexpr

Compile type inquiry of version field index in transport field.

If comms::option::def::VersionInExtraTransportFields option hasn't been used, the std::numeric_limits<std::size_t>::max() is returned.

◆ write()

template<typename... TOptions>
ErrorStatus comms::Message< TOptions >::write ( WriteIterator iter,
std::size_t  size 
) const

Write message contents using provided iterator.

The function exists only if comms::option::app::WriteIterator option was provided to comms::Message to specify type of the WriteIterator. The contents of the message are serialised into buffer. The buffer is external and is maintained by the caller. The provided iterator is advanced. The function invokes virtual writeImpl() function.

Parameters
[in,out]iterIterator used for writing the data.
[in]sizeMaximum number of bytes that can be written.
Returns
Status of the operation.
See also
hasWrite()

◆ writeData() [1/2]

template<typename... TOptions>
template<typename T , typename TIter >
static void comms::Message< TOptions >::writeData ( value,
TIter &  iter 
)
staticprotected

Write data into the output area.

Use this function to write data to the output area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.

Template Parameters
TType of the value to write. Must be integral.
Typeof output iterator
Parameters
[in]valueIntegral type value to be written.
[in,out]iterOutput iterator.
Precondition
The iterator must be valid and can be successfully dereferenced and incremented at least sizeof(T) times.
Postcondition
The iterator is advanced.
Note
Thread safety: Safe for distinct buffers, unsafe otherwise.

◆ writeData() [2/2]

template<typename... TOptions>
template<std::size_t TSize, typename T , typename TIter >
static void comms::Message< TOptions >::writeData ( value,
TIter &  iter 
)
staticprotected

Write partial data into the output area.

Use this function to write partial data to the output area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.

Template Parameters
TSizeLength of the value in bytes known in compile time.
TType of the value to write. Must be integral.
TIterType of output iterator
Parameters
[in]valueIntegral type value to be written.
[in,out]iterOutput iterator.
Precondition
TSize <= sizeof(T)
The iterator must be valid and can be successfully dereferenced and incremented at least TSize times.
Postcondition
The iterator is advanced.
Note
Thread safety: Safe for distinct buffers, unsafe otherwise.

◆ writeImpl()

template<typename... TOptions>
virtual comms::ErrorStatus comms::Message< TOptions >::writeImpl ( WriteIterator iter,
std::size_t  size 
) const
protectedvirtual

Virtual function used to implement write operation.

Called by write(), expected be implemented in the derived class. The function exists only if comms::option::app::WriteIterator option was provided to comms::Message to specify type of the WriteIterator.

Parameters
[in,out]iterIterator used for writing the data.
[in]sizeMaximum number of bytes that can be written.
Returns
Status of the operation. If not overridden returns comms::ErrorStatus::NotSupported.
See also
hasWrite()

Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.

Friends And Related Symbol Documentation

◆ COMMS_MSG_TRANSPORT_FIELD_ALIAS

template<typename... TOptions>
#define COMMS_MSG_TRANSPORT_FIELD_ALIAS (   f_,
  ... 
)
related
Value:
COMMS_EXPAND(COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS(f_, __VA_ARGS__)) \
COMMS_EXPAND(COMMS_DO_ALIAS_TYPEDEF(TransportField_, f_, __VA_ARGS__))
#define COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS(f_,...)
Generate convinience alias access member functions for extra member transport fields.
Definition Message.h:733

Generate convinience alias access member functions for extra member transport fields.

The COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro generates alias type as well as convenience access member functions for extra transport fields. Sometimes the fields may get renamed or moved to be a member of other fields, like comms::field::Bundle or comms::field::Bitfield. In such case the compilation of the existing client code (that already uses published protocol definition) may fail. To avoid such scenarios and make the transition to newer versions of the protocol easier, the COMMS_MSG_TRANSPORT_FIELD_ALIAS() macro can be used to create alias to other fields. For example, let's assume that some common interface class was defined: like this.

class MyInterface : public comms::Message<...>
{
// (Re)definition of the base class as inner Base type.
using Base = comms::Message<...>;
public:
COMMS_MSG_TRANSPORT_FIELDS_NAMES(name1, name2, name3);
};
Main interface class for all the messages.
Definition Message.h:80

In the future versions of the protocol "name3" was renamed to "newName3". To keep the existing code (that uses "name3" name) compiling it is possible to create an alias access function(s) with:

class MyInterface : public public comms::Message<...>
{
using Base = comms::Message<...>;
public:
COMMS_MSG_TRANSPORT_FIELDS_NAMES(name1, name2, newName3);
COMMS_MSG_TRANSPORT_FIELD_ALIAS(name3, newName3);
};

The usage of COMMS_MSG_TRANSPORT_FIELD_ALIAS() in the code above is equivalent to having the following type and functions defined:

class MyInterface : public public comms::Message<...>
{
public:
...
using TransportField_name3 = TransportField_newName3;
auto transportField_name3() -> decltype(transportField_newName3())
{
return transportField_newName3();
}
auto transportField_name3() const -> decltype(transportField_newName3())
{
return transportField_newName3();
}
};

Another example would be a replacing a comms::field::IntValue with comms::field::Bitfield in the future version of the protocol. It can happen when the developer decides to split the used storage into multiple values (because the range of the used/valid values allows so). In order to keep the old client code compiling, the access to the replaced field needs to be an alias to the first member of the comms::field::Bitfield. In this case the usage of COMMS_MSG_TRANSPORT_FIELD_ALIAS() will look like this:

class MyInterface : public public comms::Message<...>
{
using Base = comms::Message<...>;
public:
COMMS_MSG_TRANSPORT_FIELDS_NAMES(name1, name2, newName3);
COMMS_MSG_TRANSPORT_FIELD_ALIAS(name3, newName3, member1);
};

The usage of COMMS_MSG_TRANSPORT_FIELD_ALIAS() in the code above is equivalent to having the following functions defined:

class MyInterface : public public comms::Message<...>
{
public:
...
using TransportField_name3 = TransportField_newName3::Field_Member1;
auto transportField_name3() -> decltype(transportField_newName3().field_member1())
{
return field_newName3().field_member1();
}
auto transportField_name3() const -> decltype(transportField_newName3().field_member1())
{
return transportField_newName3().field_member1();
}
};
Parameters
[in]f_Alias field name.
[in]...List of fields' names.
Precondition
The macro COMMS_MSG_TRANSPORT_FIELDS_NAMES() needs to be used before COMMS_MSG_TRANSPORT_FIELD_ALIAS() to define convenience access functions.
See also
COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS_NOTEMPLATE()
COMMS_MSG_TRANSPORT_FIELD_ALIAS_NOTEMPLATE()
Note
Defined in "comms/Message.h"

◆ COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS

template<typename... TOptions>
#define COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS (   f_,
  ... 
)    COMMS_EXPAND(COMMS_DO_ALIAS(transportField_, f_, __VA_ARGS__))
related

Generate convinience alias access member functions for extra member transport fields.

Similar to COMMS_MSG_TRANSPORT_FIELD_ALIAS() but requires usage of COMMS_MSG_TRANSPORT_FIELDS_ACCESS() instead of COMMS_MSG_TRANSPORT_FIELDS_NAMES() and does NOT create alias to the field type, only access functions.

Parameters
[in]f_Alias field name.
[in]...List of fields' names.
Precondition
The macro COMMS_MSG_TRANSPORT_FIELDS_ACCESS() needs to be used before COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS() to define convenience access functions.
See also
COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS_NOTEMPLATE()
COMMS_MSG_TRANSPORT_FIELD_ALIAS()
Note
Defined in "comms/Message.h"

◆ COMMS_MSG_TRANSPORT_FIELDS_ACCESS

template<typename... TOptions>
#define COMMS_MSG_TRANSPORT_FIELDS_ACCESS (   ...)
related
Value:
COMMS_EXPAND(COMMS_DEFINE_TRANSPORT_FIELD_ENUM(__VA_ARGS__)) \
COMMS_MSG_TRANSPORT_FIELDS_ACCESS_FUNC { \
auto& msgBase = comms::toMessage(*this); \
using MsgBase = typename std::decay<decltype(msgBase)>::type; \
static_assert(MsgBase::hasTransportFields(), \
"Message interface class doesn't define extra transport fields."); \
using TransportFieldsTuple = typename MsgBase::TransportFields; \
static_assert(std::tuple_size<TransportFieldsTuple>::value == TransportFieldIdx_numOfValues, \
"Invalid number of names for transport fields tuple"); \
return msgBase.transportFields(); \
} \
COMMS_MSG_TRANSPORT_FIELDS_ACCESS_CONST_FUNC { \
return comms::toMessage(*this).transportFields(); \
} \
COMMS_EXPAND(COMMS_DO_TRANSPORT_FIELD_ACC_FUNC(TransportFields, transportFields(), __VA_ARGS__))
FieldsProvidedWithOption TransportFields
std::tuple of extra fields from transport layers that may affect the way the message fields get seria...
Definition Message.h:325
TransportFields & transportFields()
Get access to extra transport fields.
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

Add convenience access enum and functions to extra transport fields.

Very similar to COMMS_MSG_TRANSPORT_FIELDS_NAMES(), but does NOT require definition of Base inner member type (for some compilers) and does NOT define inner TransportField_* types for used fields.

Parameters
[in]...List of fields' names.
See also
COMMS_MSG_TRANSPORT_FIELDS_NAMES()
Note
Defined in "comms/Message.h"

◆ COMMS_MSG_TRANSPORT_FIELDS_NAMES

template<typename... TOptions>
#define COMMS_MSG_TRANSPORT_FIELDS_NAMES (   ...)
related
Value:
COMMS_EXPAND(COMMS_MSG_TRANSPORT_FIELDS_ACCESS(__VA_ARGS__)) \
COMMS_EXPAND(COMMS_DO_FIELD_TYPEDEF(typename Base::TransportFields, TransportField_, TransportFieldIdx_, __VA_ARGS__))
#define COMMS_MSG_TRANSPORT_FIELDS_ACCESS(...)
Add convenience access enum and functions to extra transport fields.
Definition Message.h:575

Provide names for extra transport fields.

The comms::Message class provides access to its extra transport fields via comms::MessageBase::transportFields() member function(s). The fields are bundled into std::tuple and can be accessed using indices with std::get. For convenience, the fields should be named. The COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro does exactly that.
As an example, let's assume that custom message uses 3 fields of any types:

using TransportField1 = ...;
using TransportField2 = ...;
using TransportField3 = ...;
typedef std::tuple<TransportField1, TransportField2, TransportField3> MyExtraTransportFields
class MyInterface : public
...
comms::option::def::ExtraTransportFields<MyExtraTransportFields> >
{
// (Re)definition of the base class as inner Base type is
// required by the COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro.
using Base = comms::Message<...>;
public:
COMMS_MSG_TRANSPORT_FIELDS_NAMES(name1, name2, name3);
};

The usage of the COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro with the list of the extra transport field's names is equivalent to having the following definitions inside the message class

class MyInterface : public comms::Message<...>
{
using Base = comms::Message<...>;
public:
enum TransportFieldIdx {
TransportFieldIdx_name1,
TransportFieldIdx_name2,
TransportFieldIdx_name3,
TransportFieldIdx_nameOfValues
};
static_assert(std::tuple_size<Base::TransportFields>::value == TransportFieldIdx_nameOfValues,
"Number of expected transport fields is incorrect");
// Accessor to "name1" transport field.
auto transportField_name1() -> decltype(std::get<TransportFieldIdx_name1>(Base::transportFields()))
{
return std::get<TransportFieldIdx_name1>(Base::transportFields());
}
// Accessor to "name1" field.
auto transportField_name1() const -> decltype(std::get<TransportFieldIdx_name1>(Base::transportFields()))
{
return std::get<TransportFieldIdx_name1>(Base::transportFields());
}
// Accessor to "name2" field.
auto transportField_name2() -> decltype(std::get<TransportFieldIdx_name2>(Base::transportFields()))
{
return std::get<TransportFieldIdx_name2>(Base::transportFields());
}
// Accessor to "name2" field.
auto transportField_name2() const -> decltype(std::get<TransportFieldIdx_name2>(Base::transportFields()))
{
return std::get<TransportFieldIdx_name2>(Base::transportFields());
}
// Accessor to "name3" field.
auto transportField_name3() -> decltype(std::get<TransportFieldIdx_name3>(Base::transportFields()))
{
return std::get<TransportFieldIdx_name3>(Base::transportFields());
}
// Accessor to "name3" field.
auto transportField_name3() const -> decltype(std::get<FieldIdx_name3>(Base::transportFields()))
{
return std::get<FieldIdx_name3>(Base::transportFields());
}
// Redefinition of the transport field types:
using TransportField_name1 = TransportField1;
using TransportField_name2 = TransportField2;
using TransportField_name3 = TransportField3;
};
STL namespace.

NOTE, that provided names name1, name2, and name3 have found their way to the following definitions:

  • TransportFieldIdx enum. The names are prefixed with TransportFieldIdx_. The TransportFieldIdx_nameOfValues value is automatically added at the end.
  • Accessor functions prefixed with transportField_*
  • Types of fields prefixed with TransportField_*

As the result, the fields can be accessed using TransportFieldIdx enum

void handle(Message1& msg)
{
auto& transportFields = msg.transportFields();
auto& field1 = std::get<Message1::TransportFieldIdx_name1>(transportFields);
auto& field2 = std::get<Message1::TransportFieldIdx_name2>(transportFields);
auto& field3 = std::get<Message1::TransportFieldIdx_name3>(transportFields);
auto value1 = field1.value();
auto value2 = field2.value();
auto value3 = field3.value();
}

or using accessor functions:

void handle(Message1& msg)
{
auto value1 = transportField_name1().value();
auto value2 = transportField_name2().value();
auto value3 = transportField_name3().value();
}
Parameters
[in]...List of fields' names.
Precondition
Requires (re)definition of the message base class as inner Base member type.
See also
COMMS_MSG_TRANSPORT_FIELDS_ACCESS()
Note
Defined in "comms/Message.h"

The documentation for this class was generated from the following file: