19#include "pw_allocator/hardening.h"
20#include "pw_assert/assert.h"
21#include "pw_status/status.h"
22#include "pw_status/status_with_size.h"
24namespace pw::allocator {
36 enum class Prev : uint8_t {
45 enum class Next : uint8_t {
52 [[nodiscard]]
constexpr Prev prev()
const {
53 return static_cast<Prev>(Decode(kPrevBits, kPrevShift));
56 [[nodiscard]]
constexpr Next next()
const {
57 return static_cast<Next>(Decode(kNextBits, kNextShift));
60 [[nodiscard]]
constexpr size_t size()
const {
61 return Decode(kSizeBits, kSizeShift);
64 [[nodiscard]]
constexpr bool ok()
const {
return encoded_.
ok(); }
66 [[nodiscard]]
constexpr Status status()
const {
return encoded_.status(); }
73 constexpr GenericBlockResult(Status status,
79 static constexpr size_t kPrevBits = 5;
80 static constexpr size_t kPrevShift = 0;
82 static constexpr size_t kNextBits = 5;
83 static constexpr size_t kNextShift = kPrevBits;
85 static constexpr size_t kSizeBits = 10;
86 static constexpr size_t kSizeShift = kPrevBits + kNextBits;
88 static constexpr size_t Encode(
size_t value,
size_t bits,
size_t shift);
89 constexpr size_t Decode(
size_t bits,
size_t shift)
const;
91 StatusWithSize encoded_;
105template <
typename BlockType>
113 status, Prev::kUnchanged, Next::kUnchanged, 0),
119 constexpr BlockResult(BlockType* block,
Prev prev,
size_t shifted_to_prev)
120 :
BlockResult(block, prev, Next::kUnchanged, shifted_to_prev) {}
131 size_t shifted_to_prev);
133 [[nodiscard]]
constexpr BlockType* block()
const {
return block_; }
136 BlockType* block_ =
nullptr;
146 if constexpr (Hardening::kIncludesDebugChecks) {
151constexpr GenericBlockResult::GenericBlockResult(
Status status,
156 Encode(size_t(prev), kPrevBits, kPrevShift) |
157 Encode(size_t(next), kNextBits, kNextShift) |
158 Encode(size, kSizeBits, kSizeShift)) {}
160constexpr size_t GenericBlockResult::Encode(
size_t value,
163 if constexpr (Hardening::kIncludesDebugChecks) {
164 PW_ASSERT(value < (1U << bits));
166 return value << shift;
169constexpr size_t GenericBlockResult::Decode(
size_t bits,
size_t shift)
const {
170 return (encoded_.
size() >> shift) & ~(~static_cast<size_t>(0) << bits);
175template <
typename BlockType>
176constexpr BlockResult<BlockType>::BlockResult(BlockType* block,
179 size_t shifted_to_prev)
180 : internal::GenericBlockResult(
OkStatus(), prev, next, shifted_to_prev),
182 if constexpr (Hardening::kIncludesDebugChecks) {
183 block->CheckInvariants();
constexpr bool ok() const
True if status() == OkStatus().
Definition: status_with_size.h:154
constexpr size_t size() const
Definition: status_with_size.h:148
Next
Definition: result.h:45
constexpr void IgnoreUnlessStrict() const
Definition: result.h:145
Prev
Definition: result.h:36
constexpr Status OkStatus()
Definition: status.h:450