QXmpp Version: 1.8.0
Loading...
Searching...
No Matches
QXmppAccountMigrationManager.h
1// SPDX-FileCopyrightText: 2023 Linus Jahn <lnj@kaidan.im>
2// SPDX-FileCopyrightText: 2024 Filipe Azevedo <pasnox@gmail.com>
3//
4// SPDX-License-Identifier: LGPL-2.1-or-later
5
6#ifndef QXMPPACCOUNTMIGRATIONMANAGER_H
7#define QXMPPACCOUNTMIGRATIONMANAGER_H
8
9#include "QXmppClientExtension.h"
10#include "QXmppFutureUtils_p.h"
11#include "QXmppTask.h"
12
13#include <any>
14#include <typeindex>
15
16struct QXmppExportDataPrivate;
17
18class QXMPP_EXPORT QXmppExportData
19{
20public:
21 template<typename T = QXmpp::Success>
22 using Result = std::variant<T, QXmppError>;
23
24 QXmppExportData();
25 QXMPP_PRIVATE_DECLARE_RULE_OF_SIX(QXmppExportData)
26
27 static std::variant<QXmppExportData, QXmppError> fromDom(const QDomElement &);
28 void toXml(QXmlStreamWriter *) const;
29
30 const QString &accountJid() const;
31 void setAccountJid(const QString &jid);
32
33 template<typename T>
34 using ExtensionParser = Result<T> (*)(const QDomElement &);
35 template<typename T>
36 using ExtensionSerializer = void (*)(const T &, QXmlStreamWriter &);
37
38 template<typename T, ExtensionParser<T> parse, ExtensionSerializer<T> serialize>
39 static void registerExtension(QStringView tagName, QStringView xmlns)
40 {
41 using namespace QXmpp::Private;
42 using AnyParser = ExtensionParser<std::any>;
43 using AnySerializer = ExtensionSerializer<std::any>;
44
45 AnyParser parseAny = [](const QDomElement &el) {
46 return std::visit(overloaded {
47 [](T data) -> Result<std::any> { return std::move(data); },
48 [](QXmppError e) -> Result<std::any> { return std::move(e); },
49 },
50 parse(el));
51 };
52
53 AnySerializer serializeAny = [](const std::any &data, QXmlStreamWriter &w) {
54 return std::invoke(serialize, std::any_cast<const T &>(data), w);
55 };
56
57 registerExtensionInternal(std::type_index(typeid(T)), parseAny, serializeAny, tagName, xmlns);
58 }
59
60private:
62 friend class tst_QXmppAccountMigrationManager;
63
64 const std::unordered_map<std::type_index, std::any> &extensions() const;
65 void setExtension(std::any value);
66
67 static void registerExtensionInternal(std::type_index, ExtensionParser<std::any>, ExtensionSerializer<std::any>, QStringView tagName, QStringView xmlns);
68
69 QSharedDataPointer<QXmppExportDataPrivate> d;
70};
71
72struct QXmppAccountMigrationManagerPrivate;
73
75{
76 Q_OBJECT
77
78 friend struct QXmppAccountMigrationManagerPrivate;
79
80public:
81 template<typename T = QXmpp::Success>
82 using Result = std::variant<T, QXmppError>;
83
86
87 QXmppTask<Result<>> importData(const QXmppExportData &account);
89
90 template<typename DataType, typename ImportFunc, typename ExportFunc>
91 void registerExportData(ImportFunc importFunc, ExportFunc exportFunc);
92
93 template<typename DataType>
94 void unregisterExportData();
95
96private:
97 void registerMigrationDataInternal(std::type_index dataType, std::function<QXmppTask<Result<>>(std::any)>, std::function<QXmppTask<Result<std::any>>()>);
98 void unregisterMigrationDataInternal(std::type_index dataType);
99
100 std::unique_ptr<QXmppAccountMigrationManagerPrivate> d;
101};
102
103template<typename DataType, typename ImportFunc, typename ExportFunc>
104void QXmppAccountMigrationManager::registerExportData(ImportFunc importFunc, ExportFunc exportFunc)
105{
106 using namespace QXmpp::Private;
107
108 static_assert(std::is_constructible_v<std::function<QXmppTask<Result<>>(const DataType &)>, ImportFunc>);
109 static_assert(std::is_constructible_v<std::function<QXmppTask<Result<DataType>>()>, ExportFunc>);
110 static_assert(std::is_invocable_v<ImportFunc, const DataType &>);
111 static_assert(std::is_invocable_v<ExportFunc>);
112 static_assert(std::is_same_v<first_argument_t<ImportFunc>, const DataType &>);
113
114 auto importInternal = [importFunc = std::move(importFunc)](std::any data) -> QXmppTask<Result<>> {
115 Q_ASSERT(std::type_index(data.type()) == std::type_index(typeid(DataType)));
116 return importFunc(std::any_cast<DataType>(std::move(data)));
117 };
118
119 using AnyResult = std::variant<std::any, QXmppError>;
120 auto exportInternal = [this, exportFunc = std::move(exportFunc)]() -> QXmppTask<AnyResult> {
121 return chain<AnyResult>(exportFunc(), this, [](Result<DataType> &&result) {
122 return std::visit(overloaded {
123 [](DataType data) -> AnyResult { return std::any(std::move(data)); },
124 [](QXmppError err) -> AnyResult { return err; } },
125 std::move(result));
126 });
127 };
128
129 registerMigrationDataInternal(std::type_index(typeid(DataType)), std::move(importInternal), std::move(exportInternal));
130}
131
132template<typename DataType>
134{
135 unregisterMigrationDataInternal(std::type_index(typeid(DataType)));
136}
137
138#endif
Allows to export and import account data.
Definition QXmppAccountMigrationManager.h:75
std::variant< T, QXmppError > Result
Definition QXmppAccountMigrationManager.h:82
void unregisterExportData()
Definition QXmppAccountMigrationManager.h:133
void registerExportData(ImportFunc importFunc, ExportFunc exportFunc)
Definition QXmppAccountMigrationManager.h:104
The QXmppClientExtension class is the base class for QXmppClient extensions.
Definition QXmppClientExtension.h:32
Definition QXmppTask.h:62
Definition QXmppError.h:17