5#ifndef QXMPPFUTUREUTILS_P_H
6#define QXMPPFUTUREUTILS_P_H
19#include "QXmppPromise.h"
20#include "QXmppSendResult.h"
25#include <QFutureWatcher>
28namespace QXmpp::Private {
32struct overloaded : Ts... {
33 using Ts::operator()...;
37overloaded(Ts...) -> overloaded<Ts...>;
40template<
typename ReturnType,
typename T,
typename Visitor>
41auto visitForward(T variant, Visitor visitor)
43 return std::visit([&](
auto &&value) -> ReturnType {
44 using ValueType = std::decay_t<
decltype(value)>;
45 if constexpr (std::is_invocable_v<Visitor, ValueType>) {
46 return visitor(std::move(value));
51 std::forward<T>(variant));
54template<
typename F,
typename Ret,
typename A,
typename... Rest>
55A lambda_helper(Ret (F::*)(A, Rest...));
57template<
typename F,
typename Ret,
typename A,
typename... Rest>
58A lambda_helper(Ret (F::*)(A, Rest...)
const);
61struct first_argument {
62 using type =
decltype(lambda_helper(&F::operator()));
66using first_argument_t =
typename first_argument<F>::type;
68#if QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
69using QtFuture::makeReadyFuture;
72QFuture<T> makeReadyFuture(T &&value)
74 QFutureInterface<T> interface(QFutureInterfaceBase::Started);
75 interface.reportResult(std::move(value));
76 interface.reportFinished();
77 return interface.future();
80inline QFuture<void> makeReadyFuture()
82 using State = QFutureInterfaceBase::State;
83 return QFutureInterface<void>(State(State::Started | State::Finished)).future();
91 promise.finish(std::move(value));
92 return promise.
task();
99 return promise.
task();
102template<
typename T,
typename Handler>
103void await(
const QFuture<T> &future, QObject *context, Handler handler)
105 auto *watcher =
new QFutureWatcher<T>(context);
106 QObject::connect(watcher, &QFutureWatcherBase::finished,
107 context, [watcher, handler = std::move(handler)]()
mutable {
108 handler(watcher->result());
109 watcher->deleteLater();
111 watcher->setFuture(future);
114template<
typename Handler>
115void await(
const QFuture<void> &future, QObject *context, Handler handler)
117 auto *watcher =
new QFutureWatcher<void>(context);
118 QObject::connect(watcher, &QFutureWatcherBase::finished,
119 context, [watcher, handler = std::move(handler)]()
mutable {
121 watcher->deleteLater();
123 watcher->setFuture(future);
126template<
typename Result,
typename Input,
typename Converter>
131 source.then(context, [=](Input &&input)
mutable {
132 promise.finish(task(std::move(input)));
134 return promise.
task();
137template<
typename IqType,
typename Input,
typename Converter>
138auto parseIq(Input &&sendResult, Converter convert) ->
decltype(convert({}))
140 using Result =
decltype(convert({}));
141 return std::visit(overloaded {
142 [convert = std::move(convert)](
const QDomElement &element) -> Result {
145 return convert(std::move(iq));
151 std::move(sendResult));
154template<
typename IqType,
typename Result,
typename Input>
155auto parseIq(Input &&sendResult) -> Result
157 return parseIq<IqType>(std::move(sendResult), [](IqType &&iq) -> Result {
163template<
typename Input,
typename Converter>
166 using Result =
decltype(convert({}));
167 using IqType = std::decay_t<first_argument_t<Converter>>;
168 return chain<Result>(std::move(input), context, [convert = std::move(convert)](Input &&input) -> Result {
169 return parseIq<IqType>(std::move(input), convert);
173template<
typename Result,
typename Input>
177 using IqType = std::decay_t<decltype(std::get<0>(Result {}))>;
178 return chain<Result>(std::move(input), context, [](Input &&sendResult)
mutable {
179 return parseIq<IqType, Result>(sendResult);
183template<
typename T,
typename Err,
typename Function>
184auto mapSuccess(std::variant<T, Err> var, Function lambda)
186 using MapResult = std::decay_t<
decltype(lambda({}))>;
187 using MappedVariant = std::variant<MapResult, Err>;
188 return std::visit(overloaded {
189 [lambda = std::move(lambda)](T val) -> MappedVariant {
190 return lambda(std::move(val));
192 [](Err err) -> MappedVariant {
198template<
typename T,
typename Err>
199auto mapToSuccess(std::variant<T, Err> var)
201 return mapSuccess(std::move(var), [](T) {
206template<
typename T,
typename Err>
209 return chain<std::variant<QXmpp::Success, QXmppError>>(std::move(source), context, mapToSuccess<T, Err>);
212template<
typename Input,
typename Converter>
213auto chainMapSuccess(
QXmppTask<Input> &&source, QObject *context, Converter convert)
215 return chain<std::variant<
decltype(convert({})),
QXmppError>>(std::move(source), context, [convert](Input &&input) {
216 return mapSuccess(std::move(input), convert);
Create and update QXmppTask objects to communicate results of asynchronous operations.
Definition: QXmppPromise.h:23
QXmppTask< T > task()
Definition: QXmppPromise.h:96
Definition: QXmppTask.h:62
Definition: QXmppError.h:17