summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Redondo <[email protected]>2024-12-11 12:23:45 +0100
committerDavid Redondo <[email protected]>2024-12-13 19:04:27 +0100
commit11518e92c2b4c0586d4ec29e50676049981c4239 (patch)
tree589677f21d8dc27ece44ecb7f8d28df9e467e8fb
parent95f02adf756d1ae485f39a060c6f23a5af3f64ee (diff)
Provide D-Bus de-/marshalling operators for std::tuple
Currently Qt provides only generic operators for pairs which can be used generically for structs with two elements. A tuple is the natural fit for dealing generically with structs that have more elements. This can be helpful when wanting to make a one-of calls to APIs that take or return such types or deferring to tuple marshalling without having to write custom operators. [ChangeLog][QtDBus][QDBusArgument] Added generic support for marshalling and demarshalling D-Bus STRUCTs from/to std::tuple. Change-Id: Id5cf49063c9b43ed68ad7821111376f6fa887a73 Reviewed-by: Thiago Macieira <[email protected]>
-rw-r--r--src/dbus/doc/src/dbus-adaptors.qdoc5
-rw-r--r--src/dbus/qdbusargument.h20
-rw-r--r--tests/auto/dbus/qdbusmarshall/common.h23
-rw-r--r--tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp21
4 files changed, 67 insertions, 2 deletions
diff --git a/src/dbus/doc/src/dbus-adaptors.qdoc b/src/dbus/doc/src/dbus-adaptors.qdoc
index e57cc095b98..2eb977081ce 100644
--- a/src/dbus/doc/src/dbus-adaptors.qdoc
+++ b/src/dbus/doc/src/dbus-adaptors.qdoc
@@ -295,8 +295,9 @@
Qt D-Bus provides template specializations for arrays and maps for
use with Qt's \l{Container classes}{container classes}, such as
QMap and QList, so it is not necessary to write the streaming
- operator functions for those. For other types, and specially for
- types implementing structures, the operators have to be explicitly
+ operator functions for those. For structures Qt provides generic
+ specializations mapping to and from \c std::tuple. In order to use
+ a custom type instead or for other types the operators have to be explicitly
implemented.
See the documentation for QDBusArgument for examples for
diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h
index 70f6703d2f2..8370de74bb6 100644
--- a/src/dbus/qdbusargument.h
+++ b/src/dbus/qdbusargument.h
@@ -321,6 +321,26 @@ inline const QDBusArgument &operator>>(const QDBusArgument &arg, std::pair<T1, T
return arg;
}
+template <typename... T>
+QDBusArgument &operator<<(QDBusArgument &argument, const std::tuple<T...> &tuple)
+{
+ static_assert(std::tuple_size_v<std::tuple<T...>> != 0, "D-Bus doesn't allow empty structs");
+ argument.beginStructure();
+ std::apply([&argument](const auto &...elements) { (argument << ... << elements); }, tuple);
+ argument.endStructure();
+ return argument;
+}
+
+template <typename... T>
+const QDBusArgument &operator>>(const QDBusArgument &argument, std::tuple<T...> &tuple)
+{
+ static_assert(std::tuple_size_v<std::tuple<T...>> != 0, "D-Bus doesn't allow empty structs");
+ argument.beginStructure();
+ std::apply([&argument](auto &...elements) { (argument >> ... >> elements); }, tuple);
+ argument.endStructure();
+ return argument;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/tests/auto/dbus/qdbusmarshall/common.h b/tests/auto/dbus/qdbusmarshall/common.h
index 9a7c1e1553a..8f1ecad29de 100644
--- a/tests/auto/dbus/qdbusmarshall/common.h
+++ b/tests/auto/dbus/qdbusmarshall/common.h
@@ -160,6 +160,14 @@ void commonInit()
qDBusRegisterMetaType<QList<MyVariantMapStruct> >();
qDBusRegisterMetaType<MyFileDescriptorStruct>();
qDBusRegisterMetaType<QList<MyFileDescriptorStruct> >();
+
+ qDBusRegisterMetaType<std::tuple<int>>();
+ qDBusRegisterMetaType<std::tuple<QString>>();
+ qDBusRegisterMetaType<std::tuple<QVariantMap>>();
+ qDBusRegisterMetaType<std::tuple<QPoint>>();
+ qDBusRegisterMetaType<std::tuple<std::tuple<int>>>();
+ qDBusRegisterMetaType<std::tuple<QList<int>>>();
+ qDBusRegisterMetaType<std::tuple<int, QString, QVariantMap>>();
}
#ifdef USE_PRIVATE_CODE
#include "private/qdbusintrospection_p.h"
@@ -510,6 +518,21 @@ bool compareToArgument(const QDBusArgument &arg, const QVariant &v2)
return compare<MyFileDescriptorStruct>(arg, v2);
else if (id == qMetaTypeId<QList<MyFileDescriptorStruct> >())
return compare<QList<MyFileDescriptorStruct> >(arg, v2);
+
+ else if (id == qMetaTypeId<std::tuple<int>>())
+ return compare<std::tuple<int>>(arg, v2);
+ else if (id == qMetaTypeId<std::tuple<QString>>())
+ return compare<std::tuple<QString>>(arg, v2);
+ else if (id == qMetaTypeId<std::tuple<QVariantMap>>())
+ return compare<std::tuple<QVariantMap>>(arg, v2);
+ else if (id == qMetaTypeId<std::tuple<QPoint>>())
+ return compare<std::tuple<QPoint>>(arg, v2);
+ else if (id == qMetaTypeId<std::tuple<std::tuple<int>>>())
+ return compare<std::tuple<std::tuple<int>>>(arg, v2);
+ else if (id == qMetaTypeId<std::tuple<QList<int>>>())
+ return compare<std::tuple<QList<int>>>(arg, v2);
+ else if (id == qMetaTypeId<std::tuple<int, QString, QVariantMap>>())
+ return compare<std::tuple<int, QString, QVariantMap>>(arg, v2);
}
qWarning() << "Unexpected QVariant type" << v2.userType()
diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
index ea515536e6e..79db456cfbd 100644
--- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
+++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp
@@ -549,6 +549,27 @@ void tst_QDBusMarshall::sendStructs_data()
list << mvms;
QTest::newRow("list-of-string-variantmap") << QVariant::fromValue(list) << "a(sa{sv})" << "[Argument: a(sa{sv}) {[Argument: (sa{sv}) \"Hello, World\", [Argument: a{sv} {\"bytearray\" = [Variant(QByteArray): {72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100}], \"int\" = [Variant(int): 42], \"short\" = [Variant(short): -47], \"uint\" = [Variant(uint): 42]}]]}]";
+ QTest::newRow("std::tuple<int>")
+ << QVariant::fromValue(std::tuple<int>{ 1 }) << "(i)" << "[Argument: (i) 1]";
+ QTest::newRow("std::tuple<QString>") << QVariant::fromValue(std::tuple<QString>{ "foo" })
+ << "(s)" << "[Argument: (s) \"foo\"]";
+ QTest::newRow("std::tuple<QVariantMap>")
+ << QVariant::fromValue(std::tuple<QVariantMap>{ { { "foo", 1 } } }) << "(a{sv})"
+ << "[Argument: (a{sv}) [Argument: a{sv} {\"foo\" = [Variant(int): 1]}]]";
+ QTest::newRow("std::tuple<QPoint>") << QVariant::fromValue(std::tuple<QPoint>{ { 1, 2 } })
+ << "((ii))" << "[Argument: ((ii)) [Argument: (ii) 1, 2]]";
+ QTest::newRow("std::tuple<std::tuple<int>>")
+ << QVariant::fromValue(std::tuple<std::tuple<int>>{ 1 }) << "((i))"
+ << "[Argument: ((i)) [Argument: (i) 1]]";
+ QTest::newRow("std::tuple<QList<int>>")
+ << QVariant::fromValue(std::tuple<QList<int>>{ { 1, 2, 3 } }) << "(ai)"
+ << "[Argument: (ai) [Argument: ai {1, 2, 3}]]";
+ QTest::newRow("std::tuple<int, QString, QVariantMap>")
+ << QVariant::fromValue(
+ std::tuple<int, QString, QVariantMap>{ 1, "foo", { { "bar", 2 } } })
+ << "(isa{sv})"
+ << "[Argument: (isa{sv}) 1, \"foo\", [Argument: a{sv} {\"bar\" = [Variant(int): 2]}]]";
+
if (fileDescriptorPassing) {
MyFileDescriptorStruct fds;
fds.fd = QDBusUnixFileDescriptor(fileDescriptorForTest());