diff options
Diffstat (limited to 'Ryujinx.Horizon.Common/Result.cs')
-rw-r--r-- | Ryujinx.Horizon.Common/Result.cs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/Ryujinx.Horizon.Common/Result.cs b/Ryujinx.Horizon.Common/Result.cs new file mode 100644 index 00000000..04281199 --- /dev/null +++ b/Ryujinx.Horizon.Common/Result.cs @@ -0,0 +1,118 @@ +using System; + +namespace Ryujinx.Horizon.Common +{ + public struct Result : IEquatable<Result> + { + private const int ModuleBits = 9; + private const int DescriptionBits = 13; + private const int ModuleMax = 1 << ModuleBits; + private const int DescriptionMax = 1 << DescriptionBits; + + public static Result Success { get; } = new Result(0, 0); + + public int ErrorCode { get; } + + public bool IsSuccess => ErrorCode == 0; + public bool IsFailure => ErrorCode != 0; + + public int Module => ErrorCode & (ModuleMax - 1); + public int Description => (ErrorCode >> ModuleBits) & (DescriptionMax - 1); + + public string PrintableResult => $"{2000 + Module:D4}-{Description:D4}"; + + public Result(int module, int description) + { + if ((uint)module >= ModuleMax) + { + throw new ArgumentOutOfRangeException(nameof(module)); + } + + if ((uint)description >= DescriptionMax) + { + throw new ArgumentOutOfRangeException(nameof(description)); + } + + ErrorCode = module | (description << ModuleBits); + } + + public override bool Equals(object obj) + { + return obj is Result result && result.Equals(this); + } + + public bool Equals(Result other) + { + return other.ErrorCode == ErrorCode; + } + + public override int GetHashCode() + { + return ErrorCode; + } + + public static bool operator ==(Result lhs, Result rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(Result lhs, Result rhs) + { + return !lhs.Equals(rhs); + } + + public bool InRange(int minInclusive, int maxInclusive) + { + return (uint)(Description - minInclusive) <= (uint)(maxInclusive - minInclusive); + } + + public void AbortOnSuccess() + { + if (IsSuccess) + { + ThrowInvalidResult(); + } + } + + public void AbortOnFailure() + { + if (this == KernelResult.ThreadTerminating) + { + throw new ThreadTerminatedException(); + } + + AbortUnless(Success); + } + + public void AbortUnless(Result result) + { + if (this != result) + { + ThrowInvalidResult(); + } + } + + public void AbortUnless(Result result, Result result2) + { + if (this != result && this != result2) + { + ThrowInvalidResult(); + } + } + + private void ThrowInvalidResult() + { + throw new InvalidResultException(this); + } + + public override string ToString() + { + if (ResultNames.TryGet(ErrorCode, out string name)) + { + return name; + } + + return PrintableResult; + } + } +} |