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, 6, 0)
70QFuture<T> makeReadyFuture(T &&value) {
return QtFuture::makeReadyValueFuture(std::move(value)); }
71#elif QT_VERSION >= QT_VERSION_CHECK(6, 1, 0)
72using QtFuture::makeReadyFuture;
75QFuture<T> makeReadyFuture(T &&value)
77 QFutureInterface<T> interface(QFutureInterfaceBase::Started);
78 interface.reportResult(std::move(value));
79 interface.reportFinished();
80 return interface.future();
83inline QFuture<void> makeReadyFuture()
85 using State = QFutureInterfaceBase::State;
86 return QFutureInterface<void>(State(State::Started | State::Finished)).future();
94 promise.finish(std::move(value));
95 return promise.
task();
102 return promise.
task();
105template<
typename T,
typename Handler>
106void await(
const QFuture<T> &future, QObject *context, Handler handler)
108 auto *watcher =
new QFutureWatcher<T>(context);
109 QObject::connect(watcher, &QFutureWatcherBase::finished,
110 context, [watcher, handler = std::move(handler)]()
mutable {
111 handler(watcher->result());
112 watcher->deleteLater();
114 watcher->setFuture(future);
117template<
typename Handler>
118void await(
const QFuture<void> &future, QObject *context, Handler handler)
120 auto *watcher =
new QFutureWatcher<void>(context);
121 QObject::connect(watcher, &QFutureWatcherBase::finished,
122 context, [watcher, handler = std::move(handler)]()
mutable {
124 watcher->deleteLater();
126 watcher->setFuture(future);
129template<
typename Result,
typename Input,
typename Converter>
134 source.then(context, [=](Input &&input)
mutable {
135 promise.finish(task(std::move(input)));
137 return promise.
task();
140template<
typename IqType,
typename Input,
typename Converter>
141auto parseIq(Input &&sendResult, Converter convert) ->
decltype(convert({}))
143 using Result =
decltype(convert({}));
144 return std::visit(overloaded {
145 [convert = std::move(convert)](
const QDomElement &element) -> Result {
148 return convert(std::move(iq));
154 std::move(sendResult));
157template<
typename IqType,
typename Result,
typename Input>
158auto parseIq(Input &&sendResult) -> Result
160 return parseIq<IqType>(std::move(sendResult), [](IqType &&iq) -> Result {
166template<
typename Input,
typename Converter>
169 using Result =
decltype(convert({}));
170 using IqType = std::decay_t<first_argument_t<Converter>>;
171 return chain<Result>(std::move(input), context, [convert = std::move(convert)](Input &&input) -> Result {
172 return parseIq<IqType>(std::move(input), convert);
176template<
typename Result,
typename Input>
180 using IqType = std::decay_t<decltype(std::get<0>(Result {}))>;
181 return chain<Result>(std::move(input), context, [](Input &&sendResult)
mutable {
182 return parseIq<IqType, Result>(sendResult);
186template<
typename T,
typename Err,
typename Function>
187auto mapSuccess(std::variant<T, Err> var, Function lambda)
189 using MapResult = std::decay_t<
decltype(lambda({}))>;
190 using MappedVariant = std::variant<MapResult, Err>;
191 return std::visit(overloaded {
192 [lambda = std::move(lambda)](T val) -> MappedVariant {
193 return lambda(std::move(val));
195 [](Err err) -> MappedVariant {
201template<
typename T,
typename Err>
202auto mapToSuccess(std::variant<T, Err> var)
204 return mapSuccess(std::move(var), [](T) {
209template<
typename T,
typename Err>
212 return chain<std::variant<QXmpp::Success, QXmppError>>(std::move(source), context, mapToSuccess<T, Err>);
215template<
typename Input,
typename Converter>
216auto chainMapSuccess(
QXmppTask<Input> &&source, QObject *context, Converter convert)
218 return chain<std::variant<
decltype(convert({})),
QXmppError>>(std::move(source), context, [convert](Input &&input) {
219 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