QXmpp  Version: 1.15.1
QXmppAsync_p.h
1 // SPDX-FileCopyrightText: 2021 Linus Jahn <lnj@kaidan.im>
2 //
3 // SPDX-License-Identifier: LGPL-2.1-or-later
4 
5 #ifndef QXMPPASYNC_P_H
6 #define QXMPPASYNC_P_H
7 
8 #include "QXmppTask.h"
9 #include "QXmppVisitHelper_p.h"
10 
11 #include <variant>
12 
13 class QDomElement;
14 struct QXmppError;
15 
16 namespace QXmpp::Private {
17 
18 // creates a task in finished state with value
19 template<typename T>
20 QXmppTask<T> makeReadyTask(T &&value) { co_return value; }
21 inline QXmppTask<void> makeReadyTask() { co_return; }
22 
23 // Attaches to existing promise
24 template<typename Result, typename Input, typename Converter>
25 auto chain(QXmppTask<Input> &&source, QObject *context, QXmppPromise<Result> &&p, Converter convert)
26 {
27  if constexpr (std::is_void_v<Input>) {
28  source.then(context, [p = std::move(p), convert = std::move(convert)]() mutable {
29  if constexpr (std::is_void_v<Result>) {
30  convert();
31  p.finish();
32  } else {
33  p.finish(convert());
34  }
35  });
36  } else {
37  source.then(context, [p = std::move(p), convert = std::move(convert)](Input &&input) mutable {
38  if constexpr (std::is_void_v<Result>) {
39  convert(std::move(input));
40  p.finish();
41  } else {
42  p.finish(convert(std::move(input)));
43  }
44  });
45  }
46 }
47 
48 // creates new task which converts the result of the first
49 template<typename Result, typename Input, typename Converter>
50 auto chain(QXmppTask<Input> &&source, QObject *context, Converter convert) -> QXmppTask<Result>
51 {
53  auto task = p.task();
54  if constexpr (std::is_void_v<Input>) {
55  source.then(context, [p = std::move(p), convert = std::move(convert)]() mutable {
56  if constexpr (std::is_void_v<Result>) {
57  convert();
58  p.finish();
59  } else {
60  p.finish(convert());
61  }
62  });
63  } else {
64  source.then(context, [p = std::move(p), convert = std::move(convert)](Input &&input) mutable {
65  if constexpr (std::is_void_v<Result>) {
66  convert(std::move(input));
67  p.finish();
68  } else {
69  p.finish(convert(std::move(input)));
70  }
71  });
72  }
73  return task;
74 }
75 
76 // parse Iq type from QDomElement or pass error
77 template<typename IqType, typename Converter>
78 auto parseIq(std::variant<QDomElement, QXmppError> &&sendResult, Converter convert)
79 {
80  using Result = std::invoke_result_t<Converter, IqType &&>;
81  return std::visit(
82  overloaded {
83  [convert = std::move(convert)](const QDomElement &element) -> Result {
84  IqType iq;
85  iq.parse(element);
86  return convert(std::move(iq));
87  },
88  [](QXmppError &&error) -> Result {
89  return error;
90  },
91  },
92  std::move(sendResult));
93 }
94 
95 template<typename IqType>
96 auto parseIq(std::variant<QDomElement, QXmppError> &&sendResult) -> std::variant<IqType, QXmppError>
97 {
98  return parseIq<IqType>(std::move(sendResult), [](IqType &&iq) {
99  return std::variant<IqType, QXmppError> { iq };
100  });
101 }
102 
103 } // namespace QXmpp::Private
104 
105 #endif // QXMPPASYNC_P_H
Definition: QXmppError.h:17
QXmppTask< T > task()
Definition: QXmppTask.h:167
Definition: QXmppTask.h:67
void finish() requires(std
Definition: QXmppTask.h:184
Create and update QXmppTask objects to communicate results of asynchronous operations.
Definition: QXmppTask.h:80
Definition: Algorithms.h:14
std::variant< T, QXmppError > Result
Definition: QXmppGlobal.h:209