#pragma once #include #include #include #include namespace rublon { class ConfigurationError { public: enum class ErrorClass { // RequiredValueNotFound, RequiredValueEmpty, BadFailMode, BadInput, BadConfiguration, Empty }; constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "RequiredValueNotFound", "RequiredValueEmpty", "BadFailMode", "BadInput", "BadConfiguration", "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< std::string_view >( // "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, // code: 10 TransactionException, TransactionIdExpiredException, // code: 11 TransactionAccessTokenExpiredException, // code: 11 TooManyRequestsException }; constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "BadSigature", "RublonCoreException", "BrokenData", "APIException", "TransactionException", "TransactionIdExpiredException", "TransactionAccessTokenExpiredException", "TooManyRequestsException"); constexpr static auto prettyName = "Core Handler Error"; // APIException -> code: 10 // TransactionException -> code: 11 CoreHandlerError(ErrorClass e = BadSigature) : errorClass{e} {} constexpr const char * what() const { return errorClassPrettyName[static_cast< int >(errorClass)].data(); } static std::optional< CoreHandlerError > fromString(std::string_view name) { for(std::size_t i{}; i < errorClassPrettyName.size(); i++) { if(errorClassPrettyName.at(i) == name) { return std::make_optional(CoreHandlerError{static_cast< ErrorClass >(i)}); } } return std::nullopt; } ErrorClass errorClass; }; class MethodError { public: enum ErrorClass { BadMethod, BadUserInput, NoMethodAvailable }; constexpr static auto errorClassPrettyName = make_array< std::string_view >("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 SecurityKeyException, // code: 16 PasscodeException, // code: 18 SendPushException, // code: 21 | this code really should not be here as rest of the codes are strictly for passcode verification TooManyRequestsException // code: 101 }; constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "BadInput", "SecurityKeyException", "PasscodeException", "SendPushException", "TooManyRequestsException"); 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< std::string_view >( // "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 { MissingFieldException, ApplicationNotFoundException, InvalidSignatureException, // code: 9 UnsupportedVersionException }; constexpr static auto errorClassPrettyName = make_array< std::string_view >( // "MissingFieldException", "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