1 // Copyright 2023 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 <array> 17 #include <cstddef> 18 #include <cstdint> 19 20 #include "pw_bytes/span.h" 21 #include "pw_result/result.h" 22 23 namespace pw::allocator { 24 25 /// Associates a default-constructed type with a memory buffer. 26 /// 27 /// Although the type is arbitrary, the intended purpose of of this class is to 28 /// provide allocators with memory to use, e.g. when testing. 29 /// 30 /// This class uses composition instead of inheritance in order to allow the 31 /// wrapped type's destructor to reference the memory without risk of a 32 /// use-after-free. As a result, the specific methods of the wrapped type 33 /// are not directly accesible. Instead, they can be accessed using the `*` and 34 /// `->` operators, e.g. 35 /// 36 /// @code{.cpp} 37 /// WithBuffer<MyAllocator, 256> allocator; 38 /// allocator->MethodSpecificToMyAllocator(); 39 /// @endcode 40 /// 41 /// Note that this class does NOT initialize the allocator, since initialization 42 /// is not specified as part of the `Allocator` interface and may vary from 43 /// allocator to allocator. As a result, typical usage includes deriving a class 44 /// that initializes the wrapped allocator with the buffer in a constructor. See 45 /// `AllocatorForTest` for an example. 46 /// 47 /// @tparam T The wrapped object. 48 /// @tparam kBufferSize The size of the backing memory, in bytes. 49 /// @tparam kAlignment Buffer memory will be aligned to this alignment 50 /// boundary. 51 template <typename T, size_t kBufferSize, size_t kAlignment = 1> 52 class WithBuffer { 53 public: 54 static constexpr size_t kCapacity = kBufferSize; 55 as_bytes()56 ByteSpan as_bytes() { return buffer_; } data()57 std::byte* data() { return buffer_.data(); } size()58 size_t size() const { return buffer_.size(); } 59 60 T& operator*() { return obj_; } 61 const T& operator*() const { return obj_; } 62 63 T* operator->() { return &obj_; } 64 const T* operator->() const { return &obj_; } 65 66 private: 67 alignas(kAlignment) std::array<std::byte, kBufferSize> buffer_; 68 T obj_; 69 }; 70 71 } // namespace pw::allocator 72