Loading...
Searching...
No Matches
QXmppAccountMigrationManager.h
// SPDX-FileCopyrightText: 2023 Linus Jahn <lnj@kaidan.im>
// SPDX-FileCopyrightText: 2024 Filipe Azevedo <pasnox@gmail.com>
//
// SPDX-License-Identifier: LGPL-2.1-or-later
#ifndef QXMPPACCOUNTMIGRATIONMANAGER_H
#define QXMPPACCOUNTMIGRATIONMANAGER_H
#include "QXmppAsync_p.h"
#include "QXmppClientExtension.h"
#include "QXmppError.h"
#include "QXmppTask.h"
#include <any>
#include <typeindex>
#include <unordered_map>
struct QXmppExportDataPrivate;
class QXMPP_EXPORT QXmppExportData
{
public:
template<typename T = QXmpp::Success>
using Result = std::variant<T, QXmppError>;
QXmppExportData();
QXMPP_PRIVATE_DECLARE_RULE_OF_SIX(QXmppExportData)
static std::variant<QXmppExportData, QXmppError> fromDom(const QDomElement &);
void toXml(QXmlStreamWriter *) const;
const QString &accountJid() const;
void setAccountJid(const QString &jid);
template<typename T>
std::optional<T> extension() const
{
const auto it = extensions().find(std::type_index(typeid(T)));
return it != extensions().cend() ? std::any_cast<T>(it->second) : std::optional<T>();
}
template<typename T>
void setExtension(T &&value)
{
Q_ASSERT(isExtensionRegistered<T>());
setExtension(std::any(std::move(value)));
}
template<typename T>
using ExtensionParser = Result<T> (*)(const QDomElement &);
template<typename T>
using ExtensionSerializer = void (*)(const T &, QXmlStreamWriter &);
template<typename T, ExtensionParser<T> parse, ExtensionSerializer<T> serialize>
static void registerExtension(QStringView tagName, QStringView xmlns)
{
using namespace QXmpp::Private;
using AnyParser = ExtensionParser<std::any>;
using AnySerializer = ExtensionSerializer<std::any>;
AnyParser parseAny = [](const QDomElement &el) {
return std::visit(overloaded {
[](T data) -> Result<std::any> { return std::move(data); },
[](QXmppError e) -> Result<std::any> { return std::move(e); },
},
parse(el));
};
AnySerializer serializeAny = [](const std::any &data, QXmlStreamWriter &w) {
return std::invoke(serialize, std::any_cast<const T &>(data), w);
};
registerExtensionInternal(std::type_index(typeid(T)), parseAny, serializeAny, tagName, xmlns);
}
template<typename T>
static bool isExtensionRegistered() { return isExtensionRegistered(std::type_index(typeid(T))); }
private:
friend class QXmppAccountMigrationManager;
friend class tst_QXmppAccountMigrationManager;
const std::unordered_map<std::type_index, std::any> &extensions() const;
void setExtension(std::any value);
static void registerExtensionInternal(std::type_index, ExtensionParser<std::any>, ExtensionSerializer<std::any>, QStringView tagName, QStringView xmlns);
static bool isExtensionRegistered(std::type_index);
QSharedDataPointer<QXmppExportDataPrivate> d;
};
struct QXmppAccountMigrationManagerPrivate;
class QXMPP_EXPORT QXmppAccountMigrationManager : public QXmppClientExtension
{
Q_OBJECT
friend struct QXmppAccountMigrationManagerPrivate;
public:
template<typename T = QXmpp::Success>
using Result = std::variant<T, QXmppError>;
QXmppAccountMigrationManager();
~QXmppAccountMigrationManager() override;
QXmppTask<Result<>> importData(const QXmppExportData &account);
QXmppTask<Result<QXmppExportData>> exportData();
template<typename DataType, typename ImportFunc, typename ExportFunc>
void registerExportData(ImportFunc importFunc, ExportFunc exportFunc);
template<typename DataType>
void unregisterExportData();
Q_SIGNAL void errorOccurred(const QXmppError &error);
private:
void registerMigrationDataInternal(std::type_index dataType, std::function<QXmppTask<Result<>>(std::any)>, std::function<QXmppTask<Result<std::any>>()>);
void unregisterMigrationDataInternal(std::type_index dataType);
std::unique_ptr<QXmppAccountMigrationManagerPrivate> d;
};
template<typename DataType, typename ImportFunc, typename ExportFunc>
void QXmppAccountMigrationManager::registerExportData(ImportFunc importFunc, ExportFunc exportFunc)
{
using namespace QXmpp::Private;
static_assert(std::is_constructible_v<std::function<QXmppTask<Result<>>(const DataType &)>, ImportFunc>);
static_assert(std::is_constructible_v<std::function<QXmppTask<Result<DataType>>()>, ExportFunc>);
static_assert(std::is_invocable_v<ImportFunc, const DataType &>);
static_assert(std::is_invocable_v<ExportFunc>);
static_assert(std::is_same_v<first_argument_t<ImportFunc>, const DataType &>);
auto importInternal = [importFunc = std::move(importFunc)](std::any data) -> QXmppTask<Result<>> {
Q_ASSERT(std::type_index(data.type()) == std::type_index(typeid(DataType)));
return importFunc(std::any_cast<DataType>(std::move(data)));
};
using AnyResult = std::variant<std::any, QXmppError>;
auto exportInternal = [this, exportFunc = std::move(exportFunc)]() -> QXmppTask<AnyResult> {
return chain<AnyResult>(exportFunc(), this, [](Result<DataType> &&result) {
return std::visit(overloaded {
[](DataType data) -> AnyResult { return std::any(std::move(data)); },
[](QXmppError err) -> AnyResult { return err; } },
std::move(result));
});
};
registerMigrationDataInternal(std::type_index(typeid(DataType)), std::move(importInternal), std::move(exportInternal));
}
template<typename DataType>
void QXmppAccountMigrationManager::unregisterExportData()
{
unregisterMigrationDataInternal(std::type_index(typeid(DataType)));
}
#endif
QXmppAccountMigrationManager::importData
QXmppTask< Result<> > importData(const QXmppExportData &account)
Definition QXmppAccountMigrationManager.cpp:276
QXmppAccountMigrationManager::Result
std::variant< T, QXmppError > Result
Definition QXmppAccountMigrationManager.h:102
QXmppAccountMigrationManager::unregisterExportData
void unregisterExportData()
Definition QXmppAccountMigrationManager.h:155
QXmppAccountMigrationManager::registerExportData
void registerExportData(ImportFunc importFunc, ExportFunc exportFunc)
Definition QXmppAccountMigrationManager.h:126
QXmppAccountMigrationManager::errorOccurred
Q_SIGNAL void errorOccurred(const QXmppError &error)
QXmppAccountMigrationManager::exportData
QXmppTask< Result< QXmppExportData > > exportData()
Definition QXmppAccountMigrationManager.cpp:319
QXmppAccountMigrationManager::QXmppAccountMigrationManager
QXmppAccountMigrationManager()
Definition QXmppAccountMigrationManager.cpp:266
QXmppClientExtension::QXmppClientExtension
QXmppClientExtension()
Definition QXmppClientExtension.cpp:12
QXmppTask
Definition QXmppTask.h:46
QXmpp::Result
std::variant< T, QXmppError > Result
Definition QXmppGlobal.h:209
QXmppError
Definition QXmppError.h:17