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