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 <thiago.macieira@intel.com>
This commit is contained in:
parent
95f02adf75
commit
11518e92c2
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user