diff --git a/src/LibHac/Result.cs b/src/LibHac/Result.cs
index 9101d813..a189c463 100644
--- a/src/LibHac/Result.cs
+++ b/src/LibHac/Result.cs
@@ -6,11 +6,17 @@ using BaseType = System.UInt32;
namespace LibHac
{
+ ///
+ /// Represents a code used to report the result of a returned function.
+ ///
[Serializable]
- [DebuggerDisplay("{ToStringWithName(),nq}")]
+ [DebuggerDisplay("{" + nameof(ToStringWithName) + "(),nq}")]
public struct Result : IEquatable
{
private const BaseType SuccessValue = default;
+ ///
+ /// The signifying success.
+ ///
public static Result Success => new Result(SuccessValue);
private static IResultLogger Logger { get; set; }
@@ -31,11 +37,20 @@ namespace LibHac
private readonly BaseType _value;
+ ///
+ /// Creates a new from the internal result value.
+ ///
+ /// The value used internally by .
public Result(BaseType value)
{
_value = GetBitsValue(value, ModuleBitsOffset, ModuleBitsCount + DescriptionBitsCount);
}
+ ///
+ /// Creates a new from a module and description.
+ ///
+ /// The module this result is from. Must be in the range 1 through 511.
+ /// The description value of the result. Must be in the range 0 through 8191.
public Result(int module, int description)
{
Debug.Assert(ModuleBegin <= module && module < ModuleEnd, "Invalid Module");
@@ -103,6 +118,11 @@ namespace LibHac
return resolver.TryResolveName(this, out name);
}
+ ///
+ /// If a has been set via , attempts to
+ /// return the name and error code of this , otherwise it only returns .
+ ///
+ /// If a name was found, the name and error code, otherwise just the error code.
public string ToStringWithName()
{
if (TryGetResultName(out string name))
@@ -122,11 +142,18 @@ namespace LibHac
public static bool operator ==(Result left, Result right) => left.Equals(right);
public static bool operator !=(Result left, Result right) => !left.Equals(right);
+ ///
+ /// Sets a to be called when is called in debug mode.
+ ///
public static void SetLogger(IResultLogger logger)
{
Logger = logger;
}
+ ///
+ /// Sets a that will be used by methods like
+ /// or to resolve the names of s.
+ ///
public static void SetNameResolver(IResultNameResolver nameResolver)
{
NameResolver = nameResolver;
@@ -156,13 +183,53 @@ namespace LibHac
return ((uint)value & ~(~default(BaseType) << bitsCount)) << bitsOffset;
}
+ ///
+ /// Represents a range of s.
+ /// This range is defined by a single module value and a range of description values.
+ /// See the documentation remarks for additional information.
+ ///
+ ///
+ /// Due to C# not having templates, we can't define results like Horizon and Atmosphere do.
+ /// Compared to those Result classes, this struct generates identical code and uses identical syntax.
+ ///
A Result definition should look like this: public static Result.Base PathNotFound => new Result.Base(ModuleFs, 1);
+ ///
Being a computed property like this will allow the compiler to do constant propagation to optimize comparisons.
+ ///
This is an example of how a Result should be returned from a function: return PathNotFound.Log();
+ ///
The method will return the for the specified , and
+ /// will optionally log the returned Result when running in debug mode for easier debugging. All Result logging functionality
+ /// is removed from release builds.
+ /// If the is not being used as a return value, will get the Result without logging anything.
+ ///
is used to check if a provided is contained within the range of the .
+ /// If the is a computed property as shown above, the compiler will be able to properly optimize the code.
+ /// The following pairs of lines will produce the same code given Result result;
+ ///
+ /// bool a1 = ResultFs.TargetNotFound.Includes(result); // Comparing a single value
+ /// bool a2 = result.Value == 0x7D402;
+ ///
+ /// bool b1 = ResultFs.InsufficientFreeSpace.Includes(result); // Comparing a range of values
+ /// bool b2 = return result.Module == 2 && (result.Description - 30 <= 45 - 30);
+ ///
+ /// Unfortunately RyuJIT will not automatically inline the property when the compiled CIL is 16 bytes or larger as in cases like
+ /// new Result.Base(ModuleFs, 2000, 2499). The property will need to have the aggressive inlining flag set like so:
+ /// public static Result.Base SdCardAccessFailed { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 2000, 2499); }
+ ///
public struct Base
{
private const int DescriptionEndBitsOffset = ReservedBitsOffset;
private readonly ulong _value;
+ ///
+ /// Creates a Result containing a single value.
+ ///
+ /// The module this result is from. Must be in the range 1 through 511.
+ /// The description value of the result. Must be in the range 0 through 8191.
public Base(int module, int description) : this(module, description, description) { }
+ ///
+ /// Creates a Result containing a range of values.
+ ///
+ /// The module this result is from. Must be in the range 1 through 511.
+ /// The inclusive start description value of the range. Must be in the range 0 through 8191.
+ /// The inclusive end description value of the range. Must be in the range 0 through 8191.
public Base(int module, int descriptionStart, int descriptionEnd)
{
Debug.Assert(ModuleBegin <= module && module < ModuleEnd, "Invalid Module");