diff options
| author | Linus Jahn <lnj@kaidan.im> | 2021-04-28 18:04:20 +0200 |
|---|---|---|
| committer | Linus Jahn <lnj@kaidan.im> | 2021-06-27 20:17:17 +0200 |
| commit | 5d33b33a25061675ca422523aaba7fdfa0d39014 (patch) | |
| tree | 8d2b4ffb05a8e5c80cfd43661b3625255d24bd04 /src | |
| parent | 3caffcebf16680576d8dd785437eed16a6c5f36d (diff) | |
| download | qxmpp-5d33b33a25061675ca422523aaba7fdfa0d39014.tar.gz | |
Add QFuture chaining utilities
Diffstat (limited to 'src')
| -rw-r--r-- | src/base/QXmppGlobal_p.h | 109 |
1 files changed, 109 insertions, 0 deletions
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 <memory> +#include <variant> + +#include <QFutureWatcher> +#include <QObject> + +#include <QXmppIq.h> + +// helper for std::visit +template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; }; +// explicit deduction guide (not needed as of C++20) +template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>; + +template<typename T> +QFuture<T> makeReadyFuture(T &&value) +{ + QFutureInterface<T> interface(QFutureInterfaceBase::Started); + interface.reportResult(value); + interface.reportFinished(); + return interface.future(); +} + +template<typename Result, typename Input, typename Converter> +QFuture<Result> chain(QFuture<Input> &&source, QObject *context, Converter task) +{ + auto resultInterface = std::make_shared<QFutureInterface<Result>>(QFutureInterfaceBase::Started); + + auto *watcher = new QFutureWatcher<Input>(context); + QObject::connect(watcher, &QFutureWatcherBase::finished, context, [=](){ + resultInterface->reportResult(task(watcher->result())); + resultInterface->reportFinished(); + watcher->deleteLater(); + }); + watcher->setFuture(source); + return resultInterface->future(); +} + +template<typename Result, typename IqType, typename Input, typename Converter> +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<typename Result, typename IqType, typename Input> +Result parseIq(Input &&sendResult) +{ + return parseIq<Result, IqType>(std::move(sendResult), [](IqType &&iq) { + // no conversion + return iq; + }); +} + +template<typename Result, typename IqType, typename Input, typename Converter> +QFuture<Result> chainIq(QFuture<Input> &&input, QObject *context, Converter convert) +{ + return chain<Result>(std::move(input), context, [convert {std::move(convert)}](Input &&input) -> Result { + return parseIq<Result, IqType>(std::move(input), convert); + }); +} + +template<typename Result, typename IqType, typename Input> +QFuture<Result> chainIq(QFuture<Input> &&input, QObject *context) +{ + return chain<Result>(std::move(input), context, [](Input &&sendResult) { + return parseIq<Result, IqType>(sendResult); + }); +} + +#endif // QXMPPGLOBAL_P_H |
