pw_status: StatusWithSize constants
- Provide StatusWithSize constants that can be used similarly to
Status::Codes. For example, StatusWithSize::DATA_LOSS constructs a
StatusWithSize with status DATA_LOSS and size 0.
- Remove the default constructor argument for the size. Use the
constants instead.
- Update uses of StatusWithSize(Status::X) to use StatusWithSize::X.
Change-Id: I901b7bb0bbbb4fde52f6b3acc3047f366b250515
diff --git a/pw_kvs/entry.cc b/pw_kvs/entry.cc
index fa224d4..894b2ce 100644
--- a/pw_kvs/entry.cc
+++ b/pw_kvs/entry.cc
@@ -87,7 +87,7 @@
StatusWithSize Entry::ReadValue(span<byte> buffer, size_t offset_bytes) const {
if (offset_bytes > value_size()) {
- return StatusWithSize(Status::OUT_OF_RANGE);
+ return StatusWithSize::OUT_OF_RANGE;
}
const size_t remaining_bytes = value_size() - offset_bytes;
diff --git a/pw_kvs/flash_memory.cc b/pw_kvs/flash_memory.cc
index f3d8dfb..0d164d8 100644
--- a/pw_kvs/flash_memory.cc
+++ b/pw_kvs/flash_memory.cc
@@ -48,7 +48,7 @@
StatusWithSize FlashPartition::Write(Address address, span<const byte> data) {
if (permission_ == PartitionPermission::kReadOnly) {
- return StatusWithSize(Status::PERMISSION_DENIED);
+ return StatusWithSize::PERMISSION_DENIED;
}
TRY_WITH_SIZE(CheckBounds(address, data.size()));
return flash_.Write(PartitionToFlashAddress(address), data);
diff --git a/pw_kvs/in_memory_fake_flash.cc b/pw_kvs/in_memory_fake_flash.cc
index 0b91965..1c9b7bc 100644
--- a/pw_kvs/in_memory_fake_flash.cc
+++ b/pw_kvs/in_memory_fake_flash.cc
@@ -79,7 +79,7 @@
StatusWithSize InMemoryFakeFlash::Read(Address address,
span<std::byte> output) {
if (address + output.size() >= sector_count() * size_bytes()) {
- return StatusWithSize(Status::OUT_OF_RANGE);
+ return StatusWithSize::OUT_OF_RANGE;
}
// Check for injected read errors
@@ -99,14 +99,14 @@
size_t(address),
data.size(),
alignment_bytes());
- return StatusWithSize(Status::INVALID_ARGUMENT);
+ return StatusWithSize::INVALID_ARGUMENT;
}
if (data.size() > sector_size_bytes() - (address % sector_size_bytes())) {
PW_LOG_ERROR("Write crosses sector boundary; address %zx, size %zu B",
size_t(address),
data.size());
- return StatusWithSize(Status::INVALID_ARGUMENT);
+ return StatusWithSize::INVALID_ARGUMENT;
}
if (address + data.size() > sector_count() * sector_size_bytes()) {
@@ -115,7 +115,7 @@
size_t(address),
data.size(),
sector_count() * sector_size_bytes());
- return StatusWithSize(Status::OUT_OF_RANGE);
+ return StatusWithSize::OUT_OF_RANGE;
}
// Check in erased state
@@ -123,7 +123,7 @@
if (buffer_[address + i] != kErasedValue) {
PW_LOG_ERROR("Writing to previously written address: %zx",
size_t(address));
- return StatusWithSize(Status::UNKNOWN);
+ return StatusWithSize::UNKNOWN;
}
}
diff --git a/pw_kvs/key_value_store.cc b/pw_kvs/key_value_store.cc
index 306ad82..6c438e8 100644
--- a/pw_kvs/key_value_store.cc
+++ b/pw_kvs/key_value_store.cc
@@ -341,7 +341,7 @@
entry_header_format_.checksum, key, value_buffer.first(result.size()));
if (!verify_result.ok()) {
std::memset(value_buffer.data(), 0, result.size());
- return StatusWithSize(verify_result);
+ return StatusWithSize(verify_result, 0);
}
return StatusWithSize(verify_result, result.size());
diff --git a/pw_kvs/public/pw_kvs/alignment.h b/pw_kvs/public/pw_kvs/alignment.h
index 08965ad..61b0b8e 100644
--- a/pw_kvs/public/pw_kvs/alignment.h
+++ b/pw_kvs/public/pw_kvs/alignment.h
@@ -101,7 +101,7 @@
// TODO: This should convert to PW_CHECK once that is available for use in
// host tests.
if (alignment_bytes > kBufferSize) {
- return StatusWithSize(Status::INTERNAL);
+ return StatusWithSize::INTERNAL;
}
AlignedWriterBuffer<kBufferSize> buffer(alignment_bytes, output);
diff --git a/pw_kvs/pw_kvs_private/macros.h b/pw_kvs/pw_kvs_private/macros.h
index 3fa326d..a4be24d 100644
--- a/pw_kvs/pw_kvs_private/macros.h
+++ b/pw_kvs/pw_kvs_private/macros.h
@@ -61,7 +61,7 @@
}
inline StatusWithSize ConvertToStatusWithSize(Status status) {
- return StatusWithSize(status);
+ return StatusWithSize(status, 0);
}
inline StatusWithSize ConvertToStatusWithSize(StatusWithSize status_with_size) {
diff --git a/pw_status/public/pw_status/status_with_size.h b/pw_status/public/pw_status/status_with_size.h
index b13a09d..607b8e1 100644
--- a/pw_status/public/pw_status/status_with_size.h
+++ b/pw_status/public/pw_status/status_with_size.h
@@ -14,11 +14,29 @@
#pragma once
#include <cstddef>
+#include <type_traits>
#include "pw_status/status.h"
namespace pw {
+class StatusWithSize;
+
+namespace internal {
+
+template <int kStatusShift>
+class StatusWithSizeConstant {
+ private:
+ friend class ::pw::StatusWithSize;
+
+ explicit constexpr StatusWithSizeConstant(Status::Code value)
+ : value_(static_cast<size_t>(value) << kStatusShift) {}
+
+ const size_t value_;
+};
+
+} // namespace internal
+
// StatusWithSize stores a status and an unsigned integer. The integer must not
// exceed StatusWithSize::max_size(), which is 134,217,727 (2**27 - 1) on 32-bit
// systems.
@@ -45,14 +63,51 @@
// increases code size.
//
class StatusWithSize {
+ private:
+ static constexpr size_t kStatusBits = 5;
+ static constexpr size_t kSizeMask = ~static_cast<size_t>(0) >> kStatusBits;
+ static constexpr size_t kStatusMask = ~kSizeMask;
+ static constexpr size_t kStatusShift = sizeof(size_t) * 8 - kStatusBits;
+
+ using Constant = internal::StatusWithSizeConstant<kStatusShift>;
+
public:
+ // Non-OK StatusWithSizes can be constructed from these constants, such as:
+ //
+ // StatusWithSize result = StatusWithSize::NOT_FOUND;
+ //
+ static constexpr Constant CANCELLED{Status::CANCELLED};
+ static constexpr Constant UNKNOWN{Status::UNKNOWN};
+ static constexpr Constant INVALID_ARGUMENT{Status::INVALID_ARGUMENT};
+ static constexpr Constant DEADLINE_EXCEEDED{Status::DEADLINE_EXCEEDED};
+ static constexpr Constant NOT_FOUND{Status::NOT_FOUND};
+ static constexpr Constant ALREADY_EXISTS{Status::ALREADY_EXISTS};
+ static constexpr Constant PERMISSION_DENIED{Status::PERMISSION_DENIED};
+ static constexpr Constant RESOURCE_EXHAUSTED{Status::RESOURCE_EXHAUSTED};
+ static constexpr Constant FAILED_PRECONDITION{Status::FAILED_PRECONDITION};
+ static constexpr Constant ABORTED{Status::ABORTED};
+ static constexpr Constant OUT_OF_RANGE{Status::OUT_OF_RANGE};
+ static constexpr Constant UNIMPLEMENTED{Status::UNIMPLEMENTED};
+ static constexpr Constant INTERNAL{Status::INTERNAL};
+ static constexpr Constant UNAVAILABLE{Status::UNAVAILABLE};
+ static constexpr Constant DATA_LOSS{Status::DATA_LOSS};
+ static constexpr Constant UNAUTHENTICATED{Status::UNAUTHENTICATED};
+
+ // Creates a StatusWithSize with Status::OK and a size of 0.
+ explicit constexpr StatusWithSize() : size_(0) {}
+
// Creates a StatusWithSize with Status::OK and the provided size.
+ // std::enable_if is used to prevent enum types (e.g. Status) from being used.
// TODO(hepler): Add debug-only assert that size <= max_size().
- explicit constexpr StatusWithSize(size_t size = 0) : size_(size) {}
+ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+ explicit constexpr StatusWithSize(T size) : size_(size) {}
// Creates a StatusWithSize with the provided status and size.
- explicit constexpr StatusWithSize(Status::Code status, size_t size = 0)
- : StatusWithSize(size | (static_cast<size_t>(status) << kStatusShift)) {}
+ constexpr StatusWithSize(Status::Code status, size_t size)
+ : StatusWithSize((static_cast<size_t>(status) << kStatusShift) | size) {}
+
+ // Allow implicit conversions from the StatusWithSize constants.
+ constexpr StatusWithSize(Constant constant) : size_(constant.value_) {}
constexpr StatusWithSize(const StatusWithSize&) = default;
constexpr StatusWithSize& operator=(const StatusWithSize&) = default;
@@ -71,11 +126,6 @@
}
private:
- static constexpr size_t kStatusBits = 5;
- static constexpr size_t kSizeMask = ~static_cast<size_t>(0) >> kStatusBits;
- static constexpr size_t kStatusMask = ~kSizeMask;
- static constexpr size_t kStatusShift = sizeof(size_t) * 8 - kStatusBits;
-
size_t size_;
};
diff --git a/pw_status/status_with_size_test.cc b/pw_status/status_with_size_test.cc
index 2ed4162..473384a 100644
--- a/pw_status/status_with_size_test.cc
+++ b/pw_status/status_with_size_test.cc
@@ -51,27 +51,18 @@
EXPECT_EQ(99u, result.size());
}
-TEST(StatusWithSize, ConstructWithStatusCodeAndDefaultSize) {
- StatusWithSize result(Status::ALREADY_EXISTS);
+TEST(StatusWithSize, ConstructFromConstant) {
+ StatusWithSize result(StatusWithSize::ALREADY_EXISTS);
+
EXPECT_EQ(Status::ALREADY_EXISTS, result.status());
EXPECT_EQ(0u, result.size());
-}
-TEST(StatusWithSize, ConstructWithStatusAndDefaultSize) {
- StatusWithSize result(Status{Status::ALREADY_EXISTS});
- EXPECT_EQ(Status::ALREADY_EXISTS, result.status());
+ result = StatusWithSize::NOT_FOUND;
+
+ EXPECT_EQ(Status::NOT_FOUND, result.status());
EXPECT_EQ(0u, result.size());
}
-TEST(StatusWithSize, AllStatusValues_DefaultSize) {
- for (int i = 0; i < 32; ++i) {
- StatusWithSize result(static_cast<Status::Code>(i));
- EXPECT_EQ(result.ok(), i == 0);
- EXPECT_EQ(i, static_cast<int>(result.status()));
- EXPECT_EQ(0u, result.size());
- }
-}
-
TEST(StatusWithSize, AllStatusValues_ZeroSize) {
for (int i = 0; i < 32; ++i) {
StatusWithSize result(static_cast<Status::Code>(i), 0);
diff --git a/pw_string/format.cc b/pw_string/format.cc
index 03942a3..b069fe8 100644
--- a/pw_string/format.cc
+++ b/pw_string/format.cc
@@ -31,7 +31,7 @@
const char* format,
va_list args) {
if (buffer.empty()) {
- return StatusWithSize(Status::RESOURCE_EXHAUSTED);
+ return StatusWithSize::RESOURCE_EXHAUSTED;
}
const int result = std::vsnprintf(buffer.data(), buffer.size(), format, args);
@@ -40,7 +40,7 @@
// Discard any output by terminating the buffer.
if (result < 0) {
buffer[0] = '\0';
- return StatusWithSize(Status::INVALID_ARGUMENT);
+ return StatusWithSize::INVALID_ARGUMENT;
}
// If result >= buffer.size(), the output was truncated and null-terminated.
diff --git a/pw_string/to_string_test.cc b/pw_string/to_string_test.cc
index 2dcb2d3..19d4931 100644
--- a/pw_string/to_string_test.cc
+++ b/pw_string/to_string_test.cc
@@ -43,7 +43,7 @@
int result =
std::snprintf(buffer.data(), buffer.size(), CustomType::kToString);
if (result < 0) {
- return StatusWithSize(Status::UNKNOWN);
+ return StatusWithSize::UNKNOWN;
}
if (static_cast<size_t>(result) < buffer.size()) {
return StatusWithSize(result);
diff --git a/pw_string/type_to_string.cc b/pw_string/type_to_string.cc
index f22b3e3..fd2d1f6 100644
--- a/pw_string/type_to_string.cc
+++ b/pw_string/type_to_string.cc
@@ -51,7 +51,7 @@
if (!buffer.empty()) {
buffer[0] = '\0';
}
- return StatusWithSize(Status::RESOURCE_EXHAUSTED);
+ return StatusWithSize::RESOURCE_EXHAUSTED;
}
} // namespace
@@ -181,7 +181,7 @@
StatusWithSize CopyString(const std::string_view& value,
const span<char>& buffer) {
if (buffer.empty()) {
- return StatusWithSize(Status::RESOURCE_EXHAUSTED);
+ return StatusWithSize::RESOURCE_EXHAUSTED;
}
const size_t copied = value.copy(buffer.data(), buffer.size() - 1);