#pragma once #include "memory/pointer.h" #include "util/number.h" #include "util/utility.h" // Ported from legacy/CrackOS3 (include/features/optional.h), adapted to the // PrOSess freestanding environment: uses the in-tree move/forward (util/utility.h) // instead of . The CrackOS3 value_or_panic() helper is omitted because // there is no global panic() in this tree yet. struct nullopt_t {}; inline constexpr nullopt_t nullopt{}; template struct optional { private: char buffer[sizeof(T)]; bool initialized; void destroy() { if (initialized) { ((T*)buffer)->~T(); initialized = false; } } public: using value_type = T; constexpr optional() : initialized(false) {} constexpr optional(nullopt_t) : initialized(false) {} optional(const T& value) : initialized(true) { new (buffer) T(value); } optional(T&& value) : initialized(true) { new (buffer) T(move(value)); } optional(const optional& other) : initialized(other.initialized) { if (initialized) { new (buffer) T(*other); } } optional(optional&& other) : initialized(other.initialized) { if (initialized) { new (buffer) T(move(*other)); } other.initialized = false; } ~optional() { destroy(); } T* operator->() { return (T*)buffer; } T& operator*() { return *((T*)buffer); } const T* operator->() const { return (const T*)buffer; } const T& operator*() const { return *((const T*)buffer); } optional& operator=(const optional& other) { if (this == &other) return *this; destroy(); if (other.initialized) { new (buffer) T(*other); initialized = true; } return *this; } optional& operator=(optional&& other) noexcept { if (this == &other) return *this; destroy(); if (other.initialized) { new (buffer) T(move(*other)); initialized = true; } other.initialized = false; return *this; } [[nodiscard]] bool has_value() const { return initialized; } T& value() { return *((T*)buffer); } const T& value() const { return *((const T*)buffer); } template T value_or_create(Func func, ArgT... args) { if (initialized) { return value(); } else { return func(args...); } } template T value_or_create(Func func, ArgT... args) const { if (initialized) { return value(); } else { return func(args...); } } const T& value_or(const T& default_value) const { if (initialized) { return *((const T*)buffer); } else { return default_value; } } operator bool() const { return initialized; } bool operator!() const { return !initialized; } template auto map(Func&& func) -> optional { if (initialized) { return func(value()); } else { return {}; } } template auto map(Func&& func) const -> optional { if (initialized) { return func(value()); } else { return {}; } } template optional or_else(Func&& func) const { if (initialized) { return *this; } return func(); } template auto bind(Func&& func) -> decltype(func(value())) { if (initialized) { return func(value()); } else { return {}; } } template auto bind(Func&& func) const -> decltype(func(value())) { if (initialized) { return func(value()); } else { return {}; } } }; template struct as_optional { using type = optional; }; template struct as_optional> { using type = optional; }; template using as_optional_t = typename as_optional::type; template auto lift(Func func) { return [func](const auto&... optionals) -> as_optional_t { if ((optionals.has_value() && ...)) { return func(optionals.value()...); } return nullopt; }; }