rpcsx/rpcs3/Emu/RSX/Common/expected.hpp

122 lines
2.3 KiB
C++
Raw Normal View History

2023-01-03 16:26:19 +01:00
#pragma once
#include <util/types.hpp>
2023-01-09 22:07:30 +01:00
2023-01-03 16:26:19 +01:00
#include <concepts>
2023-01-09 22:07:30 +01:00
#include <string>
2023-01-03 18:31:40 +01:00
#include <utility>
2023-01-03 16:26:19 +01:00
2023-01-07 20:51:02 +01:00
namespace fmt
{
template <typename CharT, usz N, typename... Args>
static std::string format(const CharT(&)[N], const Args&...);
}
2023-01-03 16:26:19 +01:00
namespace rsx
{
namespace exception_utils
{
enum soft_exception_error_code
{
none = 0,
range_exception = 1,
invalid_enum = 2
};
struct soft_exception_t
{
soft_exception_error_code error = soft_exception_error_code::none;
soft_exception_t() = default;
soft_exception_t(soft_exception_error_code code)
: error(code) {}
bool empty() const
{
return error == soft_exception_error_code::none;
}
2023-01-07 20:51:02 +01:00
std::string to_string() const
{
switch (error)
{
case soft_exception_error_code::none:
return "No error";
case soft_exception_error_code::range_exception:
return "Bad Range";
case soft_exception_error_code::invalid_enum:
return "Invalid enum";
default:
return "Unknown Error";
}
}
};
}
template <typename E>
concept ErrorType = requires (E & e)
{
{ e.empty() } -> std::same_as<bool>;
};
2023-01-03 16:26:19 +01:00
template <typename T, ErrorType E = exception_utils::soft_exception_t>
2023-01-03 16:26:19 +01:00
class expected
{
T value;
E error{};
public:
2023-01-03 18:31:40 +01:00
[[ nodiscard ]] expected(const T& value_)
2023-01-03 16:26:19 +01:00
: value(value_)
{}
2023-01-03 18:31:40 +01:00
[[ nodiscard ]] expected(const E& error_)
2023-01-03 16:26:19 +01:00
: error(error_)
2023-01-03 18:31:40 +01:00
{
ensure(!error.empty());
}
2023-01-03 16:26:19 +01:00
operator T() const
{
2023-01-03 18:31:40 +01:00
ensure(error.empty());
return value;
}
T operator *() const
{
ensure(error.empty());
2023-01-03 16:26:19 +01:00
return value;
}
2023-01-03 18:31:40 +01:00
template<typename = std::enable_if<!std::is_same_v<T, bool>>>
2023-01-03 16:26:19 +01:00
operator bool() const
{
2023-01-03 18:31:40 +01:00
return error.empty();
}
operator std::pair<T&, E&>() const
{
return { value, error };
}
bool operator == (const T& other) const
{
return error.empty() && value == other;
2023-01-03 16:26:19 +01:00
}
2023-01-07 20:51:02 +01:00
std::string to_string() const
{
if (error.empty())
{
return fmt::format("%s", value);
}
if constexpr (std::is_same_v<E, exception_utils::soft_exception_t>)
{
return error.to_string();
}
return fmt::format("%s", error);
}
2023-01-03 16:26:19 +01:00
};
}