forked from Kistler-Group/sdbus-cpp
feat: make Struct tuple-like class (#343)
This commit is contained in:
@ -104,6 +104,10 @@ namespace sdbus {
|
|||||||
*
|
*
|
||||||
* Representation of struct D-Bus type
|
* Representation of struct D-Bus type
|
||||||
*
|
*
|
||||||
|
* Struct implements tuple protocol, i.e. it's a tuple-like class.
|
||||||
|
* It can be used with std::get<>(), std::tuple_element,
|
||||||
|
* std::tuple_size and in structured bindings.
|
||||||
|
*
|
||||||
***********************************************/
|
***********************************************/
|
||||||
template <typename... _ValueTypes>
|
template <typename... _ValueTypes>
|
||||||
class Struct
|
class Struct
|
||||||
@ -135,6 +139,9 @@ namespace sdbus {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename... _Elements>
|
||||||
|
Struct(_Elements...) -> Struct<_Elements...>;
|
||||||
|
|
||||||
template<typename... _Elements>
|
template<typename... _Elements>
|
||||||
constexpr Struct<std::decay_t<_Elements>...>
|
constexpr Struct<std::decay_t<_Elements>...>
|
||||||
make_struct(_Elements&&... args)
|
make_struct(_Elements&&... args)
|
||||||
@ -280,4 +287,14 @@ namespace sdbus {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <size_t _I, typename... _ValueTypes>
|
||||||
|
struct std::tuple_element<_I, sdbus::Struct<_ValueTypes...>>
|
||||||
|
: std::tuple_element<_I, std::tuple<_ValueTypes...>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
template <typename... _ValueTypes>
|
||||||
|
struct std::tuple_size<sdbus::Struct<_ValueTypes...>>
|
||||||
|
: std::tuple_size<std::tuple<_ValueTypes...>>
|
||||||
|
{};
|
||||||
|
|
||||||
#endif /* SDBUS_CXX_TYPES_H_ */
|
#endif /* SDBUS_CXX_TYPES_H_ */
|
||||||
|
@ -93,7 +93,7 @@ std::map<int32_t, sdbus::Variant> TestAdaptor::getMapOfVariants(const std::vecto
|
|||||||
|
|
||||||
sdbus::Struct<std::string, sdbus::Struct<std::map<int32_t, int32_t>>> TestAdaptor::getStructInStruct()
|
sdbus::Struct<std::string, sdbus::Struct<std::map<int32_t, int32_t>>> TestAdaptor::getStructInStruct()
|
||||||
{
|
{
|
||||||
return sdbus::make_struct(STRING_VALUE, sdbus::make_struct(std::map<int32_t, int32_t>{{INT32_VALUE, INT32_VALUE}}));
|
return sdbus::Struct{STRING_VALUE, sdbus::Struct{std::map<int32_t, int32_t>{{INT32_VALUE, INT32_VALUE}}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t TestAdaptor::sumStructItems(const sdbus::Struct<uint8_t, uint16_t>& a, const sdbus::Struct<int32_t, int64_t>& b)
|
int32_t TestAdaptor::sumStructItems(const sdbus::Struct<uint8_t, uint16_t>& a, const sdbus::Struct<int32_t, int64_t>& b)
|
||||||
|
@ -67,7 +67,7 @@ TEST(AVariant, CanBeConstructedFromASimpleValue)
|
|||||||
TEST(AVariant, CanBeConstructedFromAComplexValue)
|
TEST(AVariant, CanBeConstructedFromAComplexValue)
|
||||||
{
|
{
|
||||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||||
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{sdbus::make_struct("hello"s, ANY_DOUBLE), sdbus::make_struct("world"s, ANY_DOUBLE)}} };
|
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{{"hello"s, ANY_DOUBLE}, {"world"s, ANY_DOUBLE}}} };
|
||||||
|
|
||||||
ASSERT_NO_THROW(sdbus::Variant{value});
|
ASSERT_NO_THROW(sdbus::Variant{value});
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ TEST(ASimpleVariant, ReturnsTheSimpleValueWhenAsked)
|
|||||||
TEST(AComplexVariant, ReturnsTheComplexValueWhenAsked)
|
TEST(AComplexVariant, ReturnsTheComplexValueWhenAsked)
|
||||||
{
|
{
|
||||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||||
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{sdbus::make_struct("hello"s, ANY_DOUBLE), sdbus::make_struct("world"s, ANY_DOUBLE)}} };
|
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{{"hello"s, ANY_DOUBLE}, {"world"s, ANY_DOUBLE}}} };
|
||||||
|
|
||||||
sdbus::Variant variant(value);
|
sdbus::Variant variant(value);
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ TEST(AVariant, HasConceptuallyNonmutableGetMethodWhichCanBeCalledXTimes)
|
|||||||
TEST(AVariant, ReturnsTrueWhenAskedIfItContainsTheTypeItReallyContains)
|
TEST(AVariant, ReturnsTrueWhenAskedIfItContainsTheTypeItReallyContains)
|
||||||
{
|
{
|
||||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||||
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{sdbus::make_struct("hello"s, ANY_DOUBLE), sdbus::make_struct("world"s, ANY_DOUBLE)}} };
|
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{{"hello"s, ANY_DOUBLE}, {"world"s, ANY_DOUBLE}}} };
|
||||||
|
|
||||||
sdbus::Variant variant(value);
|
sdbus::Variant variant(value);
|
||||||
|
|
||||||
@ -143,8 +143,8 @@ TEST(AVariant, CanContainOtherEmbeddedVariants)
|
|||||||
{
|
{
|
||||||
using TypeWithVariants = std::vector<sdbus::Struct<sdbus::Variant, double>>;
|
using TypeWithVariants = std::vector<sdbus::Struct<sdbus::Variant, double>>;
|
||||||
TypeWithVariants value;
|
TypeWithVariants value;
|
||||||
value.emplace_back(sdbus::make_struct(sdbus::Variant("a string"), ANY_DOUBLE));
|
value.push_back({sdbus::Variant("a string"), ANY_DOUBLE});
|
||||||
value.emplace_back(sdbus::make_struct(sdbus::Variant(ANY_UINT64), ANY_DOUBLE));
|
value.push_back({sdbus::Variant(ANY_UINT64), ANY_DOUBLE});
|
||||||
|
|
||||||
sdbus::Variant variant(value);
|
sdbus::Variant variant(value);
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ TEST(AnEmptyVariant, ThrowsWhenBeingSerializedToAMessage)
|
|||||||
TEST(ANonEmptyVariant, SerializesToAndDeserializesFromAMessageSuccessfully)
|
TEST(ANonEmptyVariant, SerializesToAndDeserializesFromAMessageSuccessfully)
|
||||||
{
|
{
|
||||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||||
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{sdbus::make_struct("hello"s, ANY_DOUBLE), sdbus::make_struct("world"s, ANY_DOUBLE)}} };
|
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{{"hello"s, ANY_DOUBLE}, {"world"s, ANY_DOUBLE}}} };
|
||||||
sdbus::Variant variant(value);
|
sdbus::Variant variant(value);
|
||||||
|
|
||||||
auto msg = sdbus::createPlainMessage();
|
auto msg = sdbus::createPlainMessage();
|
||||||
@ -187,7 +187,7 @@ TEST(ANonEmptyVariant, SerializesToAndDeserializesFromAMessageSuccessfully)
|
|||||||
TEST(CopiesOfVariant, SerializeToAndDeserializeFromMessageSuccessfully)
|
TEST(CopiesOfVariant, SerializeToAndDeserializeFromMessageSuccessfully)
|
||||||
{
|
{
|
||||||
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
using ComplexType = std::map<uint64_t, std::vector<sdbus::Struct<std::string, double>>>;
|
||||||
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{sdbus::make_struct("hello"s, ANY_DOUBLE), sdbus::make_struct("world"s, ANY_DOUBLE)}} };
|
ComplexType value{ {ANY_UINT64, ComplexType::mapped_type{{"hello"s, ANY_DOUBLE}, {"world"s, ANY_DOUBLE}}} };
|
||||||
sdbus::Variant variant(value);
|
sdbus::Variant variant(value);
|
||||||
auto variantCopy1{variant};
|
auto variantCopy1{variant};
|
||||||
auto variantCopy2 = variant;
|
auto variantCopy2 = variant;
|
||||||
@ -207,15 +207,41 @@ TEST(CopiesOfVariant, SerializeToAndDeserializeFromMessageSuccessfully)
|
|||||||
ASSERT_THAT(receivedVariant3.get<decltype(value)>(), Eq(value));
|
ASSERT_THAT(receivedVariant3.get<decltype(value)>(), Eq(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AStruct, CreatesStructFromTuple)
|
TEST(AStruct, CanBeCreatedFromStdTuple)
|
||||||
{
|
{
|
||||||
std::tuple<int32_t, std::string> value{1234, "abcd"};
|
std::tuple<int32_t, std::string> value{1234, "abcd"};
|
||||||
sdbus::Struct<int32_t, std::string> valueStruct{value};
|
sdbus::Struct valueStruct{value};
|
||||||
|
|
||||||
|
ASSERT_THAT(valueStruct.get<0>(), Eq(std::get<0>(value)));
|
||||||
|
ASSERT_THAT(valueStruct.get<1>(), Eq(std::get<1>(value)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AStruct, CanProvideItsDataThroughStdGet)
|
||||||
|
{
|
||||||
|
std::tuple<int32_t, std::string> value{1234, "abcd"};
|
||||||
|
sdbus::Struct valueStruct{value};
|
||||||
|
|
||||||
ASSERT_THAT(std::get<0>(valueStruct), Eq(std::get<0>(value)));
|
ASSERT_THAT(std::get<0>(valueStruct), Eq(std::get<0>(value)));
|
||||||
ASSERT_THAT(std::get<1>(valueStruct), Eq(std::get<1>(value)));
|
ASSERT_THAT(std::get<1>(valueStruct), Eq(std::get<1>(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(AStruct, CanBeUsedLikeStdTupleType)
|
||||||
|
{
|
||||||
|
using StructType = sdbus::Struct<int, std::string, bool>;
|
||||||
|
|
||||||
|
static_assert(std::tuple_size_v<StructType> == 3);
|
||||||
|
static_assert(std::is_same_v<std::tuple_element_t<1, StructType>, std::string>);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(AStruct, CanBeUsedInStructuredBinding)
|
||||||
|
{
|
||||||
|
sdbus::Struct valueStruct(1234, "abcd", true);
|
||||||
|
|
||||||
|
auto [first, second, third] = valueStruct;
|
||||||
|
|
||||||
|
ASSERT_THAT(std::tie(first, second, third), Eq(std::tuple{1234, "abcd", true}));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(AnObjectPath, CanBeConstructedFromCString)
|
TEST(AnObjectPath, CanBeConstructedFromCString)
|
||||||
{
|
{
|
||||||
const char* aPath = "/some/path";
|
const char* aPath = "/some/path";
|
||||||
|
Reference in New Issue
Block a user