| // Copyright 2021 The Fuchsia Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef SRC_DEVELOPER_DEBUG_SHARED_STATUS_H_ | |
| #define SRC_DEVELOPER_DEBUG_SHARED_STATUS_H_ | |
| #include <iosfwd> | |
| #include <string> | |
| #if defined(__Fuchsia__) | |
| #include <zircon/status.h> | |
| #endif | |
| #include "src/developer/debug/shared/serialization.h" | |
| namespace debug { | |
| class Status; | |
| #if defined(__Fuchsia__) | |
| // If there is an error and no message is given, the ZX_* constant will be queried and used. | |
| // If given, the message will be used for most display purposes instead of the platform value, so | |
| // if the value is important and you use a custom message, it should be manually included. | |
| // | |
| // These are split rather than using default values to avoid creating empty std::strings in the | |
| // common case. | |
| Status ZxStatus(zx_status_t s); | |
| Status ZxStatus(zx_status_t s, std::string msg); | |
| #else | |
| // As with the ZxStatus version above, this will automatically use the strerror() string if no | |
| // message is given. | |
| Status ErrnoStatus(int en); | |
| Status ErrnoStatus(int en, std::string msg); | |
| #endif | |
| // A cross-platform status value. It has three modes: | |
| // | |
| // - OK. This is generated by the default constructor and indicates "no error". | |
| // | |
| // - Platform error: This is generated by one of the above platform-specific helpers. It has a | |
| // platform error value (zx_status_t or errno), and it also looks up the corresponding string | |
| // from the operating system. | |
| // | |
| // - Cross-platform error: This can be one of a specific set of enum values that we need to handle | |
| // specially from a code perspective, or a generic error with just a message. There is no | |
| // platform_error number. There may or may not be a message. | |
| class Status { | |
| public: | |
| enum Type : uint32_t { | |
| kSuccess, | |
| kGenericError, // There is an error message but no specific enum or platform error. | |
| kNotSupported, // The system does not support the requested operation. | |
| kNotFound, // For example, the processes to be attached to didn't exist. | |
| kAlreadyExists, // For example, attaching to a process or job that's already attached. | |
| kNoResources, // Ran out of something (like debug registers). | |
| kPlatformError, // An error from the OS in platform_error(). | |
| // Not a valid value, used for bounds checking. | |
| kLast, | |
| }; | |
| // No error. For error construction, use one of the helpers above. | |
| Status() = default; | |
| // Constructor for a generic platform-independent error. The string may or may not be empty. | |
| explicit Status(std::string msg); | |
| // Constructor for a platform-independent error. The string is optional. | |
| // | |
| // A type of kSuccess or kPlatformError will assert (use the platform-specific helpers above). | |
| explicit Status(Type t, std::string msg = std::string()); | |
| // Code creating error should use the platform-specific helpers above. This is for code that | |
| // needs to create from some known internal values. The tag structure is to discourage direct use | |
| // of this function except when you really need it. | |
| // | |
| // The |pe| value should be 0 unless the type is a PlatformError. | |
| struct InternalValues {}; | |
| Status(InternalValues tag, Type t, uint64_t pe, std::string msg); | |
| bool ok() const { return type_ == kSuccess; } | |
| bool has_error() const { return !ok(); } | |
| Type type() const { return type_; } | |
| // Assumes the type == kPlatformError. | |
| int64_t platform_error() const { return platform_error_; } | |
| // The message may or may not be set on error. | |
| const std::string& message() const { return message_; } | |
| bool operator==(const Status& other) const { | |
| return type_ == other.type_ && platform_error_ == other.platform_error_ && | |
| message_ == other.message_; | |
| } | |
| bool operator!=(const Status& other) const { return !operator==(other); } | |
| void Serialize(Serializer& ser, uint32_t ver) { ser | type_ | platform_error_ | message_; } | |
| private: | |
| Type type_ = kSuccess; | |
| int64_t platform_error_ = 0; // Valid when type_ == kPlatformError. | |
| std::string message_; | |
| }; | |
| } // namespace debug | |
| std::ostream& operator<<(std::ostream& out, const debug::Status& status); | |
| #endif // SRC_DEVELOPER_DEBUG_SHARED_STATUS_H_ |