pw_status: Functions for checking the status code
- Add IsErrorCode() functions to simplify checking for specific status
codes.
- Automatically replace some cases of status == Status::Code() with
status.IsCode() in update_style.py.
Change-Id: I13be834a2413d694d41a7755d2e317c35d34c5bf
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/19521
Reviewed-by: Keir Mierle <keir@google.com>
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Commit-Queue: Wyatt Hepler <hepler@google.com>
diff --git a/pw_status/public/pw_status/status.h b/pw_status/public/pw_status/status.h
index be9e568..b7c1926 100644
--- a/pw_status/public/pw_status/status.h
+++ b/pw_status/public/pw_status/status.h
@@ -313,6 +313,56 @@
// True if the status is Status::Ok().
[[nodiscard]] constexpr bool ok() const { return code_ == PW_STATUS_OK; }
+ // Functions for checking which status this is.
+ [[nodiscard]] constexpr bool IsCancelled() const {
+ return code_ == PW_STATUS_CANCELLED;
+ }
+ [[nodiscard]] constexpr bool IsUnknown() const {
+ return code_ == PW_STATUS_UNKNOWN;
+ }
+ [[nodiscard]] constexpr bool IsInvalidArgument() const {
+ return code_ == PW_STATUS_INVALID_ARGUMENT;
+ }
+ [[nodiscard]] constexpr bool IsDeadlineExceeded() const {
+ return code_ == PW_STATUS_DEADLINE_EXCEEDED;
+ }
+ [[nodiscard]] constexpr bool IsNotFound() const {
+ return code_ == PW_STATUS_NOT_FOUND;
+ }
+ [[nodiscard]] constexpr bool IsAlreadyExists() const {
+ return code_ == PW_STATUS_ALREADY_EXISTS;
+ }
+ [[nodiscard]] constexpr bool IsPermissionDenied() const {
+ return code_ == PW_STATUS_PERMISSION_DENIED;
+ }
+ [[nodiscard]] constexpr bool IsResourceExhausted() const {
+ return code_ == PW_STATUS_RESOURCE_EXHAUSTED;
+ }
+ [[nodiscard]] constexpr bool IsFailedPrecondition() const {
+ return code_ == PW_STATUS_FAILED_PRECONDITION;
+ }
+ [[nodiscard]] constexpr bool IsAborted() const {
+ return code_ == PW_STATUS_ABORTED;
+ }
+ [[nodiscard]] constexpr bool IsOutOfRange() const {
+ return code_ == PW_STATUS_OUT_OF_RANGE;
+ }
+ [[nodiscard]] constexpr bool IsUnimplemented() const {
+ return code_ == PW_STATUS_UNIMPLEMENTED;
+ }
+ [[nodiscard]] constexpr bool IsInternal() const {
+ return code_ == PW_STATUS_INTERNAL;
+ }
+ [[nodiscard]] constexpr bool IsUnavailable() const {
+ return code_ == PW_STATUS_UNAVAILABLE;
+ }
+ [[nodiscard]] constexpr bool IsDataLoss() const {
+ return code_ == PW_STATUS_DATA_LOSS;
+ }
+ [[nodiscard]] constexpr bool IsUnauthenticated() const {
+ return code_ == PW_STATUS_UNAUTHENTICATED;
+ }
+
// Returns a null-terminated string representation of the Status.
[[nodiscard]] const char* str() const { return pw_StatusString(code_); }
diff --git a/pw_status/public/pw_status/status_with_size.h b/pw_status/public/pw_status/status_with_size.h
index 8c79e8c..d83548e 100644
--- a/pw_status/public/pw_status/status_with_size.h
+++ b/pw_status/public/pw_status/status_with_size.h
@@ -184,6 +184,56 @@
return static_cast<Status::Code>((size_ & kStatusMask) >> kStatusShift);
}
+ // Functions for checking which status the StatusWithSize contains.
+ [[nodiscard]] constexpr bool IsCancelled() const {
+ return status().IsCancelled();
+ }
+ [[nodiscard]] constexpr bool IsUnknown() const {
+ return status().IsUnknown();
+ }
+ [[nodiscard]] constexpr bool IsInvalidArgument() const {
+ return status().IsInvalidArgument();
+ }
+ [[nodiscard]] constexpr bool IsDeadlineExceeded() const {
+ return status().IsDeadlineExceeded();
+ }
+ [[nodiscard]] constexpr bool IsNotFound() const {
+ return status().IsNotFound();
+ }
+ [[nodiscard]] constexpr bool IsAlreadyExists() const {
+ return status().IsAlreadyExists();
+ }
+ [[nodiscard]] constexpr bool IsPermissionDenied() const {
+ return status().IsPermissionDenied();
+ }
+ [[nodiscard]] constexpr bool IsResourceExhausted() const {
+ return status().IsResourceExhausted();
+ }
+ [[nodiscard]] constexpr bool IsFailedPrecondition() const {
+ return status().IsFailedPrecondition();
+ }
+ [[nodiscard]] constexpr bool IsAborted() const {
+ return status().IsAborted();
+ }
+ [[nodiscard]] constexpr bool IsOutOfRange() const {
+ return status().IsOutOfRange();
+ }
+ [[nodiscard]] constexpr bool IsUnimplemented() const {
+ return status().IsUnimplemented();
+ }
+ [[nodiscard]] constexpr bool IsInternal() const {
+ return status().IsInternal();
+ }
+ [[nodiscard]] constexpr bool IsUnavailable() const {
+ return status().IsUnavailable();
+ }
+ [[nodiscard]] constexpr bool IsDataLoss() const {
+ return status().IsDataLoss();
+ }
+ [[nodiscard]] constexpr bool IsUnauthenticated() const {
+ return status().IsUnauthenticated();
+ }
+
private:
size_t size_;
};
diff --git a/pw_status/py/pw_status/update_style.py b/pw_status/py/pw_status/update_style.py
index 57c92bb..bdff483 100755
--- a/pw_status/py/pw_status/update_style.py
+++ b/pw_status/py/pw_status/update_style.py
@@ -45,6 +45,16 @@
'DATA_LOSS': 'DataLoss',
}
+_CODES = '|'.join(_REMAP.keys())
+_FUNCTIONS = '|'.join(_REMAP.values())
+
+_STATUS_WITH_SIZE_CTOR = re.compile(
+ fr'\bStatusWithSize\(Status::({_CODES}),\s*')
+_STATUS = re.compile(fr'\b(Status|StatusWithSize)::({_CODES})(?!")\b')
+_STATUS_EQUALITY = re.compile(
+ fr'Status::(?P<l_func>{_FUNCTIONS})\(\)\s+==\s+(?P<value>[a-zA-Z0-9_.()]+)|'
+ fr'\s+==\s+Status::(?P<r_func>{_FUNCTIONS})\(\)')
+
def _remap_status_with_size(match) -> str:
return f'StatusWithSize::{_REMAP[match.group(1)]}('
@@ -54,11 +64,10 @@
return f'{match.group(1)}::{_REMAP[match.group(2)]}()'
-_CODES = '|'.join(_REMAP.keys())
-
-_STATUS_WITH_SIZE_CTOR = re.compile(
- fr'\bStatusWithSize\(Status::({_CODES}),\s*')
-_STATUS = re.compile(fr'\b(Status|StatusWithSize)::({_CODES})(?!")\b')
+def _remap_equality(match) -> str:
+ l_func, status, r_func = match.groups('')
+ func = l_func or r_func
+ return f'{status}.ok()' if func == 'Ok' else f'{status}.Is{func}()'
def _parse_args():
@@ -92,6 +101,8 @@
# Replace Status and StatusAWithSize
text = _STATUS.sub(_remap_codes, text)
+ text = _STATUS_EQUALITY.sub(_remap_equality, text)
+
if orig != text:
updated += 1
file.write_text(text)
diff --git a/pw_status/status_test.cc b/pw_status/status_test.cc
index 280b8be..a5fa3f4 100644
--- a/pw_status/status_test.cc
+++ b/pw_status/status_test.cc
@@ -90,6 +90,44 @@
static_assert(PW_STATUS_UNAUTHENTICATED == Status::Unauthenticated());
}
+TEST(Status, IsError) {
+ static_assert(Status::Cancelled().IsCancelled());
+ static_assert(Status::Unknown().IsUnknown());
+ static_assert(Status::InvalidArgument().IsInvalidArgument());
+ static_assert(Status::DeadlineExceeded().IsDeadlineExceeded());
+ static_assert(Status::NotFound().IsNotFound());
+ static_assert(Status::AlreadyExists().IsAlreadyExists());
+ static_assert(Status::PermissionDenied().IsPermissionDenied());
+ static_assert(Status::ResourceExhausted().IsResourceExhausted());
+ static_assert(Status::FailedPrecondition().IsFailedPrecondition());
+ static_assert(Status::Aborted().IsAborted());
+ static_assert(Status::OutOfRange().IsOutOfRange());
+ static_assert(Status::Unimplemented().IsUnimplemented());
+ static_assert(Status::Internal().IsInternal());
+ static_assert(Status::Unavailable().IsUnavailable());
+ static_assert(Status::DataLoss().IsDataLoss());
+ static_assert(Status::Unauthenticated().IsUnauthenticated());
+}
+
+TEST(Status, IsNotError) {
+ static_assert(!Status::Ok().IsCancelled());
+ static_assert(!Status::Ok().IsUnknown());
+ static_assert(!Status::Ok().IsInvalidArgument());
+ static_assert(!Status::Ok().IsDeadlineExceeded());
+ static_assert(!Status::Ok().IsNotFound());
+ static_assert(!Status::Ok().IsAlreadyExists());
+ static_assert(!Status::Ok().IsPermissionDenied());
+ static_assert(!Status::Ok().IsUnauthenticated());
+ static_assert(!Status::Ok().IsResourceExhausted());
+ static_assert(!Status::Ok().IsFailedPrecondition());
+ static_assert(!Status::Ok().IsAborted());
+ static_assert(!Status::Ok().IsOutOfRange());
+ static_assert(!Status::Ok().IsUnimplemented());
+ static_assert(!Status::Ok().IsInternal());
+ static_assert(!Status::Ok().IsUnavailable());
+ static_assert(!Status::Ok().IsDataLoss());
+}
+
TEST(Status, Strings) {
EXPECT_STREQ("OK", Status().str());
EXPECT_STREQ("OK", Status::Ok().str());
diff --git a/pw_status/status_with_size_test.cc b/pw_status/status_with_size_test.cc
index f92e959..e856713 100644
--- a/pw_status/status_with_size_test.cc
+++ b/pw_status/status_with_size_test.cc
@@ -110,7 +110,7 @@
static_assert(1234u == result.size());
}
-TEST(Status, Functions_Status) {
+TEST(StatusWithSize, Functions_Status) {
// clang-format off
static_assert(StatusWithSize::Ok(0).status() == Status::Ok());
static_assert(StatusWithSize::Cancelled().status() == Status::Cancelled());
@@ -150,7 +150,7 @@
// clang-format on
}
-TEST(Status, Functions_DefaultSize) {
+TEST(StatusWithSize, Functions_DefaultSize) {
static_assert(StatusWithSize::Cancelled().size() == 0u);
static_assert(StatusWithSize::Unknown().size() == 0u);
static_assert(StatusWithSize::InvalidArgument().size() == 0u);
@@ -169,7 +169,7 @@
static_assert(StatusWithSize::DataLoss().size() == 0u);
}
-TEST(Status, Functions_SpecifiedSize) {
+TEST(StatusWithSize, Functions_SpecifiedSize) {
static_assert(StatusWithSize::Ok(123).size() == 123u);
static_assert(StatusWithSize::Cancelled(123).size() == 123u);
static_assert(StatusWithSize::Unknown(123).size() == 123u);
@@ -189,5 +189,42 @@
static_assert(StatusWithSize::DataLoss(123).size() == 123u);
}
+TEST(StatusWithSize, IsError) {
+ static_assert(StatusWithSize::Cancelled().IsCancelled());
+ static_assert(StatusWithSize::Unknown().IsUnknown());
+ static_assert(StatusWithSize::InvalidArgument().IsInvalidArgument());
+ static_assert(StatusWithSize::DeadlineExceeded().IsDeadlineExceeded());
+ static_assert(StatusWithSize::NotFound().IsNotFound());
+ static_assert(StatusWithSize::AlreadyExists().IsAlreadyExists());
+ static_assert(StatusWithSize::PermissionDenied().IsPermissionDenied());
+ static_assert(StatusWithSize::ResourceExhausted().IsResourceExhausted());
+ static_assert(StatusWithSize::FailedPrecondition().IsFailedPrecondition());
+ static_assert(StatusWithSize::Aborted().IsAborted());
+ static_assert(StatusWithSize::OutOfRange().IsOutOfRange());
+ static_assert(StatusWithSize::Unimplemented().IsUnimplemented());
+ static_assert(StatusWithSize::Internal().IsInternal());
+ static_assert(StatusWithSize::Unavailable().IsUnavailable());
+ static_assert(StatusWithSize::DataLoss().IsDataLoss());
+ static_assert(StatusWithSize::Unauthenticated().IsUnauthenticated());
+}
+
+TEST(StatusWithSize, IsNotError) {
+ static_assert(!StatusWithSize::Ok(0).IsCancelled());
+ static_assert(!StatusWithSize::Ok(0).IsUnknown());
+ static_assert(!StatusWithSize::Ok(0).IsInvalidArgument());
+ static_assert(!StatusWithSize::Ok(0).IsDeadlineExceeded());
+ static_assert(!StatusWithSize::Ok(0).IsNotFound());
+ static_assert(!StatusWithSize::Ok(0).IsAlreadyExists());
+ static_assert(!StatusWithSize::Ok(0).IsPermissionDenied());
+ static_assert(!StatusWithSize::Ok(0).IsUnauthenticated());
+ static_assert(!StatusWithSize::Ok(0).IsResourceExhausted());
+ static_assert(!StatusWithSize::Ok(0).IsFailedPrecondition());
+ static_assert(!StatusWithSize::Ok(0).IsAborted());
+ static_assert(!StatusWithSize::Ok(0).IsOutOfRange());
+ static_assert(!StatusWithSize::Ok(0).IsUnimplemented());
+ static_assert(!StatusWithSize::Ok(0).IsInternal());
+ static_assert(!StatusWithSize::Ok(0).IsUnavailable());
+ static_assert(!StatusWithSize::Ok(0).IsDataLoss());
+}
} // namespace
} // namespace pw