QXmpp  Version: 1.10.4
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  std::optional<T> extension() const
36  {
37  const auto it = extensions().find(std::type_index(typeid(T)));
38  return it != extensions().cend() ? std::any_cast<T>(it->second) : std::optional<T>();
39  }
40 
41  template<typename T>
42  void setExtension(T &&value)
43  {
44  Q_ASSERT(isExtensionRegistered<T>());
45  setExtension(std::any(std::move(value)));
46  }
47 
48  template<typename T>
49  using ExtensionParser = Result<T> (*)(const QDomElement &);
50  template<typename T>
51  using ExtensionSerializer = void (*)(const T &, QXmlStreamWriter &);
52 
53  template<typename T, ExtensionParser<T> parse, ExtensionSerializer<T> serialize>
54  static void registerExtension(QStringView tagName, QStringView xmlns)
55  {
56  using namespace QXmpp::Private;
57  using AnyParser = ExtensionParser<std::any>;
58  using AnySerializer = ExtensionSerializer<std::any>;
59 
60  AnyParser parseAny = [](const QDomElement &el) {
61  return std::visit(overloaded {
62  [](T data) -> Result<std::any> { return std::move(data); },
63  [](QXmppError e) -> Result<std::any> { return std::move(e); },
64  },
65  parse(el));
66  };
67 
68  AnySerializer serializeAny = [](const std::any &data, QXmlStreamWriter &w) {
69  return std::invoke(serialize, std::any_cast<const T &>(data), w);
70  };
71 
72  registerExtensionInternal(std::type_index(typeid(T)), parseAny, serializeAny, tagName, xmlns);
73  }
74 
75  template<typename T>
76  static bool isExtensionRegistered() { return isExtensionRegistered(std::type_index(typeid(T))); }
77 
78 private:
79  friend class QXmppAccountMigrationManager;
80  friend class tst_QXmppAccountMigrationManager;
81 
82  const std::unordered_map<std::type_index, std::any> &extensions() const;
83  void setExtension(std::any value);
84 
85  static void registerExtensionInternal(std::type_index, ExtensionParser<std::any>, ExtensionSerializer<std::any>, QStringView tagName, QStringView xmlns);
86  static bool isExtensionRegistered(std::type_index);
87 
88  QSharedDataPointer<QXmppExportDataPrivate> d;
89 };
90 
91 struct QXmppAccountMigrationManagerPrivate;
92 
94 {
95  Q_OBJECT
96 
97  friend struct QXmppAccountMigrationManagerPrivate;
98 
99 public:
100  template<typename T = QXmpp::Success>
101  using Result = std::variant<T, QXmppError>;
102 
104  ~QXmppAccountMigrationManager() override;
105 
106  QXmppTask<Result<>> importData(const QXmppExportData &account);
107  QXmppTask<Result<QXmppExportData>> exportData();
108 
109  template<typename DataType, typename ImportFunc, typename ExportFunc>
110  void registerExportData(ImportFunc importFunc, ExportFunc exportFunc);
111 
112  template<typename DataType>
113  void unregisterExportData();
114 
115  Q_SIGNAL void errorOccurred(const QXmppError &error);
116 
117 private:
118  void registerMigrationDataInternal(std::type_index dataType, std::function<QXmppTask<Result<>>(std::any)>, std::function<QXmppTask<Result<std::any>>()>);
119  void unregisterMigrationDataInternal(std::type_index dataType);
120 
121  std::unique_ptr<QXmppAccountMigrationManagerPrivate> d;
122 };
123 
124 template<typename DataType, typename ImportFunc, typename ExportFunc>
125 void QXmppAccountMigrationManager::registerExportData(ImportFunc importFunc, ExportFunc exportFunc)
126 {
127  using namespace QXmpp::Private;
128 
129  static_assert(std::is_constructible_v<std::function<QXmppTask<Result<>>(const DataType &)>, ImportFunc>);
130  static_assert(std::is_constructible_v<std::function<QXmppTask<Result<DataType>>()>, ExportFunc>);
131  static_assert(std::is_invocable_v<ImportFunc, const DataType &>);
132  static_assert(std::is_invocable_v<ExportFunc>);
133  static_assert(std::is_same_v<first_argument_t<ImportFunc>, const DataType &>);
134 
135  auto importInternal = [importFunc = std::move(importFunc)](std::any data) -> QXmppTask<Result<>> {
136  Q_ASSERT(std::type_index(data.type()) == std::type_index(typeid(DataType)));
137  return importFunc(std::any_cast<DataType>(std::move(data)));
138  };
139 
140  using AnyResult = std::variant<std::any, QXmppError>;
141  auto exportInternal = [this, exportFunc = std::move(exportFunc)]() -> QXmppTask<AnyResult> {
142  return chain<AnyResult>(exportFunc(), this, [](Result<DataType> &&result) {
143  return std::visit(overloaded {
144  [](DataType data) -> AnyResult { return std::any(std::move(data)); },
145  [](QXmppError err) -> AnyResult { return err; } },
146  std::move(result));
147  });
148  };
149 
150  registerMigrationDataInternal(std::type_index(typeid(DataType)), std::move(importInternal), std::move(exportInternal));
151 }
152 
153 template<typename DataType>
155 {
156  unregisterMigrationDataInternal(std::type_index(typeid(DataType)));
157 }
158 
159 #endif
Definition: QXmppError.h:17
void unregisterExportData()
Definition: QXmppAccountMigrationManager.h:154
Definition: QXmppTask.h:61
Allows to export and import account data.
Definition: QXmppAccountMigrationManager.h:93
std::variant< T, QXmppError > Result
Definition: QXmppAccountMigrationManager.h:101
void registerExportData(ImportFunc importFunc, ExportFunc exportFunc)
Definition: QXmppAccountMigrationManager.h:125
Definition: Algorithms.h:12
The QXmppClientExtension class is the base class for QXmppClient extensions.
Definition: QXmppClientExtension.h:31