From 5d33b33a25061675ca422523aaba7fdfa0d39014 Mon Sep 17 00:00:00 2001 From: Linus Jahn Date: Wed, 28 Apr 2021 18:04:20 +0200 Subject: Add QFuture chaining utilities --- src/base/QXmppGlobal_p.h | 109 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/base/QXmppGlobal_p.h (limited to 'src/base') diff --git a/src/base/QXmppGlobal_p.h b/src/base/QXmppGlobal_p.h new file mode 100644 index 00000000..0df63fed --- /dev/null +++ b/src/base/QXmppGlobal_p.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008-2021 The QXmpp developers + * + * Author: + * Linus Jahn + * + * Source: + * https://github.com/qxmpp-project/qxmpp + * + * This file is a part of QXmpp library. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + */ + +#ifndef QXMPPGLOBAL_P_H +#define QXMPPGLOBAL_P_H + +#include +#include + +#include +#include + +#include + +// helper for std::visit +template struct overloaded : Ts... { using Ts::operator()...; }; +// explicit deduction guide (not needed as of C++20) +template overloaded(Ts...) -> overloaded; + +template +QFuture makeReadyFuture(T &&value) +{ + QFutureInterface interface(QFutureInterfaceBase::Started); + interface.reportResult(value); + interface.reportFinished(); + return interface.future(); +} + +template +QFuture chain(QFuture &&source, QObject *context, Converter task) +{ + auto resultInterface = std::make_shared>(QFutureInterfaceBase::Started); + + auto *watcher = new QFutureWatcher(context); + QObject::connect(watcher, &QFutureWatcherBase::finished, context, [=](){ + resultInterface->reportResult(task(watcher->result())); + resultInterface->reportFinished(); + watcher->deleteLater(); + }); + watcher->setFuture(source); + return resultInterface->future(); +} + +template +Result parseIq(Input &&sendResult, Converter convert) +{ + return std::visit(overloaded { + [convert { std::move(convert) }](const QDomElement &element) -> Result { + IqType iq; + iq.parse(element); + if (iq.type() == QXmppIq::Error) { + return iq.error(); + } + return convert(std::move(iq)); + }, + [](QXmpp::PacketState) -> Result { + using Error = QXmppStanza::Error; + return Error(Error::Wait, Error::UndefinedCondition, + QStringLiteral("Couldn't send request: lost connection.")); + }, + }, sendResult); +} + +template +Result parseIq(Input &&sendResult) +{ + return parseIq(std::move(sendResult), [](IqType &&iq) { + // no conversion + return iq; + }); +} + +template +QFuture chainIq(QFuture &&input, QObject *context, Converter convert) +{ + return chain(std::move(input), context, [convert {std::move(convert)}](Input &&input) -> Result { + return parseIq(std::move(input), convert); + }); +} + +template +QFuture chainIq(QFuture &&input, QObject *context) +{ + return chain(std::move(input), context, [](Input &&sendResult) { + return parseIq(sendResult); + }); +} + +#endif // QXMPPGLOBAL_P_H -- cgit v1.2.3