mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 09:21:57 -05:00
AK: Add a functional-style Optional::map(mapper_function) API
This allows the user to transform the contents of the optional (if any exists), without manually unwrapping and then rewrapping it. This is needed by the Jakt runtime.
This commit is contained in:
parent
5809b4aafa
commit
cc948d06a6
1 changed files with 79 additions and 0 deletions
|
@ -9,11 +9,30 @@
|
|||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/StdLibExtras.h>
|
||||
#include <AK/Try.h>
|
||||
#include <AK/Types.h>
|
||||
#include <AK/kmalloc.h>
|
||||
|
||||
namespace AK {
|
||||
|
||||
namespace Detail {
|
||||
template<auto condition, typename T>
|
||||
struct ConditionallyResultType;
|
||||
|
||||
template<typename T>
|
||||
struct ConditionallyResultType<true, T> {
|
||||
using Type = typename T::ResultType;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ConditionallyResultType<false, T> {
|
||||
using Type = T;
|
||||
};
|
||||
}
|
||||
|
||||
template<auto condition, typename T>
|
||||
using ConditionallyResultType = typename Detail::ConditionallyResultType<condition, T>::Type;
|
||||
|
||||
// NOTE: If you're here because of an internal compiler error in GCC 10.3.0+,
|
||||
// it's because of the following bug:
|
||||
//
|
||||
|
@ -214,6 +233,36 @@ public:
|
|||
ALWAYS_INLINE T const* operator->() const { return &value(); }
|
||||
ALWAYS_INLINE T* operator->() { return &value(); }
|
||||
|
||||
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
|
||||
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
|
||||
{
|
||||
if constexpr (IsErrorOr) {
|
||||
if (m_has_value)
|
||||
return OptionalType { TRY(mapper(value())) };
|
||||
return OptionalType {};
|
||||
} else {
|
||||
if (m_has_value)
|
||||
return OptionalType { mapper(value()) };
|
||||
|
||||
return OptionalType {};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
|
||||
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
|
||||
{
|
||||
if constexpr (IsErrorOr) {
|
||||
if (m_has_value)
|
||||
return OptionalType { TRY(mapper(value())) };
|
||||
return OptionalType {};
|
||||
} else {
|
||||
if (m_has_value)
|
||||
return OptionalType { mapper(value()) };
|
||||
|
||||
return OptionalType {};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
alignas(T) u8 m_storage[sizeof(T)];
|
||||
bool m_has_value { false };
|
||||
|
@ -375,6 +424,36 @@ public:
|
|||
return {};
|
||||
}
|
||||
|
||||
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
|
||||
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper)
|
||||
{
|
||||
if constexpr (IsErrorOr) {
|
||||
if (m_pointer != nullptr)
|
||||
return OptionalType { TRY(mapper(value())) };
|
||||
return OptionalType {};
|
||||
} else {
|
||||
if (m_pointer != nullptr)
|
||||
return OptionalType { mapper(value()) };
|
||||
|
||||
return OptionalType {};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F, typename MappedType = decltype(declval<F>()(declval<T&>())), auto IsErrorOr = IsSpecializationOf<MappedType, ErrorOr>, typename OptionalType = Optional<ConditionallyResultType<IsErrorOr, MappedType>>>
|
||||
ALWAYS_INLINE Conditional<IsErrorOr, ErrorOr<OptionalType>, OptionalType> map(F&& mapper) const
|
||||
{
|
||||
if constexpr (IsErrorOr) {
|
||||
if (m_pointer != nullptr)
|
||||
return OptionalType { TRY(mapper(value())) };
|
||||
return OptionalType {};
|
||||
} else {
|
||||
if (m_pointer != nullptr)
|
||||
return OptionalType { mapper(value()) };
|
||||
|
||||
return OptionalType {};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RemoveReference<T>* m_pointer { nullptr };
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue