Skip to content

Commit

Permalink
feat: make Struct tuple-like class
Browse files Browse the repository at this point in the history
  • Loading branch information
sangelovic committed Aug 2, 2023
1 parent 29c877a commit 30431d2
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 10 deletions.
17 changes: 17 additions & 0 deletions include/sdbus-c++/Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ namespace sdbus {
*
* 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>
class Struct
Expand Down Expand Up @@ -135,6 +139,9 @@ namespace sdbus {
}
};

template <typename... _Elements>
Struct(_Elements...) -> Struct<_Elements...>;

template<typename... _Elements>
constexpr Struct<std::decay_t<_Elements>...>
make_struct(_Elements&&... args)
Expand Down Expand Up @@ -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_ */
2 changes: 1 addition & 1 deletion tests/integrationtests/TestAdaptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
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)
Expand Down
44 changes: 35 additions & 9 deletions tests/unittests/Types_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ TEST(AVariant, CanBeConstructedFromASimpleValue)
TEST(AVariant, CanBeConstructedFromAComplexValue)
{
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});
}
Expand Down Expand Up @@ -103,7 +103,7 @@ TEST(ASimpleVariant, ReturnsTheSimpleValueWhenAsked)
TEST(AComplexVariant, ReturnsTheComplexValueWhenAsked)
{
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);

Expand All @@ -123,7 +123,7 @@ TEST(AVariant, HasConceptuallyNonmutableGetMethodWhichCanBeCalledXTimes)
TEST(AVariant, ReturnsTrueWhenAskedIfItContainsTheTypeItReallyContains)
{
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);

Expand All @@ -143,8 +143,8 @@ TEST(AVariant, CanContainOtherEmbeddedVariants)
{
using TypeWithVariants = std::vector<sdbus::Struct<sdbus::Variant, double>>;
TypeWithVariants value;
value.emplace_back(sdbus::make_struct(sdbus::Variant("a string"), ANY_DOUBLE));
value.emplace_back(sdbus::make_struct(sdbus::Variant(ANY_UINT64), ANY_DOUBLE));
value.push_back({sdbus::Variant("a string"), ANY_DOUBLE});
value.push_back({sdbus::Variant(ANY_UINT64), ANY_DOUBLE});

sdbus::Variant variant(value);

Expand Down Expand Up @@ -172,7 +172,7 @@ TEST(AnEmptyVariant, ThrowsWhenBeingSerializedToAMessage)
TEST(ANonEmptyVariant, SerializesToAndDeserializesFromAMessageSuccessfully)
{
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);

auto msg = sdbus::createPlainMessage();
Expand All @@ -187,7 +187,7 @@ TEST(ANonEmptyVariant, SerializesToAndDeserializesFromAMessageSuccessfully)
TEST(CopiesOfVariant, SerializeToAndDeserializeFromMessageSuccessfully)
{
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);
auto variantCopy1{variant};
auto variantCopy2 = variant;
Expand All @@ -207,15 +207,41 @@ TEST(CopiesOfVariant, SerializeToAndDeserializeFromMessageSuccessfully)
ASSERT_THAT(receivedVariant3.get<decltype(value)>(), Eq(value));
}

TEST(AStruct, CreatesStructFromTuple)
TEST(AStruct, CanBeCreatedFromStdTuple)
{
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<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)
{
const char* aPath = "/some/path";
Expand Down

0 comments on commit 30431d2

Please sign in to comment.