forked from Kistler-Group/sdbus-cpp
feat: support enums in D-Bus serialization and signatures (#416)
This commit is contained in:
@@ -29,9 +29,10 @@
|
|||||||
|
|
||||||
#include <sdbus-c++/TypeTraits.h>
|
#include <sdbus-c++/TypeTraits.h>
|
||||||
#include <sdbus-c++/Error.h>
|
#include <sdbus-c++/Error.h>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
#if __cplusplus >= 202002L
|
#if __cplusplus >= 202002L
|
||||||
#include <span>
|
#include <span>
|
||||||
#endif
|
#endif
|
||||||
@@ -100,6 +101,8 @@ namespace sdbus {
|
|||||||
template <typename _Element, std::size_t _Extent>
|
template <typename _Element, std::size_t _Extent>
|
||||||
Message& operator<<(const std::span<_Element, _Extent>& items);
|
Message& operator<<(const std::span<_Element, _Extent>& items);
|
||||||
#endif
|
#endif
|
||||||
|
template <typename _Enum, typename = std::enable_if_t<std::is_enum_v<_Enum>>>
|
||||||
|
Message& operator<<(const _Enum& item);
|
||||||
template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
|
template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
|
||||||
Message& operator<<(const std::map<_Key, _Value, _Compare, _Allocator>& items);
|
Message& operator<<(const std::map<_Key, _Value, _Compare, _Allocator>& items);
|
||||||
template <typename _Key, typename _Value, typename _Hash, typename _KeyEqual, typename _Allocator>
|
template <typename _Key, typename _Value, typename _Hash, typename _KeyEqual, typename _Allocator>
|
||||||
@@ -132,6 +135,8 @@ namespace sdbus {
|
|||||||
template <typename _Element, std::size_t _Extent>
|
template <typename _Element, std::size_t _Extent>
|
||||||
Message& operator>>(std::span<_Element, _Extent>& items);
|
Message& operator>>(std::span<_Element, _Extent>& items);
|
||||||
#endif
|
#endif
|
||||||
|
template <typename _Enum, typename = std::enable_if_t<std::is_enum_v<_Enum>>>
|
||||||
|
Message& operator>>(_Enum& item);
|
||||||
template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
|
template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
|
||||||
Message& operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items);
|
Message& operator>>(std::map<_Key, _Value, _Compare, _Allocator>& items);
|
||||||
template <typename _Key, typename _Value, typename _Hash, typename _KeyEqual, typename _Allocator>
|
template <typename _Key, typename _Value, typename _Hash, typename _KeyEqual, typename _Allocator>
|
||||||
@@ -332,6 +337,12 @@ namespace sdbus {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename _Enum, typename>
|
||||||
|
inline Message& Message::operator<<(const _Enum &item)
|
||||||
|
{
|
||||||
|
return operator<<(static_cast<std::underlying_type_t<_Enum>>(item));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename _Array>
|
template <typename _Array>
|
||||||
inline void Message::serializeArray(const _Array& items)
|
inline void Message::serializeArray(const _Array& items)
|
||||||
{
|
{
|
||||||
@@ -457,6 +468,15 @@ namespace sdbus {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename _Enum, typename>
|
||||||
|
inline Message& Message::operator>>(_Enum& item)
|
||||||
|
{
|
||||||
|
std::underlying_type_t<_Enum> val;
|
||||||
|
*this >> val;
|
||||||
|
item = static_cast<_Enum>(val);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename _Array>
|
template <typename _Array>
|
||||||
inline void Message::deserializeArray(_Array& items)
|
inline void Message::deserializeArray(_Array& items)
|
||||||
{
|
{
|
||||||
|
@@ -98,7 +98,7 @@ namespace sdbus {
|
|||||||
inline constexpr dont_expect_reply_t dont_expect_reply{};
|
inline constexpr dont_expect_reply_t dont_expect_reply{};
|
||||||
|
|
||||||
// Template specializations for getting D-Bus signatures from C++ types
|
// Template specializations for getting D-Bus signatures from C++ types
|
||||||
template <typename _T>
|
template <typename _T, typename _Enable = void>
|
||||||
struct signature_of
|
struct signature_of
|
||||||
{
|
{
|
||||||
static constexpr bool is_valid = false;
|
static constexpr bool is_valid = false;
|
||||||
@@ -120,7 +120,7 @@ namespace sdbus {
|
|||||||
|
|
||||||
template <typename _T>
|
template <typename _T>
|
||||||
struct signature_of<_T&>
|
struct signature_of<_T&>
|
||||||
: public signature_of<_T>
|
: public signature_of<_T>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
@@ -405,6 +405,12 @@ namespace sdbus {
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
template <typename _Enum>
|
||||||
|
struct signature_of<_Enum, typename std::enable_if_t<std::is_enum_v<_Enum>>>
|
||||||
|
: public signature_of<std::underlying_type_t<_Enum>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
|
||||||
template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
|
template <typename _Key, typename _Value, typename _Compare, typename _Allocator>
|
||||||
struct signature_of<std::map<_Key, _Value, _Compare, _Allocator>>
|
struct signature_of<std::map<_Key, _Value, _Compare, _Allocator>>
|
||||||
{
|
{
|
||||||
@@ -429,7 +435,6 @@ namespace sdbus {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// Function traits implementation inspired by (c) kennytm,
|
// Function traits implementation inspired by (c) kennytm,
|
||||||
// https://github.com/kennytm/utils/blob/master/traits.hpp
|
// https://github.com/kennytm/utils/blob/master/traits.hpp
|
||||||
template <typename _Type>
|
template <typename _Type>
|
||||||
|
@@ -347,6 +347,24 @@ TEST(AMessage, CanCarryDBusArrayOfNontrivialTypesGivenAsStdSpan)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
TEST(AMessage, CanCarryAnEnumValue)
|
||||||
|
{
|
||||||
|
auto msg = sdbus::createPlainMessage();
|
||||||
|
|
||||||
|
enum class EnumA : int16_t {X = 5} aWritten{EnumA::X};
|
||||||
|
enum EnumB {Y = 11} bWritten{EnumB::Y};
|
||||||
|
|
||||||
|
msg << aWritten << bWritten;
|
||||||
|
msg.seal();
|
||||||
|
|
||||||
|
EnumA aRead{};
|
||||||
|
EnumB bRead{};
|
||||||
|
msg >> aRead >> bRead;
|
||||||
|
|
||||||
|
ASSERT_THAT(aRead, Eq(aWritten));
|
||||||
|
ASSERT_THAT(bRead, Eq(bWritten));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(AMessage, ThrowsWhenDestinationStdArrayIsTooSmallDuringDeserialization)
|
TEST(AMessage, ThrowsWhenDestinationStdArrayIsTooSmallDuringDeserialization)
|
||||||
{
|
{
|
||||||
auto msg = sdbus::createPlainMessage();
|
auto msg = sdbus::createPlainMessage();
|
||||||
|
@@ -49,6 +49,21 @@ namespace
|
|||||||
static std::string getDBusTypeSignature();
|
static std::string getDBusTypeSignature();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SomeEnumClass : uint8_t
|
||||||
|
{
|
||||||
|
A, B, C
|
||||||
|
};
|
||||||
|
|
||||||
|
enum struct SomeEnumStruct : int64_t
|
||||||
|
{
|
||||||
|
A, B, C
|
||||||
|
};
|
||||||
|
|
||||||
|
enum SomeClassicEnum
|
||||||
|
{
|
||||||
|
A, B, C
|
||||||
|
};
|
||||||
|
|
||||||
#define TYPE(...) \
|
#define TYPE(...) \
|
||||||
template <> \
|
template <> \
|
||||||
std::string Type2DBusTypeSignatureConversion<__VA_ARGS__>::getDBusTypeSignature() \
|
std::string Type2DBusTypeSignatureConversion<__VA_ARGS__>::getDBusTypeSignature() \
|
||||||
@@ -79,8 +94,11 @@ namespace
|
|||||||
TYPE(std::vector<int16_t>)HAS_DBUS_TYPE_SIGNATURE("an")
|
TYPE(std::vector<int16_t>)HAS_DBUS_TYPE_SIGNATURE("an")
|
||||||
TYPE(std::array<int16_t, 3>)HAS_DBUS_TYPE_SIGNATURE("an")
|
TYPE(std::array<int16_t, 3>)HAS_DBUS_TYPE_SIGNATURE("an")
|
||||||
#if __cplusplus >= 202002L
|
#if __cplusplus >= 202002L
|
||||||
TYPE(std::span<int16_t>)HAS_DBUS_TYPE_SIGNATURE("ao")
|
TYPE(std::span<int16_t>)HAS_DBUS_TYPE_SIGNATURE("an")
|
||||||
#endif
|
#endif
|
||||||
|
TYPE(SomeEnumClass)HAS_DBUS_TYPE_SIGNATURE("y")
|
||||||
|
TYPE(SomeEnumStruct)HAS_DBUS_TYPE_SIGNATURE("x")
|
||||||
|
TYPE(SomeClassicEnum)HAS_DBUS_TYPE_SIGNATURE("u")
|
||||||
TYPE(std::map<int32_t, int64_t>)HAS_DBUS_TYPE_SIGNATURE("a{ix}")
|
TYPE(std::map<int32_t, int64_t>)HAS_DBUS_TYPE_SIGNATURE("a{ix}")
|
||||||
TYPE(std::unordered_map<int32_t, int64_t>)HAS_DBUS_TYPE_SIGNATURE("a{ix}")
|
TYPE(std::unordered_map<int32_t, int64_t>)HAS_DBUS_TYPE_SIGNATURE("a{ix}")
|
||||||
using ComplexType = std::map<
|
using ComplexType = std::map<
|
||||||
@@ -127,6 +145,9 @@ namespace
|
|||||||
#if __cplusplus >= 202002L
|
#if __cplusplus >= 202002L
|
||||||
, std::span<int16_t>
|
, std::span<int16_t>
|
||||||
#endif
|
#endif
|
||||||
|
, SomeEnumClass
|
||||||
|
, SomeEnumStruct
|
||||||
|
, SomeClassicEnum
|
||||||
, std::map<int32_t, int64_t>
|
, std::map<int32_t, int64_t>
|
||||||
, std::unordered_map<int32_t, int64_t>
|
, std::unordered_map<int32_t, int64_t>
|
||||||
, ComplexType
|
, ComplexType
|
||||||
|
Reference in New Issue
Block a user