#pragma once #include #include #include #include namespace rublon { #define names constexpr static inline const char * errorClassPrettyName[] class ConnectionError { public: enum ErrorClass { Timeout, HttpError }; names = {"Timeout", "Error"}; constexpr static inline auto prettyName = "Connection Error"; constexpr ConnectionError() : errorClass{Timeout}, httpCode(200) {} constexpr ConnectionError(ErrorClass e, long httpCode) : errorClass{e}, httpCode(httpCode) {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)]; } ErrorClass errorClass; long httpCode; }; class CoreHandlerError { public: enum ErrorClass { BadSigature, RublonCoreException, BrokenData }; names = {"BadSigature", "RublonCoreException", "BrokenData"}; constexpr static inline auto prettyName = "Core Handler Error"; CoreHandlerError(ErrorClass e = BadSigature) : errorClass{e} {} CoreHandlerError(ErrorClass e, std::string r) : errorClass{e}, reson{std::move(r)} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)]; } ErrorClass errorClass; std::string reson; }; class MethodError { public: enum ErrorClass { BadMethod, BadUserInput, NoMethodAvailable }; names = {"BadMethod", "BadUserInput", "NoMethodAvailable"}; constexpr static inline auto prettyName = "Method Error"; constexpr MethodError(ErrorClass e = BadMethod) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)]; } ErrorClass errorClass; }; class WerificationError { public: enum ErrorClass { WrongCode }; names = {"WrongCode"}; constexpr static inline auto prettyName = "Werification Error"; constexpr WerificationError(ErrorClass e = WrongCode) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)]; } ErrorClass errorClass; }; class RublonAuthenticationInterrupt { public: enum ErrorClass { UserBaypass, UserDenied, UserPending }; names = {"UserBaypass", "UserDenied", "UserPending"}; constexpr static inline auto prettyName = "Rublon Authentication Interrupt"; RublonAuthenticationInterrupt(ErrorClass e = UserBaypass) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)]; } ErrorClass errorClass; }; class Error { using Error_t = std::variant< CoreHandlerError, ConnectionError, WerificationError, MethodError, RublonAuthenticationInterrupt >; Error_t _error; public: enum Category { k_CoreHandlerError, k_ConnectionError, k_WerificationError, k_MethodError, k_RublonAuthenticationInterrupt }; Error() = default; Error(CoreHandlerError error) : _error{error} {} Error(ConnectionError error) : _error{error} {} Error(MethodError error) : _error{error} {} Error(WerificationError error) : _error{error} {} Error(RublonAuthenticationInterrupt error) : _error{error} {} Error(const Error &) = default; Error(Error &&) = default; Error & operator=(const Error &) = default; Error & operator=(Error &&) = default; public: constexpr bool coreError() const { return _error.index() == 1; } constexpr bool sockerError() const { return _error.index() == 2; } constexpr Category category() const noexcept { return static_cast< Category >(_error.index()); } constexpr const char * categoryName() const noexcept { return std::visit([](const auto & e) { return e.what(); }, _error); } constexpr int errorClass() const noexcept { return std::visit([](const auto & e) { return static_cast< int >(e.errorClass); }, _error); } constexpr const char * errorClassName() const noexcept { return std::visit([](const auto & e) { return e.prettyName; }, _error); } template < typename E > constexpr bool is() const { return category() == Error{E{}}.category(); } template < typename E > constexpr bool isSameCategoryAs(const E & e) const { return category() == Error{e}.category(); } constexpr bool hasClass(int _class) const { return errorClass() == _class; } template < typename E > constexpr bool hasSameErrorClassAs(E e) const { assert(isSameCategoryAs(e)); return errorClass() == Error{e}.errorClass(); } template < typename E > constexpr const E & get() const { return std::get< E >(_error); } }; constexpr bool operator==(const Error & e, const ConnectionError & socket) { return e.sockerError() && e.errorClass() == socket.errorClass; } template < typename T > constexpr bool operator==(const Error & lhs, const T & rhs) { return lhs.isSameCategoryAs(rhs) && lhs.hasSameErrorClassAs(rhs); } } // namespace rublon