| // 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 |