|  | // Copyright Microsoft and CHERIoT Contributors. | 
|  | // SPDX-License-Identifier: MIT | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <cdefs.h> | 
|  | #include <limits> | 
|  | #include <stddef.h> | 
|  | #include <stdint.h> | 
|  | #include <type_traits> | 
|  |  | 
|  | namespace utils | 
|  | { | 
|  | constexpr size_t bytes2bits(size_t in) | 
|  | { | 
|  | return in * __CHAR_BIT__; | 
|  | } | 
|  |  | 
|  | template<size_t N> | 
|  | constexpr size_t log2() | 
|  | { | 
|  | static_assert(N > 0 && (N & (N - 1)) == 0); | 
|  |  | 
|  | return 1U + log2<(N >> 1)>(); | 
|  | } | 
|  | template<> | 
|  | constexpr size_t log2<1U>() | 
|  | { | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | template<typename T, size_t N> | 
|  | constexpr size_t array_size(T (&a)[N]) | 
|  | { | 
|  | return N; | 
|  | } | 
|  |  | 
|  | class NoCopyNoMove | 
|  | { | 
|  | public: | 
|  | NoCopyNoMove()                     = default; | 
|  | NoCopyNoMove(const NoCopyNoMove &) = delete; | 
|  | NoCopyNoMove &operator=(const NoCopyNoMove &) = delete; | 
|  | NoCopyNoMove(NoCopyNoMove &&)                 = delete; | 
|  | NoCopyNoMove &operator=(NoCopyNoMove &&) = delete; | 
|  | ~NoCopyNoMove()                          = default; | 
|  | }; | 
|  |  | 
|  | /** | 
|  | * A helper class modelled on `std::optional` that represents an optional | 
|  | * `T&`.  This is stored as a pointer with `nullptr` representing the | 
|  | * not-present version. | 
|  | * | 
|  | * Unlike `std::optional`, this intentionally omits the APIs that make it | 
|  | * possible to access the value without checking that it is present. | 
|  | * | 
|  | * This is intended to be used as an alternative to using bare pointers to | 
|  | * represent `T& | None`. | 
|  | */ | 
|  | template<typename T> | 
|  | class OptionalReference | 
|  | { | 
|  | /// The pointer to the real value | 
|  | T *pointer; | 
|  |  | 
|  | public: | 
|  | /** | 
|  | * Construct the optional wrapper from a real value. | 
|  | */ | 
|  | __always_inline OptionalReference(T &value) : pointer(&value) {} | 
|  |  | 
|  | /** | 
|  | * Construct the optional wrapper from not-present value. | 
|  | */ | 
|  | OptionalReference(std::nullptr_t) : pointer(nullptr) {} | 
|  |  | 
|  | /** | 
|  | * Returns a copy of the wrapped value if present or the provided | 
|  | * default value if not. | 
|  | */ | 
|  | T value_or(T defaultValue) | 
|  | { | 
|  | if (pointer == nullptr) | 
|  | { | 
|  | return defaultValue; | 
|  | } | 
|  | return *pointer; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * Returns a reference to the wrapped value if present or the provided | 
|  | * default value if not. | 
|  | */ | 
|  | T &value_or(T &defaultValue) | 
|  | { | 
|  | if (pointer == nullptr) | 
|  | { | 
|  | return defaultValue; | 
|  | } | 
|  | return *pointer; | 
|  | } | 
|  |  | 
|  | /** | 
|  | * If this object holds a value then apply `f` to it and return the | 
|  | * result, otherwise return the result of converting nullptr to the | 
|  | * return type of `f`. | 
|  | */ | 
|  | __always_inline auto and_then(auto &&f) | 
|  | { | 
|  | using Result = decltype(f(std::declval<T &>())); | 
|  | if constexpr (std::is_same_v<void, Result>) | 
|  | { | 
|  | if (pointer != nullptr) | 
|  | { | 
|  | f(*pointer); | 
|  | } | 
|  | return; | 
|  | } | 
|  | else | 
|  | { | 
|  | if (pointer != nullptr) | 
|  | { | 
|  | return f(*pointer); | 
|  | } | 
|  | return Result{nullptr}; | 
|  | } | 
|  | } | 
|  | }; | 
|  |  | 
|  | } // namespace utils |