#ifndef PLATFORM_V2_BASE_EXCEPTION_H_ #define PLATFORM_V2_BASE_EXCEPTION_H_ #include #include "absl/meta/type_traits.h" namespace location { namespace nearby { struct Exception { enum Value : int { kFailed = -1, // Initial value of Exception; any unknown error. kSuccess = 0, // No exception. kIo = 1, // IO Error happened. kInterrupted = 2, // Operation was interrupted. kInvalidProtocolBuffer = 3, // Couldn't parse. kExecution = 4, // Couldn't execute. kTimeout = 5, // Operarion did not finish within specified time. }; bool Ok() const { return value == kSuccess; } bool Raised() const { return !Ok(); } bool Raised(Value value) const { return this->value == value; } Value value{kFailed}; }; constexpr inline bool operator==(const Exception& a, const Exception& b) { return a.value == b.value; } constexpr inline bool operator!=(const Exception& a, const Exception& b) { return !(a == b); } // ExceptionOr provides experience similar to StatusOr used in // Google Cloud API, see: // https://googleapis.github.io/google-cloud-cpp/0.7.0/common/status__or_8h_source.html // // If ok() returns true, result() is a usable return value. Otherwise, // exception() explains why such a value is not present. // // A typical pattern of usage is as follows: // // if (!e.ok()) { // if (Exception::EXCEPTION_TYPE_1 == e.exception()) { // // Handle Exception::EXCEPTION_TYPE_1. // } else if (Exception::EXCEPTION_TYPE_2 == e.exception()) { // // Handle Exception::EXCEPTION_TYPE_2. // } // // return; // } // // // Use e.result(). template class ExceptionOr { public: ExceptionOr() = default; explicit ExceptionOr(T&& result) : result_{std::move(result)}, exception_{Exception::kSuccess} {} // NOLINT explicit ExceptionOr(const T& result) : result_{result}, exception_{Exception::kSuccess} {} // NOLINT ExceptionOr(Exception::Value exception) : exception_{exception} {} // NOLINT ExceptionOr(Exception exception) : exception_{exception} {} // NOLINT // If there exists explicit conversion from from U to T, // then allow explicit conversion from ExceptionOr to ExceptionOr. template ()})>> explicit ExceptionOr(ExceptionOr value) { if (!value.ok()) { exception_ = value.GetException(); } else { result_ = T{std::move(value.result())}; exception_ = Exception{Exception::kSuccess}; } } bool ok() const { return exception_.value == Exception::kSuccess; } T& result() & { return result_; } const T& result() const& { return result_; } T&& result() && { return std::move(result_); } const T&& result() const&& { return std::move(result_); } Exception::Value exception() const { return exception_.value; } T GetResult() const { return result_; } Exception GetException() const { return exception_; } private: T result_{}; Exception exception_{Exception::kFailed}; }; } // namespace nearby } // namespace location #endif // PLATFORM_V2_BASE_EXCEPTION_H_