#pragma once #include #include #include namespace rublon { template < typename... Types > constexpr std::array< std::string_view, sizeof...(Types) > make_array(Types... names) { return {std::forward< Types >(names)...}; } class ConfigurationError { public: enum class ErrorClass { RequiredValueNotFound, BadFailMode, BadInput, Empty }; constexpr static auto errorClassPrettyName = make_array("RequiredValueNotFound", "BadFailMode", "BadInput", "Empty"); constexpr static auto prettyName = "Configurtion Error"; constexpr ConfigurationError(ErrorClass e = ErrorClass::RequiredValueNotFound) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } ErrorClass errorClass; }; class ConnectionError { public: enum ErrorClass { Timeout, HttpError, ClientError }; constexpr static auto errorClassPrettyName = make_array("Timeout", "Error", "Client Error"); constexpr static 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)].data(); } ErrorClass errorClass; long httpCode; }; class CoreHandlerError { public: enum ErrorClass { BadSigature, RublonCoreException, BrokenData, APIException, TransactionException }; constexpr static auto errorClassPrettyName = make_array("BadSigature", "RublonCoreException", "BrokenData", "APIException", "TransactionException"); constexpr static auto prettyName = "Core Handler Error"; // APIException -> code: 10 // TransactionException -> code: 11 CoreHandlerError(ErrorClass e = BadSigature, std::string r = "") : errorClass{e}, reson{std::move(r)} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } ErrorClass errorClass; std::string reson; // TODO dynamic mem }; class MethodError { public: enum ErrorClass { BadMethod, BadUserInput, NoMethodAvailable }; constexpr static auto errorClassPrettyName = make_array("BadMethod", "BadUserInput", "NoMethodAvailable"); constexpr static auto prettyName = "Method Error"; constexpr MethodError(ErrorClass e = BadMethod) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } ErrorClass errorClass; }; class WerificationError { public: enum ErrorClass { BadInput, // User input has incorrect characters or length PasscodeException // Exception from core }; constexpr static auto errorClassPrettyName = make_array("BadInput", "PasscodeException"); constexpr static inline auto prettyName = "Werification Error"; constexpr WerificationError(ErrorClass e = PasscodeException) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } static std::optional< WerificationError > fromString(std::string_view name) { for(std::size_t i{}; i < errorClassPrettyName.size(); i++) { if(errorClassPrettyName.at(i) == name) { return std::make_optional(WerificationError{static_cast< ErrorClass >(i)}); } } return std::nullopt; } ErrorClass errorClass; }; class RublonAuthenticationInterrupt { public: // UserPending -> user has no methods configured enum ErrorClass { UserBaypass, UserDenied, UserPending, UserWaiting, UserNotFound }; constexpr static auto errorClassPrettyName = make_array("UserBypassedException", "UserDenied", "UserPending", "UserWaiting", "UserNotFoundException"); constexpr static auto prettyName = "Rublon Authentication Interrupt"; RublonAuthenticationInterrupt(ErrorClass e = UserBaypass) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } static std::optional< RublonAuthenticationInterrupt > fromString(std::string_view name) { for(std::size_t i{}; i < errorClassPrettyName.size(); i++) { if(errorClassPrettyName.at(i) == name) { return std::make_optional(RublonAuthenticationInterrupt{static_cast< ErrorClass >(i)}); } } return std::nullopt; } ErrorClass errorClass; }; class RublonCheckApplicationException { public: enum ErrorClass { ApplicationNotFoundException, InvalidSignatureException, UnsupportedVersionException }; constexpr static auto errorClassPrettyName = make_array("ApplicationNotFoundException", "InvalidSignatureException", "UnsupportedVersionException"); constexpr static auto prettyName = "Rublon Check Application Interrupt"; RublonCheckApplicationException(ErrorClass e = ApplicationNotFoundException) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } static std::optional< RublonCheckApplicationException > fromString(std::string_view name) { for(std::size_t i{}; i < errorClassPrettyName.size(); i++) { if(errorClassPrettyName.at(i) == name) { return std::make_optional(RublonCheckApplicationException{static_cast< ErrorClass >(i)}); } } return std::nullopt; } ErrorClass errorClass; }; class Error { using Error_t = std::variant< ConfigurationError, CoreHandlerError, ConnectionError, WerificationError, MethodError, RublonAuthenticationInterrupt, RublonCheckApplicationException >; Error_t _error; public: enum Category { k_ConfigurationError, k_CoreHandlerError, k_ConnectionError, k_WerificationError, k_MethodError, k_RublonAuthenticationInterrupt, k_RublonCheckApplication }; Error() = default; Error(ConfigurationError error) : _error{error} {} 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(RublonCheckApplicationException 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 is(typename E::ErrorClass errorClass) const { return is< E >() && hasSameErrorClassAs(errorClass); } 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