575 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			575 lines
		
	
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*
 | 
						|
This file is part of Telegram Desktop,
 | 
						|
the official desktop application for the Telegram messaging service.
 | 
						|
 | 
						|
For license and copyright information please follow this link:
 | 
						|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 | 
						|
*/
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include "base/flat_set.h"
 | 
						|
 | 
						|
class RPCError {
 | 
						|
public:
 | 
						|
	RPCError(const MTPrpcError &error);
 | 
						|
 | 
						|
	int32 code() const {
 | 
						|
		return _code;
 | 
						|
	}
 | 
						|
 | 
						|
	const QString &type() const {
 | 
						|
		return _type;
 | 
						|
	}
 | 
						|
 | 
						|
	const QString &description() const {
 | 
						|
		return _description;
 | 
						|
	}
 | 
						|
 | 
						|
	enum {
 | 
						|
		NoError,
 | 
						|
		TimeoutError
 | 
						|
	};
 | 
						|
 | 
						|
	static RPCError Local(const QString &type, const QString &description) {
 | 
						|
		return MTP_rpc_error(
 | 
						|
			MTP_int(0),
 | 
						|
			MTP_bytes(
 | 
						|
			("CLIENT_"
 | 
						|
				+ type
 | 
						|
				+ (description.length()
 | 
						|
					? (": " + description)
 | 
						|
					: QString())).toUtf8()));
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	int32 _code;
 | 
						|
	QString _type, _description;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
namespace MTP {
 | 
						|
 | 
						|
inline bool isFloodError(const RPCError &error) {
 | 
						|
	return error.type().startsWith(qstr("FLOOD_WAIT_"));
 | 
						|
}
 | 
						|
 | 
						|
inline bool isTemporaryError(const RPCError &error) {
 | 
						|
	return error.code() < 0 || error.code() >= 500 || isFloodError(error);
 | 
						|
}
 | 
						|
 | 
						|
inline bool isDefaultHandledError(const RPCError &error) {
 | 
						|
	return isTemporaryError(error);
 | 
						|
}
 | 
						|
 | 
						|
} // namespace MTP
 | 
						|
 | 
						|
class RPCAbstractDoneHandler { // abstract done
 | 
						|
public:
 | 
						|
	[[nodiscard]] virtual bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) = 0;
 | 
						|
	virtual ~RPCAbstractDoneHandler() {
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
using RPCDoneHandlerPtr = std::shared_ptr<RPCAbstractDoneHandler>;
 | 
						|
 | 
						|
class RPCAbstractFailHandler { // abstract fail
 | 
						|
public:
 | 
						|
	virtual bool operator()(mtpRequestId requestId, const RPCError &e) = 0;
 | 
						|
	virtual ~RPCAbstractFailHandler() {
 | 
						|
	}
 | 
						|
};
 | 
						|
using RPCFailHandlerPtr = std::shared_ptr<RPCAbstractFailHandler>;
 | 
						|
 | 
						|
struct RPCResponseHandler {
 | 
						|
	RPCResponseHandler() = default;
 | 
						|
	RPCResponseHandler(RPCDoneHandlerPtr &&done, RPCFailHandlerPtr &&fail)
 | 
						|
	: onDone(std::move(done))
 | 
						|
	, onFail(std::move(fail)) {
 | 
						|
	}
 | 
						|
 | 
						|
	RPCDoneHandlerPtr onDone;
 | 
						|
	RPCFailHandlerPtr onFail;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCDoneHandlerBare : public RPCAbstractDoneHandler { // done(from, end)
 | 
						|
	using CallbackType = bool (*)(const mtpPrime *, const mtpPrime *);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCDoneHandlerBare(CallbackType onDone) : _onDone(onDone) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		return (*_onDone)(from, end);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onDone;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCDoneHandlerBareReq : public RPCAbstractDoneHandler { // done(from, end, req_id)
 | 
						|
	using CallbackType = bool (*)(const mtpPrime *, const mtpPrime *, mtpRequestId);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCDoneHandlerBareReq(CallbackType onDone) : _onDone(onDone) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		return (*_onDone)(from, end, requestId);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onDone;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename TReturn, typename TResponse>
 | 
						|
class RPCDoneHandlerPlain : public RPCAbstractDoneHandler { // done(result)
 | 
						|
	using CallbackType = TReturn (*)(const TResponse &);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCDoneHandlerPlain(CallbackType onDone) : _onDone(onDone) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		auto response = TResponse();
 | 
						|
		if (!response.read(from, end)) {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		(*_onDone)(std::move(response));
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onDone;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename TReturn, typename TResponse>
 | 
						|
class RPCDoneHandlerReq : public RPCAbstractDoneHandler { // done(result, req_id)
 | 
						|
	using CallbackType = TReturn (*)(const TResponse &, mtpRequestId);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCDoneHandlerReq(CallbackType onDone) : _onDone(onDone) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		auto response = TResponse();
 | 
						|
		if (!response.read(from, end)) {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		(*_onDone)(std::move(response), requestId);
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onDone;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename TReturn>
 | 
						|
class RPCDoneHandlerNo : public RPCAbstractDoneHandler { // done()
 | 
						|
	using CallbackType = TReturn (*)();
 | 
						|
 | 
						|
public:
 | 
						|
	RPCDoneHandlerNo(CallbackType onDone) : _onDone(onDone) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		(*_onDone)();
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onDone;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename TReturn>
 | 
						|
class RPCDoneHandlerNoReq : public RPCAbstractDoneHandler { // done(req_id)
 | 
						|
	using CallbackType = TReturn (*)(mtpRequestId);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCDoneHandlerNoReq(CallbackType onDone) : _onDone(onDone) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		(*_onDone)(requestId);
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onDone;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerPlain : public RPCAbstractFailHandler { // fail(error)
 | 
						|
	using CallbackType = bool (*)(const RPCError &);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCFailHandlerPlain(CallbackType onFail) : _onFail(onFail) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &e) override {
 | 
						|
		return (*_onFail)(e);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onFail;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerReq : public RPCAbstractFailHandler { // fail(error, req_id)
 | 
						|
	using CallbackType = bool (*)(const RPCError &, mtpRequestId);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCFailHandlerReq(CallbackType onFail) : _onFail(onFail) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &e) override {
 | 
						|
		return (*_onFail)(e, requestId);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onFail;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerNo : public RPCAbstractFailHandler { // fail()
 | 
						|
	using CallbackType = bool (*)();
 | 
						|
 | 
						|
public:
 | 
						|
	RPCFailHandlerNo(CallbackType onFail) : _onFail(onFail) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &e) override {
 | 
						|
		return (*_onFail)();
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onFail;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerNoReq : public RPCAbstractFailHandler { // fail(req_id)
 | 
						|
	using CallbackType = bool (*)(mtpRequestId);
 | 
						|
 | 
						|
public:
 | 
						|
	RPCFailHandlerNoReq(CallbackType onFail) : _onFail(onFail) {
 | 
						|
	}
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &e) override {
 | 
						|
		return (*_onFail)(requestId);
 | 
						|
	}
 | 
						|
 | 
						|
private:
 | 
						|
	CallbackType _onFail;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
struct RPCCallbackClear {
 | 
						|
	RPCCallbackClear(mtpRequestId id, int32 code = RPCError::NoError)
 | 
						|
	: requestId(id)
 | 
						|
	, errorCode(code) {
 | 
						|
	}
 | 
						|
 | 
						|
	mtpRequestId requestId = 0;
 | 
						|
	int32 errorCode = 0;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
inline RPCDoneHandlerPtr rpcDone(bool (*onDone)(const mtpPrime *, const mtpPrime *)) { // done(from, end)
 | 
						|
	return RPCDoneHandlerPtr(new RPCDoneHandlerBare(onDone));
 | 
						|
}
 | 
						|
 | 
						|
inline RPCDoneHandlerPtr rpcDone(bool (*onDone)(const mtpPrime *, const mtpPrime *, mtpRequestId)) { // done(from, end, req_id)
 | 
						|
	return RPCDoneHandlerPtr(new RPCDoneHandlerBareReq(onDone));
 | 
						|
}
 | 
						|
 | 
						|
template <typename TReturn, typename TResponse>
 | 
						|
inline RPCDoneHandlerPtr rpcDone(TReturn (*onDone)(const TResponse &)) { // done(result)
 | 
						|
	return RPCDoneHandlerPtr(new RPCDoneHandlerPlain<TReturn, TResponse>(onDone));
 | 
						|
}
 | 
						|
 | 
						|
template <typename TReturn, typename TResponse>
 | 
						|
inline RPCDoneHandlerPtr rpcDone(TReturn (*onDone)(const TResponse &, mtpRequestId)) { // done(result, req_id)
 | 
						|
	return RPCDoneHandlerPtr(new RPCDoneHandlerReq<TReturn, TResponse>(onDone));
 | 
						|
}
 | 
						|
 | 
						|
template <typename TReturn>
 | 
						|
inline RPCDoneHandlerPtr rpcDone(TReturn (*onDone)()) { // done()
 | 
						|
	return RPCDoneHandlerPtr(new RPCDoneHandlerNo<TReturn>(onDone));
 | 
						|
}
 | 
						|
 | 
						|
template <typename TReturn>
 | 
						|
inline RPCDoneHandlerPtr rpcDone(TReturn (*onDone)(mtpRequestId)) { // done(req_id)
 | 
						|
	return RPCDoneHandlerPtr(new RPCDoneHandlerNoReq<TReturn>(onDone));
 | 
						|
}
 | 
						|
 | 
						|
inline RPCFailHandlerPtr rpcFail(bool (*onFail)(const RPCError &)) { // fail(error)
 | 
						|
	return RPCFailHandlerPtr(new RPCFailHandlerPlain(onFail));
 | 
						|
}
 | 
						|
 | 
						|
inline RPCFailHandlerPtr rpcFail(bool (*onFail)(const RPCError &, mtpRequestId)) { // fail(error, req_id)
 | 
						|
	return RPCFailHandlerPtr(new RPCFailHandlerReq(onFail));
 | 
						|
}
 | 
						|
 | 
						|
inline RPCFailHandlerPtr rpcFail(bool (*onFail)()) { // fail()
 | 
						|
	return RPCFailHandlerPtr(new RPCFailHandlerNo(onFail));
 | 
						|
}
 | 
						|
 | 
						|
inline RPCFailHandlerPtr rpcFail(bool (*onFail)(mtpRequestId)) { // fail(req_id)
 | 
						|
	return RPCFailHandlerPtr(new RPCFailHandlerNoReq(onFail));
 | 
						|
}
 | 
						|
 | 
						|
using MTPStateChangedHandler = void (*)(int32 dcId, int32 state);
 | 
						|
using MTPSessionResetHandler = void (*)(int32 dcId);
 | 
						|
 | 
						|
template <typename Base, typename FunctionType>
 | 
						|
class RPCHandlerImplementation : public Base {
 | 
						|
protected:
 | 
						|
	using Lambda = FnMut<FunctionType>;
 | 
						|
	using Parent = RPCHandlerImplementation<Base, FunctionType>;
 | 
						|
 | 
						|
public:
 | 
						|
	RPCHandlerImplementation(Lambda handler) : _handler(std::move(handler)) {
 | 
						|
	}
 | 
						|
 | 
						|
protected:
 | 
						|
	Lambda _handler;
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename FunctionType>
 | 
						|
using RPCDoneHandlerImplementation = RPCHandlerImplementation<RPCAbstractDoneHandler, FunctionType>;
 | 
						|
 | 
						|
class RPCDoneHandlerImplementationBare : public RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*)> { // done(from, end)
 | 
						|
public:
 | 
						|
	using RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*)>::Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		return this->_handler ? this->_handler(from, end) : true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCDoneHandlerImplementationBareReq : public RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*, mtpRequestId)> { // done(from, end, req_id)
 | 
						|
public:
 | 
						|
	using RPCDoneHandlerImplementation<bool(const mtpPrime*, const mtpPrime*, mtpRequestId)>::Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		return this->_handler ? this->_handler(from, end, requestId) : true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename R, typename TResponse>
 | 
						|
class RPCDoneHandlerImplementationPlain : public RPCDoneHandlerImplementation<R(const TResponse&)> { // done(result)
 | 
						|
public:
 | 
						|
	using RPCDoneHandlerImplementation<R(const TResponse&)>::Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		auto response = TResponse();
 | 
						|
		if (!response.read(from, end)) {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		if (this->_handler) {
 | 
						|
			this->_handler(std::move(response));
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename R, typename TResponse>
 | 
						|
class RPCDoneHandlerImplementationReq : public RPCDoneHandlerImplementation<R(const TResponse&, mtpRequestId)> { // done(result, req_id)
 | 
						|
public:
 | 
						|
	using RPCDoneHandlerImplementation<R(const TResponse&, mtpRequestId)>::Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		auto response = TResponse();
 | 
						|
		if (!response.read(from, end)) {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		if (this->_handler) {
 | 
						|
			this->_handler(std::move(response), requestId);
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename R>
 | 
						|
class RPCDoneHandlerImplementationNo : public RPCDoneHandlerImplementation<R()> { // done()
 | 
						|
public:
 | 
						|
	using RPCDoneHandlerImplementation<R()>::Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		if (this->_handler) {
 | 
						|
			this->_handler();
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename R>
 | 
						|
class RPCDoneHandlerImplementationNoReq : public RPCDoneHandlerImplementation<R(mtpRequestId)> { // done(req_id)
 | 
						|
public:
 | 
						|
	using RPCDoneHandlerImplementation<R(mtpRequestId)>::Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) override {
 | 
						|
		if (this->_handler) {
 | 
						|
			this->_handler(requestId);
 | 
						|
		}
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcDone_canCallBare_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda, const mtpPrime*, const mtpPrime*>;
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcDone_canCallBareReq_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda, const mtpPrime*, const mtpPrime*, mtpRequestId>;
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcDone_canCallNo_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda>;
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcDone_canCallNoReq_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda, mtpRequestId>;
 | 
						|
 | 
						|
template <typename Function>
 | 
						|
struct rpcDone_canCallPlain : std::false_type {
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda, typename Return, typename T>
 | 
						|
struct rpcDone_canCallPlain<Return(Lambda::*)(const T&)> : std::true_type {
 | 
						|
	using Arg = T;
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda, typename Return, typename T>
 | 
						|
struct rpcDone_canCallPlain<Return(Lambda::*)(const T&)const>
 | 
						|
	: rpcDone_canCallPlain<Return(Lambda::*)(const T&)> {
 | 
						|
};
 | 
						|
 | 
						|
template <typename Function>
 | 
						|
constexpr bool rpcDone_canCallPlain_v = rpcDone_canCallPlain<Function>::value;
 | 
						|
 | 
						|
template <typename Function>
 | 
						|
struct rpcDone_canCallReq : std::false_type {
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda, typename Return, typename T>
 | 
						|
struct rpcDone_canCallReq<Return(Lambda::*)(const T&, mtpRequestId)> : std::true_type {
 | 
						|
	using Arg = T;
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda, typename Return, typename T>
 | 
						|
struct rpcDone_canCallReq<Return(Lambda::*)(const T&, mtpRequestId)const>
 | 
						|
	: rpcDone_canCallReq<Return(Lambda::*)(const T&, mtpRequestId)> {
 | 
						|
};
 | 
						|
 | 
						|
template <typename Function>
 | 
						|
constexpr bool rpcDone_canCallReq_v = rpcDone_canCallReq<Function>::value;
 | 
						|
 | 
						|
template <typename Function>
 | 
						|
struct rpcDone_returnType;
 | 
						|
 | 
						|
template <typename Lambda, typename Return, typename ...Args>
 | 
						|
struct rpcDone_returnType<Return(Lambda::*)(Args...)> {
 | 
						|
	using type = Return;
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda, typename Return, typename ...Args>
 | 
						|
struct rpcDone_returnType<Return(Lambda::*)(Args...)const> {
 | 
						|
	using type = Return;
 | 
						|
};
 | 
						|
 | 
						|
template <typename Function>
 | 
						|
using rpcDone_returnType_t = typename rpcDone_returnType<Function>::type;
 | 
						|
 | 
						|
template <
 | 
						|
	typename Lambda,
 | 
						|
	typename Function = crl::deduced_call_type<Lambda>>
 | 
						|
RPCDoneHandlerPtr rpcDone(Lambda lambda) {
 | 
						|
	using R = rpcDone_returnType_t<Function>;
 | 
						|
	if constexpr (rpcDone_canCallBare_v<Lambda>) {
 | 
						|
		return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBare(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcDone_canCallBareReq_v<Lambda>) {
 | 
						|
		return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBareReq(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcDone_canCallNo_v<Lambda>) {
 | 
						|
		return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNo<R>(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcDone_canCallNoReq_v<Lambda>) {
 | 
						|
		return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNoReq<R>(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcDone_canCallPlain_v<Function>) {
 | 
						|
		using T = typename rpcDone_canCallPlain<Function>::Arg;
 | 
						|
		return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationPlain<R, T>(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcDone_canCallReq_v<Function>) {
 | 
						|
		using T = typename rpcDone_canCallReq<Function>::Arg;
 | 
						|
		return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationReq<R, T>(std::move(lambda)));
 | 
						|
	} else {
 | 
						|
		static_assert(false_t(lambda), "Unknown method.");
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
template <typename FunctionType>
 | 
						|
using RPCFailHandlerImplementation = RPCHandlerImplementation<RPCAbstractFailHandler, FunctionType>;
 | 
						|
 | 
						|
class RPCFailHandlerImplementationPlain : public RPCFailHandlerImplementation<bool(const RPCError&)> { // fail(error)
 | 
						|
public:
 | 
						|
	using Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &error) override {
 | 
						|
		return _handler ? _handler(error) : true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerImplementationReq : public RPCFailHandlerImplementation<bool(const RPCError&, mtpRequestId)> { // fail(error, req_id)
 | 
						|
public:
 | 
						|
	using Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &error) override {
 | 
						|
		return this->_handler ? this->_handler(error, requestId) : true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerImplementationNo : public RPCFailHandlerImplementation<bool()> { // fail()
 | 
						|
public:
 | 
						|
	using Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &error) override {
 | 
						|
		return this->_handler ? this->_handler() : true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
class RPCFailHandlerImplementationNoReq : public RPCFailHandlerImplementation<bool(mtpRequestId)> { // fail(req_id)
 | 
						|
public:
 | 
						|
	using Parent::Parent;
 | 
						|
	bool operator()(mtpRequestId requestId, const RPCError &error) override {
 | 
						|
		return this->_handler ? this->_handler(requestId) : true;
 | 
						|
	}
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcFail_canCallNo_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda>;
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcFail_canCallNoReq_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda, mtpRequestId>;
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcFail_canCallPlain_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda, const RPCError&>;
 | 
						|
 | 
						|
template <typename Lambda>
 | 
						|
constexpr bool rpcFail_canCallReq_v = rpl::details::is_callable_plain_v<
 | 
						|
	Lambda, const RPCError&, mtpRequestId>;
 | 
						|
 | 
						|
template <
 | 
						|
	typename Lambda,
 | 
						|
	typename Function = crl::deduced_call_type<Lambda>>
 | 
						|
RPCFailHandlerPtr rpcFail(Lambda lambda) {
 | 
						|
	if constexpr (rpcFail_canCallNo_v<Lambda>) {
 | 
						|
		return RPCFailHandlerPtr(new RPCFailHandlerImplementationNo(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcFail_canCallNoReq_v<Lambda>) {
 | 
						|
		return RPCFailHandlerPtr(new RPCFailHandlerImplementationNoReq(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcFail_canCallPlain_v<Lambda>) {
 | 
						|
		return RPCFailHandlerPtr(new RPCFailHandlerImplementationPlain(std::move(lambda)));
 | 
						|
	} else if constexpr (rpcFail_canCallReq_v<Lambda>) {
 | 
						|
		return RPCFailHandlerPtr(new RPCFailHandlerImplementationReq(std::move(lambda)));
 | 
						|
	} else {
 | 
						|
		static_assert(false_t(lambda), "Unknown method.");
 | 
						|
	}
 | 
						|
}
 |