xref: /aosp_15_r20/external/pigweed/pw_status/public/pw_status/status.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include "pw_status/internal/config.h"
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif  // __cplusplus
21 
22 // This is the pw_Status enum. pw_Status is used to return the status from an
23 // operation.
24 //
25 // In C++, use the pw::Status class instead of the pw_Status enum. pw_Status and
26 // Status implicitly convert to one another and can be passed cleanly between C
27 // and C++ APIs.
28 //
29 // pw_Status uses the canonical Google error codes. The following enum was based
30 // on Abseil's status/status.h. The values are all-caps and prefixed with
31 // PW_STATUS_ instead of using C++ constant style.
32 //
33 // The status codes are described at https://pigweed.dev/pw_status#status-codes.
34 // Consult that guide when deciding which status code to use.
35 typedef enum {
36   PW_STATUS_OK = 0,                   // Use OkStatus() in C++
37   PW_STATUS_CANCELLED = 1,            // Use Status::Cancelled() in C++
38   PW_STATUS_UNKNOWN = 2,              // Use Status::Unknown() in C++
39   PW_STATUS_INVALID_ARGUMENT = 3,     // Use Status::InvalidArgument() in C++
40   PW_STATUS_DEADLINE_EXCEEDED = 4,    // Use Status::DeadlineExceeded() in C++
41   PW_STATUS_NOT_FOUND = 5,            // Use Status::NotFound() in C++
42   PW_STATUS_ALREADY_EXISTS = 6,       // Use Status::AlreadyExists() in C++
43   PW_STATUS_PERMISSION_DENIED = 7,    // Use Status::PermissionDenied() in C++
44   PW_STATUS_RESOURCE_EXHAUSTED = 8,   // Use Status::ResourceExhausted() in C++
45   PW_STATUS_FAILED_PRECONDITION = 9,  // Use Status::FailedPrecondition() in C++
46   PW_STATUS_ABORTED = 10,             // Use Status::Aborted() in C++
47   PW_STATUS_OUT_OF_RANGE = 11,        // Use Status::OutOfRange() in C++
48   PW_STATUS_UNIMPLEMENTED = 12,       // Use Status::Unimplemented() in C++
49   PW_STATUS_INTERNAL = 13,            // Use Status::Internal() in C++
50   PW_STATUS_UNAVAILABLE = 14,         // Use Status::Unavailable() in C++
51   PW_STATUS_DATA_LOSS = 15,           // Use Status::DataLoss() in C++
52   PW_STATUS_UNAUTHENTICATED = 16,     // Use Status::Unauthenticated() in C++
53 
54   // NOTE: this error code entry should not be used and you should not rely on
55   // its value, which may change.
56   //
57   // The purpose of this enumerated value is to force people who handle status
58   // codes with `switch()` statements to *not* simply enumerate all possible
59   // values, but instead provide a "default:" case. Providing such a default
60   // case ensures that code will compile when new codes are added.
61   PW_STATUS_DO_NOT_USE_RESERVED_FOR_FUTURE_EXPANSION_USE_DEFAULT_IN_SWITCH_INSTEAD_,
62 } pw_Status;  // Use pw::Status in C++
63 
64 // Returns a null-terminated string representation of the pw_Status.
65 const char* pw_StatusString(pw_Status status);
66 
67 // Indicates the status code with the highest valid value.
68 #define PW_STATUS_LAST PW_STATUS_UNAUTHENTICATED
69 
70 #ifdef __cplusplus
71 
72 }  // extern "C"
73 
74 namespace pw {
75 
76 /// `Status` is a thin, zero-cost abstraction around the `pw_Status` enum. It
77 /// initializes to @pw_status{OK} by default and adds `ok()` and `str()`
78 /// methods. Implicit conversions are permitted between `pw_Status` and
79 /// `pw::Status`.
80 ///
81 /// An @pw_status{OK} `Status` is created by the @cpp_func{pw::OkStatus}
82 /// function or by the default `Status` constructor.  Non-OK `Status` is created
83 /// with a static member function that corresponds with the status code.
84 class _PW_STATUS_NO_DISCARD Status {
85  public:
86   using Code = pw_Status;
87 
88   // Functions that create a Status with the specified code.
89   //
90   // The status codes are described at
91   // https://pigweed.dev/pw_status#status-codes. Consult that guide when
92   // deciding which status code to use.
93   // clang-format off
Cancelled()94   [[nodiscard]] static constexpr Status Cancelled() {
95     return PW_STATUS_CANCELLED;
96   }
Unknown()97   [[nodiscard]] static constexpr Status Unknown() {
98     return PW_STATUS_UNKNOWN;
99   }
InvalidArgument()100   [[nodiscard]] static constexpr Status InvalidArgument() {
101     return PW_STATUS_INVALID_ARGUMENT;
102   }
DeadlineExceeded()103   [[nodiscard]] static constexpr Status DeadlineExceeded() {
104     return PW_STATUS_DEADLINE_EXCEEDED;
105   }
NotFound()106   [[nodiscard]] static constexpr Status NotFound() {
107     return PW_STATUS_NOT_FOUND;
108   }
AlreadyExists()109   [[nodiscard]] static constexpr Status AlreadyExists() {
110     return PW_STATUS_ALREADY_EXISTS;
111   }
PermissionDenied()112   [[nodiscard]] static constexpr Status PermissionDenied() {
113     return PW_STATUS_PERMISSION_DENIED;
114   }
ResourceExhausted()115   [[nodiscard]] static constexpr Status ResourceExhausted() {
116     return PW_STATUS_RESOURCE_EXHAUSTED;
117   }
FailedPrecondition()118   [[nodiscard]] static constexpr Status FailedPrecondition() {
119     return PW_STATUS_FAILED_PRECONDITION;
120   }
Aborted()121   [[nodiscard]] static constexpr Status Aborted() {
122     return PW_STATUS_ABORTED;
123   }
OutOfRange()124   [[nodiscard]] static constexpr Status OutOfRange() {
125     return PW_STATUS_OUT_OF_RANGE;
126   }
Unimplemented()127   [[nodiscard]] static constexpr Status Unimplemented() {
128     return PW_STATUS_UNIMPLEMENTED;
129   }
Internal()130   [[nodiscard]] static constexpr Status Internal() {
131     return PW_STATUS_INTERNAL;
132   }
Unavailable()133   [[nodiscard]] static constexpr Status Unavailable() {
134     return PW_STATUS_UNAVAILABLE;
135   }
DataLoss()136   [[nodiscard]] static constexpr Status DataLoss() {
137     return PW_STATUS_DATA_LOSS;
138   }
Unauthenticated()139   [[nodiscard]] static constexpr Status Unauthenticated() {
140     return PW_STATUS_UNAUTHENTICATED;
141   }
142   // clang-format on
143 
144   // Statuses are created with a Status::Code.
code_(code)145   constexpr Status(Code code = PW_STATUS_OK) : code_(code) {}
146 
147   constexpr Status(const Status&) = default;
148   constexpr Status& operator=(const Status&) = default;
149 
150   /// Returns the `Status::Code` (`pw_Status`) for this `Status`.
code()151   constexpr Code code() const { return code_; }
152 
153   /// True if the status is @pw_status{OK}.
154   ///
155   /// This function is provided in place of an `IsOk()` function.
ok()156   [[nodiscard]] constexpr bool ok() const { return code_ == PW_STATUS_OK; }
157 
158   // Functions for checking which status this is.
IsCancelled()159   [[nodiscard]] constexpr bool IsCancelled() const {
160     return code_ == PW_STATUS_CANCELLED;
161   }
IsUnknown()162   [[nodiscard]] constexpr bool IsUnknown() const {
163     return code_ == PW_STATUS_UNKNOWN;
164   }
IsInvalidArgument()165   [[nodiscard]] constexpr bool IsInvalidArgument() const {
166     return code_ == PW_STATUS_INVALID_ARGUMENT;
167   }
IsDeadlineExceeded()168   [[nodiscard]] constexpr bool IsDeadlineExceeded() const {
169     return code_ == PW_STATUS_DEADLINE_EXCEEDED;
170   }
IsNotFound()171   [[nodiscard]] constexpr bool IsNotFound() const {
172     return code_ == PW_STATUS_NOT_FOUND;
173   }
IsAlreadyExists()174   [[nodiscard]] constexpr bool IsAlreadyExists() const {
175     return code_ == PW_STATUS_ALREADY_EXISTS;
176   }
IsPermissionDenied()177   [[nodiscard]] constexpr bool IsPermissionDenied() const {
178     return code_ == PW_STATUS_PERMISSION_DENIED;
179   }
IsResourceExhausted()180   [[nodiscard]] constexpr bool IsResourceExhausted() const {
181     return code_ == PW_STATUS_RESOURCE_EXHAUSTED;
182   }
IsFailedPrecondition()183   [[nodiscard]] constexpr bool IsFailedPrecondition() const {
184     return code_ == PW_STATUS_FAILED_PRECONDITION;
185   }
IsAborted()186   [[nodiscard]] constexpr bool IsAborted() const {
187     return code_ == PW_STATUS_ABORTED;
188   }
IsOutOfRange()189   [[nodiscard]] constexpr bool IsOutOfRange() const {
190     return code_ == PW_STATUS_OUT_OF_RANGE;
191   }
IsUnimplemented()192   [[nodiscard]] constexpr bool IsUnimplemented() const {
193     return code_ == PW_STATUS_UNIMPLEMENTED;
194   }
IsInternal()195   [[nodiscard]] constexpr bool IsInternal() const {
196     return code_ == PW_STATUS_INTERNAL;
197   }
IsUnavailable()198   [[nodiscard]] constexpr bool IsUnavailable() const {
199     return code_ == PW_STATUS_UNAVAILABLE;
200   }
IsDataLoss()201   [[nodiscard]] constexpr bool IsDataLoss() const {
202     return code_ == PW_STATUS_DATA_LOSS;
203   }
IsUnauthenticated()204   [[nodiscard]] constexpr bool IsUnauthenticated() const {
205     return code_ == PW_STATUS_UNAUTHENTICATED;
206   }
207 
208   /// Updates this `Status` to the provided `Status` IF this status is
209   /// @pw_status{OK}. This is useful for tracking the first encountered error,
210   /// as calls to this helper will not change one error status to another error
211   /// status.
Update(Status other)212   constexpr void Update(Status other) {
213     if (ok()) {
214       code_ = other.code();
215     }
216   }
217 
218   /// Ignores any errors. This method does nothing except potentially suppress
219   /// complaints from any tools that are checking that errors are not dropped on
220   /// the floor.
IgnoreError()221   constexpr void IgnoreError() const {}
222 
223   /// Returns a null-terminated string representation of the `Status`.
str()224   [[nodiscard]] const char* str() const { return pw_StatusString(code_); }
225 
226  private:
227   Code code_;
228 };
229 
230 /// Returns an @pw_status{OK} status. Equivalent to `Status()` or
231 /// `Status(PW_STATUS_OK)`.  This function is used instead of a `Status::Ok()`
232 /// function, which would be too similar to `Status::ok()`.
OkStatus()233 [[nodiscard]] constexpr Status OkStatus() { return Status(); }
234 
235 constexpr bool operator==(const Status& lhs, const Status& rhs) {
236   return lhs.code() == rhs.code();
237 }
238 
239 constexpr bool operator!=(const Status& lhs, const Status& rhs) {
240   return lhs.code() != rhs.code();
241 }
242 
243 namespace internal {
244 
245 // This function and its various overloads are for use by internal macros
246 // like PW_TRY.
ConvertToStatus(Status status)247 constexpr Status ConvertToStatus(Status status) { return status; }
248 
249 }  // namespace internal
250 }  // namespace pw
251 
252 // Create a C++ overload of pw_StatusString so that it supports pw::Status in
253 // addition to pw_Status.
pw_StatusString(pw::Status status)254 inline const char* pw_StatusString(pw::Status status) {
255   return pw_StatusString(status.code());
256 }
257 
258 #endif  // __cplusplus
259