Skip to content

Commit

Permalink
Added message type traits
Browse files Browse the repository at this point in the history
  • Loading branch information
John Wellbelove committed Mar 5, 2024
1 parent 4245e23 commit c6dc700
Show file tree
Hide file tree
Showing 5 changed files with 265 additions and 30 deletions.
84 changes: 82 additions & 2 deletions include/etl/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ namespace etl
}
};

class message_tag {};

#if ETL_HAS_VIRTUAL_MESSAGES
//***************************************************************************
/// Message interface.
Expand All @@ -85,10 +87,14 @@ namespace etl
/// Virtual.
//***************************************************************************
template <etl::message_id_t ID_, typename TBase = etl::imessage>
class message : public TBase
class message : public TBase, public etl::message_tag
{
public:

ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TBase>::value), "TBase is not derived from etl::imessage");

typedef TBase base_type;

//***********************************
ETL_NODISCARD virtual etl::message_id_t get_message_id() const ETL_NOEXCEPT ETL_OVERRIDE
{
Expand Down Expand Up @@ -149,12 +155,14 @@ namespace etl
/// Non-virtual.
//***************************************************************************
template <etl::message_id_t ID_, typename TBase = etl::imessage>
class message : public TBase
class message : public TBase, public etl::message_tag
{
public:

ETL_STATIC_ASSERT((etl::is_base_of<etl::imessage, TBase>::value), "TBase is not derived from etl::imessage");

typedef TBase base_type;

//***********************************
message() ETL_NOEXCEPT
: TBase(ID)
Expand Down Expand Up @@ -183,6 +191,78 @@ namespace etl
//***************************************************************************
template <etl::message_id_t ID_, typename TBase>
ETL_CONSTANT etl::message_id_t etl::message<ID_, TBase>::ID;

//***************************************************************************
/// Is T an etl::imessage?
//***************************************************************************
template <typename T>
struct is_imessage : public etl::bool_constant<etl::is_same<etl::imessage, typename etl::remove_cvref<T>::type>::value>
{
};

//***************************************************************************
/// Is T ultimately derived from etl::imessage?
//***************************************************************************
template <typename T>
struct is_message : public etl::bool_constant<etl::is_base_of<etl::imessage, typename etl::remove_cvref<T>::type>::value>
{
};

//***************************************************************************
/// Is T derived from etl::message<>
//***************************************************************************
template <typename T>
struct is_message_type : public etl::bool_constant<etl::is_base_of<etl::message_tag, typename etl::remove_cvref<T>::type>::value>
{
};

//***************************************************************************
/// Is T a base of etl::message<T>
//***************************************************************************
template <typename T>
struct is_message_base : public etl::bool_constant<etl::is_message<T>::value && !is_message_type<T>::value>
{
};

//***************************************************************************
/// Is T a user defined base of etl::message<T>
//***************************************************************************
template <typename T>
struct is_user_message_base : public etl::bool_constant<etl::is_message_base<T>::value && !is_imessage<T>::value>
{
};

#if ETL_USING_CPP17
//***************************************************************************
/// Is T an etl::imessage?
//***************************************************************************
template <typename T>
inline constexpr bool is_imessage_v = is_imessage<T>::value;

//***************************************************************************
/// Is T ultimately derived from etl::imessage?
//***************************************************************************
template <typename T>
inline constexpr bool is_message_v = is_message<T>::value;

//***************************************************************************
/// Is T derived from etl::message<>
//***************************************************************************
template <typename T>
inline constexpr bool is_message_type_v = is_message_type<T>::value;

//***************************************************************************
/// Is T a base of etl::message<T>
//***************************************************************************
template <typename T>
inline constexpr bool is_message_base_v = is_message_base<T>::value;

//***************************************************************************
/// Is T a user defined base of etl::message<T>
//***************************************************************************
template <typename T>
inline constexpr bool is_user_message_base_v = is_user_message_base<T>::value;
#endif
}

#endif
90 changes: 63 additions & 27 deletions include/etl/message_packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,26 +76,35 @@ namespace etl

private:

using ThisPacketType = etl::message_packet<TMessageTypes...>;

template <typename T>
static constexpr bool IsMessagePacket = etl::is_same_v<remove_cvref_t<T>, ThisPacketType>;

template <typename T>
static constexpr bool IsMessagePacket = etl::is_same_v< etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_cvref_t<T>, TMessageTypes...>;

template <typename T>
static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<T>>, TMessageTypes...>;
static constexpr bool IsIMessage = etl::is_same_v<etl::remove_cvref_t<T>, etl::imessage>;

template <typename T>
static constexpr bool IsIMessage = etl::is_same_v<remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
static constexpr bool IsDerivedFromIMessage = etl::is_base_of_v<etl::imessage, etl::remove_cvref_t<T>>;

public:

//********************************************
/// Default constructor
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet()
: valid(false)
{
}
#include "private/diagnostic_pop.h"

//**********************************************
//********************************************
/// Copy constructor
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet(const message_packet& other)
: valid(other.is_valid())
Expand All @@ -107,7 +116,9 @@ namespace etl
}
#include "private/diagnostic_pop.h"

//**********************************************
//********************************************
/// Move constructor
//********************************************
#include "private/diagnostic_uninitialized_push.h"
message_packet(message_packet&& other)
: valid(other.is_valid())
Expand All @@ -119,36 +130,61 @@ namespace etl
}
#include "private/diagnostic_pop.h"

#include "private/diagnostic_uninitialized_push.h"
//********************************************
///
//********************************************
#include "private/diagnostic_uninitialized_push.h"
template <typename T, typename = typename etl::enable_if<IsIMessage<T> || IsInMessageList<T>>::type>
explicit message_packet(T&& msg)
explicit message_packet(const etl::imessage& msg)
: valid(true)
{
if constexpr (IsIMessage<T>)
if (accepts(msg))
{
if (accepts(msg))
{
add_new_message(etl::forward<T>(msg));
valid = true;
}
else
{
valid = false;
}

ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
add_new_message(msg);
valid = true;
}
else
{
valid = false;
}
else if constexpr (IsInMessageList<T>)

ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
}
#include "private/diagnostic_pop.h"

#include "private/diagnostic_uninitialized_push.h"
//********************************************
///
//********************************************
explicit message_packet(etl::imessage&& msg)
: valid(true)
{
if (accepts(msg))
{
add_new_message_type<T>(etl::forward<T>(msg));
add_new_message(etl::move(msg));
valid = true;
}
else
{
ETL_STATIC_ASSERT(IsInMessageList<T>, "Message not in packet type list");
valid = false;
}

ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
}
#include "private/diagnostic_pop.h"

#include "private/diagnostic_uninitialized_push.h"
//********************************************
/// Enabled for types that are not a message packet or etl::imessage
/// Invokes a static assert for types not in the message type list.
//********************************************
template <typename T, typename = etl::enable_if_t<!IsMessagePacket<T> &&
!IsIMessage<T>, int>>
explicit message_packet(T&& msg)
: valid(true)
{
ETL_STATIC_ASSERT(IsInMessageList<T>, "Message type not in packet type list");

add_new_message_type(etl::forward<T>(msg));
}
#include "private/diagnostic_pop.h"

Expand Down Expand Up @@ -250,15 +286,15 @@ namespace etl
//**********************************************
template <typename TMessage>
static ETL_CONSTEXPR
typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type
typename etl::enable_if_t<etl::is_base_of_v<etl::imessage, TMessage>, bool>
accepts()
{
return accepts<TMessage::ID>();
}

enum
{
SIZE = etl::largest<TMessageTypes...>::size,
SIZE = etl::largest<TMessageTypes...>::size,
ALIGNMENT = etl::largest<TMessageTypes...>::alignment
};

Expand Down Expand Up @@ -308,11 +344,11 @@ namespace etl
/// Only enabled for types that are in the typelist.
//********************************************
template <typename TMessage>
etl::enable_if_t<etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<TMessage>>, TMessageTypes...>, void>
etl::enable_if_t<IsInMessageList<TMessage>>
add_new_message_type(TMessage&& msg)
{
void* p = data;
new (p) etl::remove_reference_t<TMessage>((etl::forward<TMessage>(msg)));
new (p) etl::remove_cvref_t<TMessage>((etl::forward<TMessage>(msg)));
}
#include "private/diagnostic_pop.h"

Expand Down
Loading

0 comments on commit c6dc700

Please sign in to comment.