summaryrefslogtreecommitdiffstats
path: root/src/core/hle/result.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/result.h')
-rw-r--r--src/core/hle/result.h81
1 files changed, 63 insertions, 18 deletions
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 3807b9aa8..47a1b829b 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -1,6 +1,5 @@
-// Copyright 2014 Citra Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: 2014 Citra Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -112,15 +111,16 @@ enum class ErrorModule : u32 {
};
/// Encapsulates a Horizon OS error code, allowing it to be separated into its constituent fields.
-union ResultCode {
+union Result {
u32 raw;
BitField<0, 9, ErrorModule> module;
BitField<9, 13, u32> description;
- constexpr explicit ResultCode(u32 raw_) : raw(raw_) {}
+ Result() = default;
+ constexpr explicit Result(u32 raw_) : raw(raw_) {}
- constexpr ResultCode(ErrorModule module_, u32 description_)
+ constexpr Result(ErrorModule module_, u32 description_)
: raw(module.FormatValue(module_) | description.FormatValue(description_)) {}
[[nodiscard]] constexpr bool IsSuccess() const {
@@ -131,19 +131,20 @@ union ResultCode {
return !IsSuccess();
}
};
+static_assert(std::is_trivial_v<Result>);
-[[nodiscard]] constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
+[[nodiscard]] constexpr bool operator==(const Result& a, const Result& b) {
return a.raw == b.raw;
}
-[[nodiscard]] constexpr bool operator!=(const ResultCode& a, const ResultCode& b) {
+[[nodiscard]] constexpr bool operator!=(const Result& a, const Result& b) {
return !operator==(a, b);
}
// Convenience functions for creating some common kinds of errors:
-/// The default success `ResultCode`.
-constexpr ResultCode ResultSuccess(0);
+/// The default success `Result`.
+constexpr Result ResultSuccess(0);
/**
* Placeholder result code used for unknown error codes.
@@ -151,10 +152,52 @@ constexpr ResultCode ResultSuccess(0);
* @note This should only be used when a particular error code
* is not known yet.
*/
-constexpr ResultCode ResultUnknown(UINT32_MAX);
+constexpr Result ResultUnknown(UINT32_MAX);
/**
- * This is an optional value type. It holds a `ResultCode` and, if that code is ResultSuccess, it
+ * A ResultRange defines an inclusive range of error descriptions within an error module.
+ * This can be used to check whether the description of a given Result falls within the range.
+ * The conversion function returns a Result with its description set to description_start.
+ *
+ * An example of how it could be used:
+ * \code
+ * constexpr ResultRange ResultCommonError{ErrorModule::Common, 0, 9999};
+ *
+ * Result Example(int value) {
+ * const Result result = OtherExample(value);
+ *
+ * // This will only evaluate to true if result.module is ErrorModule::Common and
+ * // result.description is in between 0 and 9999 inclusive.
+ * if (ResultCommonError.Includes(result)) {
+ * // This returns Result{ErrorModule::Common, 0};
+ * return ResultCommonError;
+ * }
+ *
+ * return ResultSuccess;
+ * }
+ * \endcode
+ */
+class ResultRange {
+public:
+ consteval ResultRange(ErrorModule module, u32 description_start, u32 description_end_)
+ : code{module, description_start}, description_end{description_end_} {}
+
+ [[nodiscard]] constexpr operator Result() const {
+ return code;
+ }
+
+ [[nodiscard]] constexpr bool Includes(Result other) const {
+ return code.module == other.module && code.description <= other.description &&
+ other.description <= description_end;
+ }
+
+private:
+ Result code;
+ u32 description_end;
+};
+
+/**
+ * This is an optional value type. It holds a `Result` and, if that code is ResultSuccess, it
* also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying
* to access the inner value with operator* is undefined behavior and will assert with Unwrap().
* Users of this class must be cognizant to check the status of the ResultVal with operator bool(),
@@ -165,7 +208,7 @@ constexpr ResultCode ResultUnknown(UINT32_MAX);
* ResultVal<int> Frobnicate(float strength) {
* if (strength < 0.f || strength > 1.0f) {
* // Can't frobnicate too weakly or too strongly
- * return ResultCode{ErrorModule::Common, 1};
+ * return Result{ErrorModule::Common, 1};
* } else {
* // Frobnicated! Give caller a cookie
* return 42;
@@ -188,7 +231,9 @@ class ResultVal {
public:
constexpr ResultVal() : expected{} {}
- constexpr ResultVal(ResultCode code) : expected{Common::Unexpected(code)} {}
+ constexpr ResultVal(Result code) : expected{Common::Unexpected(code)} {}
+
+ constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {}
template <typename U>
constexpr ResultVal(U&& val) : expected{std::forward<U>(val)} {}
@@ -208,7 +253,7 @@ public:
return expected.has_value();
}
- [[nodiscard]] constexpr ResultCode Code() const {
+ [[nodiscard]] constexpr Result Code() const {
return expected.has_value() ? ResultSuccess : expected.error();
}
@@ -275,8 +320,8 @@ public:
}
private:
- // TODO: Replace this with std::expected once it is standardized in the STL.
- Common::Expected<T, ResultCode> expected;
+ // TODO (Morph): Replace this with C++23 std::expected.
+ Common::Expected<T, Result> expected;
};
/**
@@ -293,7 +338,7 @@ private:
target = std::move(*CONCAT2(check_result_L, __LINE__))
/**
- * Analogous to CASCADE_RESULT, but for a bare ResultCode. The code will be propagated if
+ * Analogous to CASCADE_RESULT, but for a bare Result. The code will be propagated if
* non-success, or discarded otherwise.
*/
#define CASCADE_CODE(source) \