diff --git a/src/LibHac/Boot/Package1.cs b/src/LibHac/Boot/Package1.cs index 674e5b23..c49db99d 100644 --- a/src/LibHac/Boot/Package1.cs +++ b/src/LibHac/Boot/Package1.cs @@ -335,7 +335,7 @@ namespace LibHac.Boot private bool VerifyPk11Sizes() { - Assert.True(IsDecrypted); + Assert.SdkRequires(IsDecrypted); int pk11Size = Unsafe.SizeOf() + GetSectionSize(Package1Section.WarmBoot) + GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor); diff --git a/src/LibHac/Common/Keys/ExternalKeyReader.cs b/src/LibHac/Common/Keys/ExternalKeyReader.cs index 242ab16d..89acb583 100644 --- a/src/LibHac/Common/Keys/ExternalKeyReader.cs +++ b/src/LibHac/Common/Keys/ExternalKeyReader.cs @@ -493,8 +493,8 @@ namespace LibHac.Common.Keys // of the file which will be treated as the end of a line. if (state == ReaderState.Value || state == ReaderState.WhiteSpace2) { - Assert.True(i == buffer.Length); - Assert.True(reader.HasReadEndOfFile); + Assert.SdkEqual(i, buffer.Length); + Assert.SdkAssert(reader.HasReadEndOfFile); // WhiteSpace2 will have already set this value if (state == ReaderState.Value) @@ -506,8 +506,8 @@ namespace LibHac.Common.Keys // Same situation as the two above states if (state == ReaderState.Comment) { - Assert.True(i == buffer.Length); - Assert.True(reader.HasReadEndOfFile); + Assert.SdkEqual(i, buffer.Length); + Assert.SdkAssert(reader.HasReadEndOfFile); keyLength = i - keyOffset; state = ReaderState.CommentSuccess; @@ -516,8 +516,8 @@ namespace LibHac.Common.Keys // Same as the above states except the final line was empty or whitespace. if (state == ReaderState.Initial) { - Assert.True(i == buffer.Length); - Assert.True(reader.HasReadEndOfFile); + Assert.SdkEqual(i, buffer.Length); + Assert.SdkAssert(reader.HasReadEndOfFile); reader.BufferPos = i; return ReaderStatus.NoKeyRead; diff --git a/src/LibHac/Common/Keys/KeyInfo.cs b/src/LibHac/Common/Keys/KeyInfo.cs index 5c0bc922..3fb39804 100644 --- a/src/LibHac/Common/Keys/KeyInfo.cs +++ b/src/LibHac/Common/Keys/KeyInfo.cs @@ -48,7 +48,7 @@ namespace LibHac.Common.Keys public KeyInfo(int group, KeyType type, string name, KeyGetter retrieveFunc) { - Assert.True(IsKeyTypeValid(type)); + Assert.SdkRequires(IsKeyTypeValid(type)); Name = name; RangeType = KeyRangeType.Single; @@ -61,7 +61,7 @@ namespace LibHac.Common.Keys public KeyInfo(int group, KeyType type, string name, byte rangeStart, byte rangeEnd, KeyGetter retrieveFunc) { - Assert.True(IsKeyTypeValid(type)); + Assert.SdkRequires(IsKeyTypeValid(type)); Name = name; RangeType = KeyRangeType.Range; @@ -87,7 +87,7 @@ namespace LibHac.Common.Keys private bool MatchesSingle(ReadOnlySpan keyName, out bool isDev) { - Assert.Equal((int)KeyRangeType.Single, (int)RangeType); + Assert.SdkRequiresEqual((int)KeyRangeType.Single, (int)RangeType); isDev = false; @@ -113,7 +113,7 @@ namespace LibHac.Common.Keys private bool MatchesRangedKey(ReadOnlySpan keyName, ref int keyIndex, out bool isDev) { - Assert.Equal((int)KeyRangeType.Range, (int)RangeType); + Assert.SdkRequiresEqual((int)KeyRangeType.Range, (int)RangeType); isDev = false; diff --git a/src/LibHac/Common/U8StringBuilder.cs b/src/LibHac/Common/U8StringBuilder.cs index b7e40834..22614c1f 100644 --- a/src/LibHac/Common/U8StringBuilder.cs +++ b/src/LibHac/Common/U8StringBuilder.cs @@ -173,7 +173,7 @@ namespace LibHac.Common // Grow the buffer and try again. The buffer size will at least double each time it grows, // so asking for 0x10 additional bytes actually gets us more than that. Grow(availableBuffer.Length + 0x10); - Assert.True(Length + availableBuffer.Length < Capacity); + Assert.SdkGreater(Capacity, Length + availableBuffer.Length); } PadOutput(bytesWritten); @@ -212,7 +212,7 @@ namespace LibHac.Common } Grow(availableBuffer.Length + 0x10); - Assert.True(Length + availableBuffer.Length < Capacity); + Assert.SdkGreater(Capacity, Length + availableBuffer.Length); } PadOutput(bytesWritten); @@ -251,7 +251,7 @@ namespace LibHac.Common } Grow(availableBuffer.Length + 0x10); - Assert.True(Length + availableBuffer.Length < Capacity); + Assert.SdkGreater(Capacity, Length + availableBuffer.Length); } PadOutput(bytesWritten); @@ -290,7 +290,7 @@ namespace LibHac.Common } Grow(availableBuffer.Length + 0x10); - Assert.True(Length + availableBuffer.Length < Capacity); + Assert.SdkGreater(Capacity, Length + availableBuffer.Length); } PadOutput(bytesWritten); @@ -368,7 +368,7 @@ namespace LibHac.Common if (!hasCapacity && AutoExpand) { Grow(requiredAfterPadding); - Assert.True(HasCapacity(Length + requiredAfterPadding)); + Assert.SdkAssert(HasCapacity(Length + requiredAfterPadding)); hasCapacity = true; } diff --git a/src/LibHac/Crypto/Aes.cs b/src/LibHac/Crypto/Aes.cs index 13ac315e..4e642d90 100644 --- a/src/LibHac/Crypto/Aes.cs +++ b/src/LibHac/Crypto/Aes.cs @@ -296,7 +296,7 @@ namespace LibHac.Crypto private static void LeftShiftBytes(ReadOnlySpan input, Span output) { - Assert.True(output.Length >= input.Length); + Assert.SdkRequiresGreaterEqual(output.Length, input.Length); byte carry = 0; diff --git a/src/LibHac/Diag/Abort.cs b/src/LibHac/Diag/Abort.cs index 5d236f7d..027eb71d 100644 --- a/src/LibHac/Diag/Abort.cs +++ b/src/LibHac/Diag/Abort.cs @@ -3,8 +3,32 @@ using System.Runtime.CompilerServices; namespace LibHac.Diag { + public ref struct AbortInfo + { + public AbortReason AbortReason; + public string Message; + public string Condition; + public string FunctionName; + public string FileName; + public int LineNumber; + } + + public enum AbortReason + { + SdkAssert, + SdkRequires, + UserAssert, + Abort, + UnexpectedDefault + } + public static class Abort { + internal static void InvokeAbortObserver(in AbortInfo abortInfo) + { + // Todo + } + [DoesNotReturn] public static void DoAbort(Result result, string message = null) { diff --git a/src/LibHac/Diag/Assert.cs b/src/LibHac/Diag/Assert.cs index 5bf60a52..8b50fa19 100644 --- a/src/LibHac/Diag/Assert.cs +++ b/src/LibHac/Diag/Assert.cs @@ -1,86 +1,1093 @@ using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using LibHac.Diag.Impl; +using LibHac.Os; namespace LibHac.Diag { + public ref struct AssertionInfo + { + public AssertionType AssertionType; + public string Message; + public string Condition; + public string FunctionName; + public string FileName; + public int LineNumber; + } + + public enum AssertionType + { + SdkAssert, + SdkRequires, + UserAssert + } + + public enum AssertionFailureOperation + { + Abort, + Continue + } + + public delegate AssertionFailureOperation AssertionFailureHandler(in AssertionInfo assertionInfo); + public static class Assert { - [Conditional("DEBUG")] - public static void True([DoesNotReturnIf(false)] bool condition, string message = null) + private const string AssertCondition = "ENABLE_ASSERTS"; + + private static SdkMutexType _mutex = InitMutex(); + private static AssertionFailureHandler _assertionFailureHandler = DefaultAssertionFailureHandler; + + private static SdkMutexType InitMutex() + { + var mutex = new SdkMutexType(); + mutex.Initialize(); + return mutex; + } + + private static AbortReason ToAbortReason(AssertionType assertionType) + { + switch (assertionType) + { + case AssertionType.SdkAssert: return AbortReason.SdkAssert; + case AssertionType.SdkRequires: return AbortReason.SdkRequires; + case AssertionType.UserAssert: return AbortReason.UserAssert; + default: return AbortReason.Abort; + } + } + + private static AssertionFailureOperation DefaultAssertionFailureHandler(in AssertionInfo assertionInfo) + { + return AssertionFailureOperation.Abort; + } + + private static void ExecuteAssertionFailureOperation(AssertionFailureOperation operation, + in AssertionInfo assertionInfo) + { + switch (operation) + { + case AssertionFailureOperation.Abort: + var abortInfo = new AbortInfo + { + AbortReason = ToAbortReason(assertionInfo.AssertionType), + Message = assertionInfo.Message, + Condition = assertionInfo.Condition, + FunctionName = assertionInfo.FunctionName, + FileName = assertionInfo.FileName, + LineNumber = assertionInfo.LineNumber + }; + + Abort.InvokeAbortObserver(in abortInfo); + Abort.DoAbort(abortInfo.Message); + break; + case AssertionFailureOperation.Continue: + return; + default: + Abort.DoAbort("Unknown AssertionFailureOperation"); + break; + } + } + + private static void InvokeAssertionFailureHandler(in AssertionInfo assertionInfo) + { + AssertionFailureOperation operation = _assertionFailureHandler(in assertionInfo); + ExecuteAssertionFailureOperation(operation, in assertionInfo); + } + + internal static void OnAssertionFailure(AssertionType assertionType, string condition, string functionName, + string fileName, int lineNumber) + { + OnAssertionFailure(assertionType, condition, functionName, fileName, lineNumber, string.Empty); + } + + internal static void OnAssertionFailure(AssertionType assertionType, string condition, string functionName, + string fileName, int lineNumber, string message) + { + // Invalidate the IPC message buffer and call SynchronizePreemptionState if necessary + // nn::diag::detail::PrepareAbort(); + + if (_mutex.IsLockedByCurrentThread()) + Abort.DoAbort(); + + using ScopedLock lk = ScopedLock.Lock(ref _mutex); + + var assertionInfo = new AssertionInfo + { + AssertionType = assertionType, + Message = message, + Condition = condition, + FunctionName = functionName, + FileName = fileName, + LineNumber = lineNumber + }; + + InvokeAssertionFailureHandler(in assertionInfo); + } + + public static void SetAssertionFailureHandler(AssertionFailureHandler assertionHandler) + { + _assertionFailureHandler = assertionHandler; + } + + // --------------------------------------------------------------------- + // True + // --------------------------------------------------------------------- + + private static void TrueImpl(AssertionType assertionType, bool condition, string conditionText, string message, + string functionName, string fileName, int lineNumber) { if (condition) return; - if (string.IsNullOrWhiteSpace(message)) - { - throw new LibHacException("Assertion failed."); - } - - throw new LibHacException($"Assertion failed: {message}"); + OnAssertionFailure(assertionType, conditionText, functionName, fileName, lineNumber, message); } - [Conditional("DEBUG")] - public static void False([DoesNotReturnIf(true)] bool condition, string message = null) + [Conditional(AssertCondition)] + public static void True([DoesNotReturnIf(false)] bool condition, + string message = "", + [CallerArgumentExpression("condition")] string conditionText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) { - if (!condition) + TrueImpl(AssertionType.UserAssert, condition, conditionText, message, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void SdkAssert([DoesNotReturnIf(false)] bool condition, + string message = "", + [CallerArgumentExpression("condition")] string conditionText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + TrueImpl(AssertionType.SdkAssert, condition, conditionText, message, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void SdkRequires([DoesNotReturnIf(false)] bool condition, + string message = "", + [CallerArgumentExpression("condition")] string conditionText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + TrueImpl(AssertionType.SdkRequires, condition, conditionText, message, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Not null + // --------------------------------------------------------------------- + + private static void NotNullImpl(AssertionType assertionType, [NotNull] T value, string valueText, + string functionName, string fileName, int lineNumber) where T : class + { + if (AssertImpl.NotNull(value)) return; - if (string.IsNullOrWhiteSpace(message)) - { - throw new LibHacException("Assertion failed."); - } - - throw new LibHacException($"Assertion failed: {message}"); + AssertImpl.InvokeAssertionNotNull(assertionType, valueText, functionName, fileName, lineNumber); } - [Conditional("DEBUG")] - public static void Null([NotNull] T item) where T : class + [Conditional(AssertCondition)] + public static void NotNull([NotNull] T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : class { - if (!(item is null)) - { - throw new LibHacException("Null assertion failed."); - } + NotNullImpl(AssertionType.UserAssert, value, valueText, functionName, fileName, lineNumber); } - [Conditional("DEBUG")] - public static void NotNull([NotNull] T item) where T : class + [Conditional(AssertCondition)] + internal static void SdkNotNull([NotNull] T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : class { - if (item is null) - { - throw new LibHacException("Not-null assertion failed."); - } + NotNullImpl(AssertionType.SdkAssert, value, valueText, functionName, fileName, lineNumber); } - [Conditional("DEBUG")] - public static void InRange(int value, int lowerInclusive, int upperExclusive) + [Conditional(AssertCondition)] + internal static void SdkRequiresNotNull([NotNull] T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : class { - InRange((long)value, lowerInclusive, upperExclusive); + NotNullImpl(AssertionType.SdkRequires, value, valueText, functionName, fileName, lineNumber); } - [Conditional("DEBUG")] - public static void InRange(long value, long lowerInclusive, long upperExclusive) + // --------------------------------------------------------------------- + // Not null ref + // --------------------------------------------------------------------- + + private static void NotNullImpl(AssertionType assertionType, [NotNull] ref T value, string valueText, + string functionName, string fileName, int lineNumber) { - if (value < lowerInclusive || value >= upperExclusive) - { - throw new LibHacException($"Value {value} is not in the range {lowerInclusive} to {upperExclusive}"); - } + if (AssertImpl.NotNull(ref value)) + return; + + AssertImpl.InvokeAssertionNotNull(assertionType, valueText, functionName, fileName, lineNumber); } - public static void Equal(T value1, T value2) where T : IEquatable + [Conditional(AssertCondition)] + public static void NotNull([NotNull] ref T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) { - if (!value1.Equals(value2)) - { - throw new LibHacException($"Values were not equal: {value1}, {value2}"); - } + NotNullImpl(AssertionType.UserAssert, ref value, valueText, functionName, fileName, lineNumber); } - public static void NotEqual(T value1, T value2) where T : IEquatable + [Conditional(AssertCondition)] + internal static void SdkNotNull([NotNull] ref T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) { - if (value1.Equals(value2)) - { - throw new LibHacException($"Values should not be equal: {value1}, {value2}"); - } + NotNullImpl(AssertionType.SdkAssert, ref value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNotNull([NotNull] ref T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.SdkRequires, ref value, valueText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Not null out + // --------------------------------------------------------------------- + + private static void NotNullOutImpl(AssertionType assertionType, [NotNull] out T value, string valueText, + string functionName, string fileName, int lineNumber) + { + Unsafe.SkipInit(out value); + +#if ENABLE_ASSERTS + if (!Unsafe.IsNullRef(ref value)) + return; + + AssertImpl.InvokeAssertionNotNull(assertionType, valueText, functionName, fileName, lineNumber); +#endif + } + + public static void NotNullOut([NotNull] out T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullOutImpl(AssertionType.UserAssert, out value, valueText, functionName, fileName, lineNumber); + } + + internal static void SdkNotNullOut([NotNull] out T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullOutImpl(AssertionType.SdkAssert, out value, valueText, functionName, fileName, lineNumber); + } + + internal static void SdkRequiresNotNullOut([NotNull] out T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullOutImpl(AssertionType.SdkRequires, out value, valueText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Not null span + // --------------------------------------------------------------------- + + private static void NotNullImpl(AssertionType assertionType, [NotNull] Span value, + string valueText, string functionName, string fileName, int lineNumber) + { + if (AssertImpl.NotNull(value)) + return; + + AssertImpl.InvokeAssertionNotNull(assertionType, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void NotNull([NotNull] Span value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.UserAssert, value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkNotNull([NotNull] Span value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.SdkAssert, value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNotNull([NotNull] Span value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.SdkRequires, value, valueText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Not null read-only span + // --------------------------------------------------------------------- + + private static void NotNullImpl(AssertionType assertionType, [NotNull] ReadOnlySpan value, + string valueText, string functionName, string fileName, int lineNumber) + { + if (AssertImpl.NotNull(value)) + return; + + AssertImpl.InvokeAssertionNotNull(assertionType, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void NotNull([NotNull] ReadOnlySpan value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.UserAssert, value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkNotNull([NotNull] ReadOnlySpan value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.SdkAssert, value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNotNull([NotNull] ReadOnlySpan value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NotNullImpl(AssertionType.SdkRequires, value, valueText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Null + // --------------------------------------------------------------------- + + private static void NullImpl(AssertionType assertionType, T value, string valueText, + string functionName, string fileName, int lineNumber) where T : class + { + if (AssertImpl.Null(value)) + return; + + AssertImpl.InvokeAssertionNull(assertionType, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void Null(T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] + int lineNumber = 0) + where T : class + { + NullImpl(AssertionType.UserAssert, value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkNull(T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : class + { + NullImpl(AssertionType.SdkAssert, value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNull(T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : class + { + NullImpl(AssertionType.SdkRequires, value, valueText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Null ref + // --------------------------------------------------------------------- + + private static void NullImpl(AssertionType assertionType, ref T value, string valueText, + string functionName, string fileName, int lineNumber) + { + if (AssertImpl.Null(ref value)) + return; + + AssertImpl.InvokeAssertionNull(assertionType, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void Null(ref T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NullImpl(AssertionType.UserAssert, ref value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkNull(ref T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NullImpl(AssertionType.SdkAssert, ref value, valueText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNull(ref T value, + [CallerArgumentExpression("value")] string valueText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + NullImpl(AssertionType.SdkRequires, ref value, valueText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // In range + // --------------------------------------------------------------------- + + private static void InRangeImpl(AssertionType assertionType, int value, int lower, int upper, string valueText, + string lowerText, string upperText, string functionName, string fileName, int lineNumber) + { + if (AssertImpl.WithinRange(value, lower, upper)) + return; + + AssertImpl.InvokeAssertionInRange(assertionType, value, lower, upper, valueText, lowerText, upperText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void InRange(int value, int lowerInclusive, int upperExclusive, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("lowerInclusive")] string lowerInclusiveText = "", + [CallerArgumentExpression("upperExclusive")] string upperExclusiveText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + InRangeImpl(AssertionType.UserAssert, value, lowerInclusive, upperExclusive, valueText, lowerInclusiveText, + upperExclusiveText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkInRange(int value, int lowerInclusive, int upperExclusive, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("lowerInclusive")] string lowerInclusiveText = "", + [CallerArgumentExpression("upperExclusive")] string upperExclusiveText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + InRangeImpl(AssertionType.SdkAssert, value, lowerInclusive, upperExclusive, valueText, lowerInclusiveText, + upperExclusiveText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresInRange(int value, int lowerInclusive, int upperExclusive, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("lowerInclusive")] string lowerInclusiveText = "", + [CallerArgumentExpression("upperExclusive")] string upperExclusiveText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + InRangeImpl(AssertionType.SdkRequires, value, lowerInclusive, upperExclusive, valueText, lowerInclusiveText, + upperExclusiveText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Within min-max int + // --------------------------------------------------------------------- + + private static void WithinMinMaxImpl(AssertionType assertionType, int value, int min, int max, string valueText, + string minText, string maxText, string functionName, string fileName, int lineNumber) + { + if (AssertImpl.WithinMinMax(value, min, max)) + return; + + AssertImpl.InvokeAssertionWithinMinMax(assertionType, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void WithinMinMax(int value, int min, int max, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("min")] string minText = "", + [CallerArgumentExpression("max")] string maxText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + WithinMinMaxImpl(AssertionType.UserAssert, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkWithinMinMax(int value, int min, int max, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("min")] string minText = "", + [CallerArgumentExpression("max")] string maxText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + WithinMinMaxImpl(AssertionType.SdkAssert, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresWithinMinMax(int value, int min, int max, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("min")] string minText = "", + [CallerArgumentExpression("max")] string maxText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + WithinMinMaxImpl(AssertionType.SdkRequires, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Within min-max long + // --------------------------------------------------------------------- + + private static void WithinMinMaxImpl(AssertionType assertionType, long value, long min, long max, + string valueText, string minText, string maxText, string functionName, string fileName, int lineNumber) + { + if (AssertImpl.WithinMinMax(value, min, max)) + return; + + AssertImpl.InvokeAssertionWithinMinMax(assertionType, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void WithinMinMax(long value, long min, long max, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("min")] string minText = "", + [CallerArgumentExpression("max")] string maxText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + WithinMinMaxImpl(AssertionType.UserAssert, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkWithinMinMax(long value, long min, long max, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("min")] string minText = "", + [CallerArgumentExpression("max")] string maxText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + WithinMinMaxImpl(AssertionType.SdkAssert, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresWithinMinMax(long value, long min, long max, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("min")] string minText = "", + [CallerArgumentExpression("max")] string maxText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + WithinMinMaxImpl(AssertionType.SdkRequires, value, min, max, valueText, minText, maxText, functionName, + fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Equal + // --------------------------------------------------------------------- + + private static void EqualImpl(AssertionType assertionType, T lhs, T rhs, string lhsText, string rhsText, + string functionName, string fileName, int lineNumber) where T : IEquatable + { + if (AssertImpl.Equal(lhs, rhs)) + return; + + AssertImpl.InvokeAssertionEqual(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void Equal(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + EqualImpl(AssertionType.UserAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + EqualImpl(AssertionType.SdkAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + EqualImpl(AssertionType.SdkRequires, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Equal ref + // --------------------------------------------------------------------- + + private static void EqualImpl(AssertionType assertionType, ref T lhs, ref T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable + { + if (AssertImpl.Equal(ref lhs, ref rhs)) + return; + + AssertImpl.InvokeAssertionEqual(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void Equal(ref T lhs, ref T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + EqualImpl(AssertionType.UserAssert, ref lhs, ref rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkEqual(ref T lhs, ref T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + EqualImpl(AssertionType.SdkAssert, ref lhs, ref rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresEqual(ref T lhs, ref T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + EqualImpl(AssertionType.SdkRequires, ref lhs, ref rhs, lhsText, rhsText, functionName, fileName, + lineNumber); + } + + // --------------------------------------------------------------------- + // Not equal + // --------------------------------------------------------------------- + + private static void NotEqualImpl(AssertionType assertionType, T lhs, T rhs, string lhsText, string rhsText, + string functionName, string fileName, int lineNumber) where T : IEquatable + { + if (AssertImpl.NotEqual(lhs, rhs)) + return; + + AssertImpl.InvokeAssertionNotEqual(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void NotEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + NotEqualImpl(AssertionType.UserAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkNotEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + NotEqualImpl(AssertionType.SdkAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNotEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + NotEqualImpl(AssertionType.SdkRequires, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Not equal ref + // --------------------------------------------------------------------- + + private static void NotEqualImpl(AssertionType assertionType, ref T lhs, ref T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable + { + if (AssertImpl.NotEqual(ref lhs, ref rhs)) + return; + + AssertImpl.InvokeAssertionNotEqual(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void NotEqual(ref T lhs, ref T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + NotEqualImpl(AssertionType.UserAssert, ref lhs, ref rhs, lhsText, rhsText, functionName, fileName, + lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkNotEqual(ref T lhs, ref T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + NotEqualImpl(AssertionType.SdkAssert, ref lhs, ref rhs, lhsText, rhsText, functionName, fileName, + lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresNotEqual(ref T lhs, ref T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IEquatable + { + NotEqualImpl(AssertionType.SdkRequires, ref lhs, ref rhs, lhsText, rhsText, functionName, fileName, + lineNumber); + } + + // --------------------------------------------------------------------- + // Less + // --------------------------------------------------------------------- + + private static void LessImpl(AssertionType assertionType, T lhs, T rhs, string lhsText, string rhsText, + string functionName, string fileName, int lineNumber) where T : IComparable + { + if (AssertImpl.Less(lhs, rhs)) + return; + + AssertImpl.InvokeAssertionLess(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void Less(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + LessImpl(AssertionType.UserAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkLess(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + LessImpl(AssertionType.SdkAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresLess(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + LessImpl(AssertionType.SdkRequires, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Less equal + // --------------------------------------------------------------------- + + private static void LessEqualImpl(AssertionType assertionType, T lhs, T rhs, string lhsText, string rhsText, + string functionName, string fileName, int lineNumber) where T : IComparable + { + if (AssertImpl.LessEqual(lhs, rhs)) + return; + + AssertImpl.InvokeAssertionLessEqual(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void LessEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + LessEqualImpl(AssertionType.UserAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkLessEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + LessEqualImpl(AssertionType.SdkAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresLessEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + LessEqualImpl(AssertionType.SdkRequires, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Greater + // --------------------------------------------------------------------- + + private static void GreaterImpl(AssertionType assertionType, T lhs, T rhs, string lhsText, string rhsText, + string functionName, string fileName, int lineNumber) where T : IComparable + { + if (AssertImpl.Greater(lhs, rhs)) + return; + + AssertImpl.InvokeAssertionGreater(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void Greater(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + GreaterImpl(AssertionType.UserAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkGreater(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + GreaterImpl(AssertionType.SdkAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresGreater(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + GreaterImpl(AssertionType.SdkRequires, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Greater equal + // --------------------------------------------------------------------- + + private static void GreaterEqualImpl(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable + { + if (AssertImpl.GreaterEqual(lhs, rhs)) + return; + + AssertImpl.InvokeAssertionGreaterEqual(assertionType, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + public static void GreaterEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + GreaterEqualImpl(AssertionType.UserAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkGreaterEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + GreaterEqualImpl(AssertionType.SdkAssert, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresGreaterEqual(T lhs, T rhs, + [CallerArgumentExpression("lhs")] string lhsText = "", + [CallerArgumentExpression("rhs")] string rhsText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + where T : IComparable + { + GreaterEqualImpl(AssertionType.SdkRequires, lhs, rhs, lhsText, rhsText, functionName, fileName, lineNumber); + } + + // --------------------------------------------------------------------- + // Aligned + // --------------------------------------------------------------------- + + private static void AlignedImpl(AssertionType assertionType, ulong value, int alignment, string valueText, + string alignmentText, string functionName, string fileName, int lineNumber) + { + if (AssertImpl.IsAligned(value, alignment)) + return; + + AssertImpl.InvokeAssertionAligned(assertionType, value, alignment, valueText, alignmentText, functionName, fileName, + lineNumber); + } + + [Conditional(AssertCondition)] + public static void Aligned(ulong value, int alignment, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("alignment")] string alignmentText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + AlignedImpl(AssertionType.UserAssert, value, alignment, valueText, alignmentText, functionName, fileName, + lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkAligned(ulong value, int alignment, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("alignment")] string alignmentText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + AlignedImpl(AssertionType.SdkAssert, value, alignment, valueText, alignmentText, functionName, fileName, + lineNumber); + } + + [Conditional(AssertCondition)] + internal static void SdkRequiresAligned(ulong value, int alignment, + [CallerArgumentExpression("value")] string valueText = "", + [CallerArgumentExpression("alignment")] string alignmentText = "", + [CallerMemberName] string functionName = "", + [CallerFilePath] string fileName = "", + [CallerLineNumber] int lineNumber = 0) + { + AlignedImpl(AssertionType.SdkRequires, value, alignment, valueText, alignmentText, functionName, fileName, + lineNumber); } } } diff --git a/src/LibHac/Diag/Impl/AssertImpl.cs b/src/LibHac/Diag/Impl/AssertImpl.cs new file mode 100644 index 00000000..351d2e9a --- /dev/null +++ b/src/LibHac/Diag/Impl/AssertImpl.cs @@ -0,0 +1,233 @@ +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using LibHac.Util; + +namespace LibHac.Diag.Impl +{ + internal static class AssertImpl + { + internal static void InvokeAssertionNotNull(AssertionType assertionType, string valueText, string functionName, + string fileName, int lineNumber) + { + Assert.OnAssertionFailure(assertionType, valueText, functionName, fileName, lineNumber, + $"{valueText} must not be nullptr."); + } + + internal static void InvokeAssertionNull(AssertionType assertionType, string valueText, string functionName, + string fileName, int lineNumber) + { + Assert.OnAssertionFailure(assertionType, valueText, functionName, fileName, lineNumber, + $"{valueText} must be nullptr."); + } + + internal static void InvokeAssertionInRange(AssertionType assertionType, int value, int lower, int upper, + string valueText, string lowerText, string upperText, string functionName, string fileName, int lineNumber) + { + string message = + string.Format( + "{0} must be within the range [{1}, {2})\nThe actual values are as follows.\n{0}: {3}\n{1}: {4}\n{2}: {5}", + valueText, lowerText, upperText, value, lower, upper); + + Assert.OnAssertionFailure(assertionType, "RangeCheck", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionWithinMinMax(AssertionType assertionType, long value, long min, long max, + string valueText, string minText, string maxText, string functionName, string fileName, int lineNumber) + { + string message = + string.Format( + "{0} must satisfy the condition min:{1} and max:{2}\nThe actual values are as follows.\n{0}: {3}\n{1}: {4}\n{2}: {5}", + valueText, minText, maxText, value, min, max); + + Assert.OnAssertionFailure(assertionType, "MinMaxCheck", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionEqual(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable + { + string message = + string.Format("{0} must be equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + lhsText, rhsText, lhs, rhs); + + Assert.OnAssertionFailure(assertionType, "Equal", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionNotEqual(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable + { + string message = + string.Format("{0} must be equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + lhsText, rhsText, lhs, rhs); + + Assert.OnAssertionFailure(assertionType, "Equal", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionLess(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable + { + string message = + string.Format("{0} must be less than {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + lhsText, rhsText, lhs, rhs); + + Assert.OnAssertionFailure(assertionType, "Less", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionLessEqual(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable + { + string message = + string.Format( + "{0} must be less than or equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + lhsText, rhsText, lhs, rhs); + + Assert.OnAssertionFailure(assertionType, "LessEqual", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionGreater(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable + { + string message = + string.Format("{0} must be greater than {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + lhsText, rhsText, lhs, rhs); + + Assert.OnAssertionFailure(assertionType, "Greater", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionGreaterEqual(AssertionType assertionType, T lhs, T rhs, string lhsText, + string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable + { + string message = + string.Format( + "{0} must be greater than or equal to {1}.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + lhsText, rhsText, lhs, rhs); + + Assert.OnAssertionFailure(assertionType, "GreaterEqual", functionName, fileName, lineNumber, message); + } + + internal static void InvokeAssertionAligned(AssertionType assertionType, ulong value, int alignment, + string valueText, string alignmentText, string functionName, string fileName, int lineNumber) + { + string message = + string.Format("{0} must be {1}-bytes aligned.\nThe actual values are as follows.\n{0}: {2}\n{1}: {3}", + valueText, alignmentText, value, alignment); + + Assert.OnAssertionFailure(assertionType, "Aligned", functionName, fileName, lineNumber, message); + } + + public static bool Null(T item) where T : class + { + return item is null; + } + + public static bool Null(ref T item) + { + return Unsafe.IsNullRef(ref item); + } + + public static bool NotNull(T item) where T : class + { + return item is not null; + } + + public static bool NotNull(ref T item) + { + return !Unsafe.IsNullRef(ref item); + } + + public static bool NotNull(Span span) + { + return !Unsafe.IsNullRef(ref MemoryMarshal.GetReference(span)); + } + + public static bool NotNull(ReadOnlySpan span) + { + return !Unsafe.IsNullRef(ref MemoryMarshal.GetReference(span)); + } + + public static bool WithinRange(int value, int lowerInclusive, int upperExclusive) + { + return lowerInclusive <= value && value < upperExclusive; + } + + public static bool WithinRange(long value, long lowerInclusive, long upperExclusive) + { + return lowerInclusive <= value && value < upperExclusive; + } + + public static bool WithinMinMax(int value, int min, int max) + { + return min <= value && value <= max; + } + + public static bool WithinMinMax(long value, long min, long max) + { + return min <= value && value <= max; + } + + public static bool Equal(T lhs, T rhs) where T : IEquatable + { + return lhs.Equals(rhs); + } + + public static bool Equal(ref T lhs, ref T rhs) where T : IEquatable + { + return lhs.Equals(rhs); + } + + public static bool NotEqual(T lhs, T rhs) where T : IEquatable + { + return !lhs.Equals(rhs); + } + + public static bool NotEqual(ref T lhs, ref T rhs) where T : IEquatable + { + return !lhs.Equals(rhs); + } + + public static bool Less(T lhs, T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) < 0; + } + + public static bool Less(ref T lhs, ref T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) < 0; + } + + public static bool LessEqual(T lhs, T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) <= 0; + } + + public static bool LessEqual(ref T lhs, ref T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) <= 0; + } + + public static bool Greater(T lhs, T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) > 0; + } + + public static bool Greater(ref T lhs, ref T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) > 0; + } + + public static bool GreaterEqual(T lhs, T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) >= 0; + } + + public static bool GreaterEqual(ref T lhs, ref T rhs) where T : IComparable + { + return lhs.CompareTo(rhs) >= 0; + } + + public static bool IsAligned(ulong value, int alignment) + { + return Alignment.IsAlignedPow2(value, (uint)alignment); + } + } +} diff --git a/src/LibHac/Diag/Impl/ObserverManager.cs b/src/LibHac/Diag/Impl/ObserverManager.cs index 3ec47b53..27b1a00f 100644 --- a/src/LibHac/Diag/Impl/ObserverManager.cs +++ b/src/LibHac/Diag/Impl/ObserverManager.cs @@ -23,7 +23,7 @@ namespace LibHac.Diag.Impl public void RegisterObserver(TObserver observerHolder) { - Assert.False(observerHolder.IsRegistered); + Assert.SdkRequires(!observerHolder.IsRegistered); using ScopedLock lk = ScopedLock.Lock(ref _rwLock); @@ -33,7 +33,7 @@ namespace LibHac.Diag.Impl public void UnregisterObserver(TObserver observerHolder) { - Assert.True(observerHolder.IsRegistered); + Assert.SdkRequires(observerHolder.IsRegistered); using ScopedLock lk = ScopedLock.Lock(ref _rwLock); @@ -91,7 +91,7 @@ namespace LibHac.Diag.Impl public void RegisterObserver(LogObserverHolder observerHolder) { - Assert.False(observerHolder.IsRegistered); + Assert.SdkRequires(!observerHolder.IsRegistered); using ScopedLock lk = ScopedLock.Lock(ref _rwLock); @@ -101,7 +101,7 @@ namespace LibHac.Diag.Impl public void UnregisterObserver(LogObserverHolder observerHolder) { - Assert.True(observerHolder.IsRegistered); + Assert.SdkRequires(observerHolder.IsRegistered); using ScopedLock lk = ScopedLock.Lock(ref _rwLock); diff --git a/src/LibHac/Fs/AccessLog.cs b/src/LibHac/Fs/AccessLog.cs index a6a474b3..42670fdb 100644 --- a/src/LibHac/Fs/AccessLog.cs +++ b/src/LibHac/Fs/AccessLog.cs @@ -139,7 +139,8 @@ namespace LibHac.Fs.Impl private ReadOnlySpan ToValueString(int value) { bool success = Utf8Formatter.TryFormat(value, _buffer.Bytes, out int length); - Assert.True(success && length < _buffer.Bytes.Length); + Assert.SdkAssert(success); + Assert.SdkLess(length, _buffer.Bytes.Length); _buffer[length] = 0; return _buffer.Bytes; @@ -480,13 +481,13 @@ namespace LibHac.Fs.Impl public void RegisterCallback(AccessLogPrinterCallback callback) { - Assert.Null(_callback); + Assert.SdkNull(_callback); _callback = callback; } public int InvokeCallback(Span textBuffer) { - Assert.True(IsRegisteredCallback()); + Assert.SdkAssert(IsRegisteredCallback()); return _callback(textBuffer); } } @@ -658,7 +659,8 @@ namespace LibHac.Fs.Impl // We should never receive non-null here. // ReSharper disable once ConditionIsAlwaysTrueOrFalse - Assert.True(handle is null); + Assert.SdkAssert(handle is null, + "Handle type must be FileHandle or DirectoryHandle. Please cast to handle type."); return false; } @@ -683,7 +685,7 @@ namespace LibHac.Fs.Impl internal static void FlushAccessLog(this FileSystemClientImpl fs) { - Assert.True(false, $"Unsupported {nameof(FlushAccessLog)}"); + Assert.SdkAssert(false, $"Unsupported {nameof(FlushAccessLog)}"); } internal static void FlushAccessLogOnSdCard(this FileSystemClientImpl fs) diff --git a/src/LibHac/Fs/Fsa/IFile.cs b/src/LibHac/Fs/Fsa/IFile.cs index 68b43a3a..af908b79 100644 --- a/src/LibHac/Fs/Fsa/IFile.cs +++ b/src/LibHac/Fs/Fsa/IFile.cs @@ -1,7 +1,6 @@ using System; using System.Runtime.CompilerServices; using LibHac.Common; -using LibHac.Diag; namespace LibHac.Fs.Fsa { @@ -181,8 +180,6 @@ namespace LibHac.Fs.Fsa if (!openMode.HasFlag(OpenMode.Write)) return ResultFs.WriteUnpermitted.Log(); - Assert.True(size >= 0); - return Result.Success; } diff --git a/src/LibHac/Fs/Fsa/MountTable.cs b/src/LibHac/Fs/Fsa/MountTable.cs index 2db1f565..720753c8 100644 --- a/src/LibHac/Fs/Fsa/MountTable.cs +++ b/src/LibHac/Fs/Fsa/MountTable.cs @@ -68,7 +68,7 @@ namespace LibHac.Fs.Impl public bool CanAcceptMountName(U8Span name) { - Assert.True(_mutex.IsLockedByCurrentThread()); + Assert.SdkAssert(_mutex.IsLockedByCurrentThread()); for (LinkedListNode currentNode = _fileSystemList.First; currentNode is not null; diff --git a/src/LibHac/Fs/Impl/IFileDataCache.cs b/src/LibHac/Fs/Impl/IFileDataCache.cs index 50a6d3ff..1b25b9eb 100644 --- a/src/LibHac/Fs/Impl/IFileDataCache.cs +++ b/src/LibHac/Fs/Impl/IFileDataCache.cs @@ -55,7 +55,7 @@ namespace LibHac.Fs.Impl public int GetCacheFetchedRegionCount() { - Assert.True(_isFileDataCacheUsed); + Assert.SdkRequires(_isFileDataCacheUsed); return _regionCount; } @@ -63,9 +63,9 @@ namespace LibHac.Fs.Impl public FileRegion GetCacheFetchedRegion(int index) { - Assert.True(IsFileDataCacheUsed()); - Assert.True(index >= 0); - Assert.True(index < _regionCount); + Assert.SdkRequires(IsFileDataCacheUsed()); + Assert.SdkRequiresLessEqual(0, index); + Assert.SdkRequiresLess(index, _regionCount); return _regions[index]; } diff --git a/src/LibHac/Fs/Shim/ContentStorage.cs b/src/LibHac/Fs/Shim/ContentStorage.cs index 9651c76d..4d0b1595 100644 --- a/src/LibHac/Fs/Shim/ContentStorage.cs +++ b/src/LibHac/Fs/Shim/ContentStorage.cs @@ -32,14 +32,14 @@ namespace LibHac.Fs.Shim int neededSize = StringUtils.GetLength(GetContentStorageMountName(StorageId), PathTool.MountNameLengthMax) + 2; - Assert.True(nameBuffer.Length >= neededSize); + Assert.SdkRequiresGreaterEqual(nameBuffer.Length, neededSize); // Generate the name. var sb = new U8StringBuilder(nameBuffer); sb.Append(GetContentStorageMountName(StorageId)) .Append(StringTraits.DriveSeparator); - Assert.True(sb.Length == neededSize - 1); + Assert.SdkEqual(sb.Length, neededSize - 1); return Result.Success; } diff --git a/src/LibHac/Fs/Shim/GameCard.cs b/src/LibHac/Fs/Shim/GameCard.cs index 17f9674b..2ced0cf8 100644 --- a/src/LibHac/Fs/Shim/GameCard.cs +++ b/src/LibHac/Fs/Shim/GameCard.cs @@ -53,7 +53,7 @@ namespace LibHac.Fs.Shim StringUtils.GetLength(GetGameCardMountNameSuffix(PartitionId), PathTool.MountNameLengthMax) + handleDigitCount + 2; - Assert.True(nameBuffer.Length >= neededSize); + Assert.SdkRequiresGreaterEqual(nameBuffer.Length, neededSize); // Generate the name. var sb = new U8StringBuilder(nameBuffer); @@ -62,7 +62,7 @@ namespace LibHac.Fs.Shim .AppendFormat(Handle.Value, 'x', (byte)handleDigitCount) .Append(StringTraits.DriveSeparator); - Assert.True(sb.Length == neededSize - 1); + Assert.SdkEqual(sb.Length, neededSize - 1); return Result.Success; } diff --git a/src/LibHac/Fs/Shim/Host.cs b/src/LibHac/Fs/Shim/Host.cs index ce0de63f..9581ad33 100644 --- a/src/LibHac/Fs/Shim/Host.cs +++ b/src/LibHac/Fs/Shim/Host.cs @@ -93,7 +93,7 @@ namespace LibHac.Fs.Shim var sb = new U8StringBuilder(nameBuffer); sb.Append(HostRootFileSystemPath).Append(_path.Str); - Assert.True(sb.Length == requiredNameBufferSize - 1); + Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1); return Result.Success; } @@ -107,12 +107,12 @@ namespace LibHac.Fs.Shim { const int requiredNameBufferSize = HostRootFileSystemPathLength; - Assert.True(nameBuffer.Length >= requiredNameBufferSize); + Assert.SdkRequiresGreaterEqual(nameBuffer.Length, requiredNameBufferSize); var sb = new U8StringBuilder(nameBuffer); sb.Append(HostRootFileSystemPath); - Assert.True(sb.Length == requiredNameBufferSize - 1); + Assert.SdkEqual(sb.Length, requiredNameBufferSize - 1); return Result.Success; } diff --git a/src/LibHac/Fs/SubStorage.cs b/src/LibHac/Fs/SubStorage.cs index 06852146..037364ba 100644 --- a/src/LibHac/Fs/SubStorage.cs +++ b/src/LibHac/Fs/SubStorage.cs @@ -82,9 +82,9 @@ namespace LibHac.Fs Size = size; IsResizable = false; - Assert.True(IsValid()); - Assert.True(Offset >= 0); - Assert.True(Size >= 0); + Assert.SdkRequiresNotNull(baseStorage); + Assert.SdkRequiresLessEqual(0, Offset); + Assert.SdkRequiresLessEqual(0, Size); } /// @@ -102,9 +102,9 @@ namespace LibHac.Fs Size = size; IsResizable = false; - Assert.True(IsValid()); - Assert.True(Offset >= 0); - Assert.True(Size >= 0); + Assert.SdkRequiresNotNull(sharedBaseStorage); + Assert.SdkRequiresLessEqual(0, Offset); + Assert.SdkRequiresLessEqual(0, Size); } /// @@ -126,10 +126,10 @@ namespace LibHac.Fs Size = size; IsResizable = false; - Assert.True(IsValid()); - Assert.True(Offset >= 0); - Assert.True(Size >= 0); - Assert.True(other.Size >= offset + size); + Assert.SdkRequires(other.IsValid()); + Assert.SdkRequiresLessEqual(0, Offset); + Assert.SdkRequiresLessEqual(0, Size); + Assert.SdkRequiresGreaterEqual(other.Size, offset + size); } private bool IsValid() => BaseStorage != null; diff --git a/src/LibHac/FsSrv/Impl/LocationResolverSet.cs b/src/LibHac/FsSrv/Impl/LocationResolverSet.cs index 7e721d65..e152dd2b 100644 --- a/src/LibHac/FsSrv/Impl/LocationResolverSet.cs +++ b/src/LibHac/FsSrv/Impl/LocationResolverSet.cs @@ -197,7 +197,7 @@ namespace LibHac.FsSrv.Impl private static int GetResolverIndexFromStorageId(StorageId id) { - Assert.True(IsValidStorageId(id)); + Assert.SdkRequires(IsValidStorageId(id)); return id switch { diff --git a/src/LibHac/FsSrv/Impl/Utility.cs b/src/LibHac/FsSrv/Impl/Utility.cs index e105a43e..35e26bd0 100644 --- a/src/LibHac/FsSrv/Impl/Utility.cs +++ b/src/LibHac/FsSrv/Impl/Utility.cs @@ -36,7 +36,7 @@ namespace LibHac.FsSrv.Impl private static Result EnsureDirectoryImpl(IFileSystem fileSystem, Span path) { // Double check the trailing separators have been trimmed - Assert.True(path.Length <= 1 || path[path.Length - 1] != StringTraits.DirectorySeparator); + Assert.SdkRequires(path.Length <= 1 || path[path.Length - 1] != StringTraits.DirectorySeparator); // Use the root path if the input path is empty var pathToCheck = new U8Span(path.IsEmpty ? FileSystemRootPath : path); @@ -91,8 +91,8 @@ namespace LibHac.FsSrv.Impl private static Result EnsureParentDirectoryImpl(IFileSystem fileSystem, Span path) { // The path should not be empty or have a trailing directory separator - Assert.True(path.Length > 0); - Assert.NotEqual(StringTraits.DirectorySeparator, path[path.Length - 1]); + Assert.SdkRequiresLess(0, path.Length); + Assert.SdkRequiresNotEqual(path[path.Length - 1], StringTraits.DirectorySeparator); // Make sure the path's not too long if (path.Length > PathTool.EntryNameLengthMax) diff --git a/src/LibHac/FsSrv/NcaFileSystemService.cs b/src/LibHac/FsSrv/NcaFileSystemService.cs index 71dde3fc..4cff02b3 100644 --- a/src/LibHac/FsSrv/NcaFileSystemService.cs +++ b/src/LibHac/FsSrv/NcaFileSystemService.cs @@ -121,7 +121,7 @@ namespace LibHac.FsSrv if (originalResult.IsFailure()) return originalResult; - Assert.True(originalPathNormalizerHasValue); + Assert.SdkAssert(originalPathNormalizerHasValue); // There is an original version and no patch version. Open the original directly rc = ServiceImpl.OpenFileSystem(out tempFileSystem, originalPathNormalizer.Path, fsType, programId.Value); diff --git a/src/LibHac/FsSrv/SaveDataIndexer.cs b/src/LibHac/FsSrv/SaveDataIndexer.cs index 1d7bbf84..69052dff 100644 --- a/src/LibHac/FsSrv/SaveDataIndexer.cs +++ b/src/LibHac/FsSrv/SaveDataIndexer.cs @@ -533,7 +533,7 @@ namespace LibHac.FsSrv private FlatMapKeyValueStore.Iterator GetBeginIterator() { - Assert.True(IsKvdbLoaded); + Assert.SdkRequires(IsKvdbLoaded); return KvDatabase.GetBeginIterator(); } diff --git a/src/LibHac/FsSrv/SaveDataIndexerManager.cs b/src/LibHac/FsSrv/SaveDataIndexerManager.cs index c19f73e8..df0376d1 100644 --- a/src/LibHac/FsSrv/SaveDataIndexerManager.cs +++ b/src/LibHac/FsSrv/SaveDataIndexerManager.cs @@ -168,7 +168,7 @@ namespace LibHac.FsSrv // ReSharper disable once RedundantAssignment Result rc = _tempIndexer.Indexer.Reset(); - Assert.True(rc.IsSuccess()); + Assert.SdkAssert(rc.IsSuccess()); } public void InvalidateIndexer(SaveDataSpaceId spaceId) diff --git a/src/LibHac/FsSrv/Sf/Path.cs b/src/LibHac/FsSrv/Sf/Path.cs index c714a1d7..54e89f0d 100644 --- a/src/LibHac/FsSrv/Sf/Path.cs +++ b/src/LibHac/FsSrv/Sf/Path.cs @@ -1,9 +1,12 @@ using System; -using System.Diagnostics; using System.Runtime.InteropServices; using LibHac.Common; using LibHac.Fs; +#if DEBUG +using System.Diagnostics; +#endif + namespace LibHac.FsSrv.Sf { [StructLayout(LayoutKind.Sequential, Size = PathTool.EntryNameLengthMax + 1)] diff --git a/src/LibHac/FsSrv/StatusReportService.cs b/src/LibHac/FsSrv/StatusReportService.cs index dfd59c62..eb77b198 100644 --- a/src/LibHac/FsSrv/StatusReportService.cs +++ b/src/LibHac/FsSrv/StatusReportService.cs @@ -124,15 +124,15 @@ namespace LibHac.FsSrv switch (threadType) { case FsStackUsageThreadType.MainThread: - Assert.NotNull(_config.MainThreadStackUsageReporter); + Assert.SdkRequiresNotNull(_config.MainThreadStackUsageReporter); return _config.MainThreadStackUsageReporter.GetStackUsage(); case FsStackUsageThreadType.IpcWorker: - Assert.NotNull(_config.IpcWorkerThreadStackUsageReporter); + Assert.SdkRequiresNotNull(_config.IpcWorkerThreadStackUsageReporter); return _config.IpcWorkerThreadStackUsageReporter.GetStackUsage(); case FsStackUsageThreadType.PipelineWorker: - Assert.NotNull(_config.PipeLineWorkerThreadStackUsageReporter); + Assert.SdkRequiresNotNull(_config.PipeLineWorkerThreadStackUsageReporter); return _config.PipeLineWorkerThreadStackUsageReporter.GetStackUsage(); default: diff --git a/src/LibHac/FsSrv/Storage/StorageDeviceManagerFactory.cs b/src/LibHac/FsSrv/Storage/StorageDeviceManagerFactory.cs index de016ef4..74cd6dca 100644 --- a/src/LibHac/FsSrv/Storage/StorageDeviceManagerFactory.cs +++ b/src/LibHac/FsSrv/Storage/StorageDeviceManagerFactory.cs @@ -31,7 +31,7 @@ namespace LibHac.FsSrv.Storage out ReferenceCountedDisposable deviceManager, StorageDevicePortId portId) { IStorageDeviceManagerFactory factory = storage.GetStorageDeviceManagerFactory(null); - Assert.NotNull(factory); + Assert.SdkNotNull(factory); return factory.Create(out deviceManager, portId); } diff --git a/src/LibHac/FsSystem/BucketTree.cs b/src/LibHac/FsSystem/BucketTree.cs index ff31205c..14c303f1 100644 --- a/src/LibHac/FsSystem/BucketTree.cs +++ b/src/LibHac/FsSystem/BucketTree.cs @@ -35,11 +35,11 @@ namespace LibHac.FsSystem public Result Initialize(SubStorage nodeStorage, SubStorage entryStorage, int nodeSize, int entrySize, int entryCount) { - Assert.True(entrySize >= sizeof(long)); - Assert.True(nodeSize >= entrySize + Unsafe.SizeOf()); - Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax); - Assert.True(BitUtil.IsPowerOfTwo(nodeSize)); - Assert.True(!IsInitialized()); + Assert.SdkRequiresLessEqual(sizeof(long), entrySize); + Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf(), nodeSize); + Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize)); + Assert.SdkRequires(!IsInitialized()); // Ensure valid entry count. if (entryCount <= 0) @@ -119,7 +119,7 @@ namespace LibHac.FsSystem public Result Find(ref Visitor visitor, long virtualAddress) { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); if (virtualAddress < 0) return ResultFs.InvalidOffset.Log(); @@ -137,11 +137,11 @@ namespace LibHac.FsSystem public static long QueryNodeStorageSize(long nodeSize, long entrySize, int entryCount) { - Assert.True(entrySize >= sizeof(long)); - Assert.True(nodeSize >= entrySize + Unsafe.SizeOf()); - Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax); - Assert.True(BitUtil.IsPowerOfTwo(nodeSize)); - Assert.True(entryCount >= 0); + Assert.SdkRequiresLessEqual(sizeof(long), entrySize); + Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf(), nodeSize); + Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize)); + Assert.SdkRequiresLessEqual(0, entryCount); if (entryCount <= 0) return 0; @@ -151,11 +151,11 @@ namespace LibHac.FsSystem public static long QueryEntryStorageSize(long nodeSize, long entrySize, int entryCount) { - Assert.True(entrySize >= sizeof(long)); - Assert.True(nodeSize >= entrySize + Unsafe.SizeOf()); - Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax); - Assert.True(BitUtil.IsPowerOfTwo(nodeSize)); - Assert.True(entryCount >= 0); + Assert.SdkRequiresLessEqual(sizeof(long), entrySize); + Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf(), nodeSize); + Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize)); + Assert.SdkRequiresLessEqual(0, entryCount); if (entryCount <= 0) return 0; @@ -276,7 +276,7 @@ namespace LibHac.FsSystem public bool Allocate(int nodeSize) { - Assert.True(_header == null); + Assert.SdkRequiresNotNull(_header); _header = new long[nodeSize / sizeof(long)]; @@ -298,7 +298,7 @@ namespace LibHac.FsSystem public ref NodeHeader GetHeader() { - Assert.True(_header.Length / sizeof(long) >= Unsafe.SizeOf()); + Assert.SdkRequiresGreaterEqual(_header.Length / sizeof(long), Unsafe.SizeOf()); return ref Unsafe.As(ref _header[0]); } @@ -322,8 +322,9 @@ namespace LibHac.FsSystem { _buffer = buffer; - Assert.True(_buffer.Length >= Unsafe.SizeOf()); - Assert.True(_buffer.Length >= Unsafe.SizeOf() + GetHeader().Count * Unsafe.SizeOf()); + Assert.SdkRequiresGreaterEqual(_buffer.Length, Unsafe.SizeOf()); + Assert.SdkRequiresGreaterEqual(_buffer.Length, + Unsafe.SizeOf() + GetHeader().Count * Unsafe.SizeOf()); } public int GetCount() => GetHeader().Count; @@ -381,8 +382,8 @@ namespace LibHac.FsSystem public Result Initialize(BucketTree tree) { - Assert.True(tree != null); - Assert.True(Tree == null || tree == Tree); + Assert.SdkRequiresNotNull(tree); + Assert.SdkRequires(Tree == null || tree == Tree); if (Entry == null) { diff --git a/src/LibHac/FsSystem/BucketTreeBuilder.cs b/src/LibHac/FsSystem/BucketTreeBuilder.cs index 1a7f2c29..e7070c6e 100644 --- a/src/LibHac/FsSystem/BucketTreeBuilder.cs +++ b/src/LibHac/FsSystem/BucketTreeBuilder.cs @@ -42,10 +42,10 @@ namespace LibHac.FsSystem public Result Initialize(SubStorage headerStorage, SubStorage nodeStorage, SubStorage entryStorage, int nodeSize, int entrySize, int entryCount) { - Assert.True(entrySize >= sizeof(long)); - Assert.True(nodeSize >= entrySize + Unsafe.SizeOf()); - Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax); - Assert.True(BitUtil.IsPowerOfTwo(nodeSize)); + Assert.SdkRequiresLessEqual(sizeof(long), entrySize); + Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf(), nodeSize); + Assert.SdkRequiresWithinMinMax(nodeSize, NodeSizeMin, NodeSizeMax); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(nodeSize)); if (headerStorage is null || nodeStorage is null || entryStorage is null) return ResultFs.NullptrArgument.Log(); @@ -99,7 +99,7 @@ namespace LibHac.FsSystem /// The of the operation. public Result Add(ref T entry) where T : unmanaged { - Assert.True(Unsafe.SizeOf() == EntrySize); + Assert.SdkRequiresEqual(Unsafe.SizeOf(), EntrySize); if (CurrentEntryIndex >= EntryCount) return ResultFs.OutOfRange.Log(); diff --git a/src/LibHac/FsSystem/Buffers/BufferManagerUtility.cs b/src/LibHac/FsSystem/Buffers/BufferManagerUtility.cs index c8081a83..32915a4b 100644 --- a/src/LibHac/FsSystem/Buffers/BufferManagerUtility.cs +++ b/src/LibHac/FsSystem/Buffers/BufferManagerUtility.cs @@ -94,8 +94,9 @@ namespace LibHac.FsSystem.Buffers int size, IBufferManager.BufferAttribute attribute, IsValidBufferFunction isValidBuffer, [CallerMemberName] string callerName = "") { - Assert.NotNull(bufferManager); - Assert.NotNull(callerName); + Assert.SdkNotNullOut(out outBuffer); + Assert.SdkNotNull(bufferManager); + Assert.SdkNotNull(callerName); // Clear the output. outBuffer = new Buffer(); @@ -135,7 +136,7 @@ namespace LibHac.FsSystem.Buffers if (rc.IsFailure()) return rc; } - Assert.True(!tempBuffer.IsNull); + Assert.SdkAssert(!tempBuffer.IsNull); outBuffer = tempBuffer; return Result.Success; } diff --git a/src/LibHac/FsSystem/Buffers/FileSystemBuddyHeap.cs b/src/LibHac/FsSystem/Buffers/FileSystemBuddyHeap.cs index 6529072a..22c3a8bb 100644 --- a/src/LibHac/FsSystem/Buffers/FileSystemBuddyHeap.cs +++ b/src/LibHac/FsSystem/Buffers/FileSystemBuddyHeap.cs @@ -40,7 +40,7 @@ namespace LibHac.FsSystem public PageEntry* PopFront() { - Assert.True(EntryCount > 0); + Assert.SdkRequires(EntryCount > 0); // Get the first entry. PageEntry* pageEntry = FirstPageEntry; @@ -51,7 +51,7 @@ namespace LibHac.FsSystem // Decrement our count. EntryCount--; - Assert.True(EntryCount >= 0); + Assert.SdkGreaterEqual(EntryCount, 0); // If this was our last page, clear our last entry. if (EntryCount == 0) @@ -64,7 +64,7 @@ namespace LibHac.FsSystem public void PushBack(PageEntry* pageEntry) { - Assert.True(pageEntry != null); + Assert.SdkRequires(pageEntry != null); // If we're empty, we want to set the first page entry. if (IsEmpty()) @@ -74,7 +74,7 @@ namespace LibHac.FsSystem else { // We're not empty, so push the page to the back. - Assert.True(LastPageEntry != pageEntry); + Assert.SdkAssert(LastPageEntry != pageEntry); LastPageEntry->Next = pageEntry; } @@ -84,12 +84,12 @@ namespace LibHac.FsSystem // Increment our entry count. EntryCount++; - Assert.True(EntryCount > 0); + Assert.SdkGreater(EntryCount, 0); } public bool Remove(PageEntry* pageEntry) { - Assert.True(pageEntry != null); + Assert.SdkRequires(pageEntry != null); // If we're empty, we can't remove the page list. if (IsEmpty()) @@ -128,7 +128,7 @@ namespace LibHac.FsSystem // Update our entry count. EntryCount--; - Assert.True(EntryCount >= 0); + Assert.SdkGreaterEqual(EntryCount, 0); return true; } @@ -162,14 +162,14 @@ namespace LibHac.FsSystem public static int GetBlockCountFromOrder(int order) { - Assert.True(0 <= order); - Assert.True(order < OrderUpperLimit); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLess(order, OrderUpperLimit); return 1 << order; } public static nuint QueryWorkBufferSize(int orderMax) { - Assert.InRange(orderMax, 1, OrderUpperLimit); + Assert.SdkRequiresInRange(orderMax, 1, OrderUpperLimit); var pageListSize = (nint)Unsafe.SizeOf(); uint pageListAlignment = (uint)Unsafe.SizeOf(); @@ -180,9 +180,9 @@ namespace LibHac.FsSystem public static int QueryOrderMax(nuint size, nuint blockSize) { - Assert.True(size >= blockSize); - Assert.True(blockSize >= BlockSizeMin); - Assert.True(BitUtil.IsPowerOfTwo(blockSize)); + Assert.SdkRequiresGreaterEqual(size, blockSize); + Assert.SdkRequiresGreaterEqual(blockSize, BlockSizeMin); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize)); int blockCount = (int)(Alignment.AlignUpPow2(size, (uint)blockSize) / blockSize); for (int order = 1; ; order++) @@ -200,14 +200,15 @@ namespace LibHac.FsSystem public Result Initialize(UIntPtr address, nuint size, nuint blockSize, int orderMax, void* workBuffer, nuint workBufferSize) { - Assert.True(workBufferSize >= QueryWorkBufferSize(orderMax)); + Assert.SdkRequiresGreaterEqual(workBufferSize, QueryWorkBufferSize(orderMax)); uint pageListAlignment = (uint)Unsafe.SizeOf(); var alignedWork = (void*)Alignment.AlignUpPow2((ulong)workBuffer, pageListAlignment); ExternalFreeLists = (PageList*)alignedWork; // Note: The original code does not have a buffer size assert after adjusting for alignment. - Assert.True(workBufferSize - ((nuint)alignedWork - (nuint)workBuffer) >= QueryWorkBufferSize(orderMax)); + Assert.SdkRequiresGreaterEqual(workBufferSize - ((nuint)alignedWork - (nuint)workBuffer), + QueryWorkBufferSize(orderMax)); return Initialize(address, size, blockSize, orderMax); } @@ -219,14 +220,14 @@ namespace LibHac.FsSystem public Result Initialize(UIntPtr address, nuint size, nuint blockSize, int orderMax) { - Assert.True(FreeLists == null); - Assert.True(address != UIntPtr.Zero); - Assert.True(Alignment.IsAlignedPow2(address.ToUInt64(), (uint)BufferAlignment)); - Assert.True(blockSize >= BlockSizeMin); - Assert.True(BitUtil.IsPowerOfTwo(blockSize)); - Assert.True(size >= blockSize); - Assert.True(orderMax > 0); - Assert.True(orderMax < OrderUpperLimit); + Assert.SdkRequires(FreeLists == null); + Assert.SdkRequiresNotEqual(address, UIntPtr.Zero); + Assert.SdkRequiresAligned(address.ToUInt64(), (int)BufferAlignment); + Assert.SdkRequiresGreaterEqual(blockSize, BlockSizeMin); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize)); + Assert.SdkRequiresGreaterEqual(size, blockSize); + Assert.SdkRequiresGreater(orderMax, 0); + Assert.SdkRequiresLess(orderMax, OrderUpperLimit); // Set up our basic member variables BlockSize = blockSize; @@ -239,12 +240,12 @@ namespace LibHac.FsSystem // Determine page sizes nuint maxPageSize = BlockSize << OrderMax; nuint maxPageCount = (nuint)Alignment.AlignUp(HeapSize, (uint)maxPageSize) / maxPageSize; - Assert.True(maxPageCount > 0); + Assert.SdkGreater((int)maxPageCount, 0); // Setup the free lists if (ExternalFreeLists != null) { - Assert.Null(InternalFreeLists); + Assert.SdkAssert(InternalFreeLists == null); FreeLists = ExternalFreeLists; } else @@ -268,7 +269,7 @@ namespace LibHac.FsSystem { nuint remaining = HeapSize - (maxPageCount - 1) * maxPageSize; nuint curAddress = HeapStart - (maxPageCount - 1) * maxPageSize; - Assert.True(Alignment.IsAlignedPow2(remaining, (uint)BlockSize)); + Assert.SdkAligned(remaining, (int)BlockSize); do { @@ -276,12 +277,12 @@ namespace LibHac.FsSystem int order = GetOrderFromBytes(remaining + 1); if (order < 0) { - Assert.True(GetOrderFromBytes(remaining) == orderMax); + Assert.SdkEqual(OrderMax, GetOrderFromBytes(remaining)); order = OrderMax + 1; } - Assert.True(0 < order); - Assert.True(order <= OrderMax + 1); + Assert.SdkGreater(order, 0); + Assert.SdkLessEqual(order, OrderMax + 1); // Add to the correct free list. FreeLists[order - 1].PushBack(GetPageEntryFromAddress(curAddress)); @@ -299,9 +300,9 @@ namespace LibHac.FsSystem public void* AllocateByOrder(int order) { - Assert.True(FreeLists != null); - Assert.True(order >= 0); - Assert.True(order <= GetOrderMax()); + Assert.SdkRequires(FreeLists != null); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLessEqual(order, GetOrderMax()); // Get the page entry. PageEntry* pageEntry = GetFreePageEntry(order); @@ -309,7 +310,7 @@ namespace LibHac.FsSystem if (pageEntry != null) { // Ensure we're allocating an unlinked page. - Assert.True(pageEntry->Next == null); + Assert.SdkAssert(pageEntry->Next == null); // Return the address for this entry. return (void*)GetAddressFromPageEntry(pageEntry); @@ -322,20 +323,20 @@ namespace LibHac.FsSystem public void Free(void* pointer, int order) { - Assert.True(FreeLists != null); - Assert.True(order >= 0); - Assert.True(order <= GetOrderMax()); + Assert.SdkRequires(FreeLists != null); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLessEqual(order, GetOrderMax()); // Allow Free(null) if (pointer == null) return; // Ensure the pointer is block aligned. - Assert.True(Alignment.IsAlignedPow2((nuint)pointer - HeapStart, (uint)GetBlockSize())); + Assert.SdkAligned((nuint)pointer - HeapStart, (int)GetBlockSize()); // Get the page entry. PageEntry* pageEntry = GetPageEntryFromAddress((UIntPtr)pointer); - Assert.True(IsAlignedToOrder(pageEntry, order)); + Assert.SdkAssert(IsAlignedToOrder(pageEntry, order)); /* Reinsert into the free lists. */ JoinBuddies(pageEntry, order); @@ -343,13 +344,13 @@ namespace LibHac.FsSystem public nuint GetTotalFreeSize() { - Assert.True(FreeLists != null); + Assert.SdkRequires(FreeLists != null); return TotalFreeSize; } public nuint GetAllocatableSizeMax() { - Assert.True(FreeLists != null); + Assert.SdkRequires(FreeLists != null); // The maximum allocatable size is a chunk from the biggest non-empty order. for (int order = GetOrderMax(); order >= 0; order--) @@ -366,43 +367,43 @@ namespace LibHac.FsSystem public void Dump() { - Assert.True(FreeLists != null); + Assert.SdkRequires(FreeLists != null); throw new NotImplementedException(); } public int GetOrderFromBytes(nuint size) { - Assert.True(FreeLists != null); + Assert.SdkRequires(FreeLists != null); return GetOrderFromBlockCount(GetBlockCountFromSize(size)); } public nuint GetBytesFromOrder(int order) { - Assert.True(FreeLists != null); - Assert.True(order >= 0); - Assert.True(order <= GetOrderMax()); + Assert.SdkRequires(FreeLists != null); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLessEqual(order, GetOrderMax()); return GetBlockSize() << order; } public int GetOrderMax() { - Assert.True(FreeLists != null); + Assert.SdkRequires(FreeLists != null); return OrderMax; } public nuint GetBlockSize() { - Assert.True(FreeLists != null); + Assert.SdkRequires(FreeLists != null); return BlockSize; } private void DivideBuddies(PageEntry* pageEntry, int requiredOrder, int chosenOrder) { - Assert.True(FreeLists != null); - Assert.True(requiredOrder >= 0); - Assert.True(chosenOrder >= requiredOrder); - Assert.True(chosenOrder <= GetOrderMax()); + Assert.SdkRequires(FreeLists != null); + Assert.SdkRequiresGreaterEqual(requiredOrder, 0); + Assert.SdkRequiresGreaterEqual(chosenOrder, requiredOrder); + Assert.SdkRequiresLessEqual(chosenOrder, GetOrderMax()); // Start at the end of the entry. nuint address = GetAddressFromPageEntry(pageEntry) + GetBytesFromOrder(chosenOrder); @@ -421,9 +422,9 @@ namespace LibHac.FsSystem private void JoinBuddies(PageEntry* pageEntry, int order) { - Assert.True(pageEntry != null); - Assert.True(order >= 0); - Assert.True(order <= GetOrderMax()); + Assert.SdkRequires(FreeLists != null); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLessEqual(order, GetOrderMax()); PageEntry* curEntry = pageEntry; int curOrder = order; @@ -460,9 +461,9 @@ namespace LibHac.FsSystem private PageEntry* GetBuddy(PageEntry* pageEntry, int order) { - Assert.True(pageEntry != null); - Assert.True(order >= 0); - Assert.True(order <= GetOrderMax()); + Assert.SdkRequires(FreeLists != null); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLessEqual(order, GetOrderMax()); nuint address = GetAddressFromPageEntry(pageEntry); nuint offset = (nuint)GetBlockCountFromOrder(order) * GetBlockSize(); @@ -482,8 +483,8 @@ namespace LibHac.FsSystem private PageEntry* GetFreePageEntry(int order) { - Assert.True(order >= 0); - Assert.True(order <= GetOrderMax()); + Assert.SdkRequiresGreaterEqual(order, 0); + Assert.SdkRequiresLessEqual(order, GetOrderMax()); // Try orders from low to high until we find a free page entry. for (int curOrder = order; curOrder <= GetOrderMax(); curOrder++) @@ -493,14 +494,14 @@ namespace LibHac.FsSystem { // The current list isn't empty, so grab an entry from it. PageEntry* pageEntry = freeList.PopFront(); - Assert.True(pageEntry != null); + Assert.SdkAssert(pageEntry != null); // Update size bookkeeping. TotalFreeSize -= GetBytesFromOrder(curOrder); // If we allocated more memory than needed, free the unneeded portion. DivideBuddies(pageEntry, order, curOrder); - Assert.True(pageEntry->Next == null); + Assert.SdkAssert(pageEntry->Next == null); // Return the newly-divided entry. return pageEntry; @@ -513,7 +514,7 @@ namespace LibHac.FsSystem private int GetOrderFromBlockCount(int blockCount) { - Assert.True(blockCount >= 0); + Assert.SdkRequiresGreaterEqual(blockCount, 0); // Return the first order with a big enough block count. for (int order = 0; order <= GetOrderMax(); ++order) @@ -537,17 +538,17 @@ namespace LibHac.FsSystem { var address = new UIntPtr(pageEntry); - Assert.True((nuint)HeapStart <= address); - Assert.True(address < HeapStart + HeapSize); - Assert.True(Alignment.IsAlignedPow2((nuint)address - HeapStart, (uint)GetBlockSize())); + Assert.SdkRequiresGreaterEqual(address, HeapStart); + Assert.SdkRequiresLess((nuint)address, HeapStart + HeapSize); + Assert.SdkRequiresAligned((nuint)address - HeapStart, (int)GetBlockSize()); return address; } private PageEntry* GetPageEntryFromAddress(UIntPtr address) { - Assert.True((nuint)HeapStart <= address); - Assert.True(address < HeapStart + HeapSize); + Assert.SdkRequiresGreaterEqual(address, HeapStart); + Assert.SdkRequiresLess((nuint)address, HeapStart + HeapSize); ulong blockStart = (ulong)HeapStart + Alignment.AlignDownPow2((nuint)address - HeapStart, (uint)GetBlockSize()); @@ -558,9 +559,9 @@ namespace LibHac.FsSystem { var address = (nuint)pageEntry; - Assert.True(HeapStart <= address); - Assert.True(address < HeapStart + HeapSize); - Assert.True(Alignment.IsAlignedPow2(address - HeapStart, (uint)GetBlockSize())); + Assert.SdkRequiresGreaterEqual(address, (nuint)HeapStart); + Assert.SdkRequiresLess(address, HeapStart + HeapSize); + Assert.SdkRequiresAligned(address - HeapStart, (int)GetBlockSize()); return (int)((address - HeapStart) / GetBlockSize()); } @@ -616,7 +617,7 @@ namespace LibHac.FsSystem public Buffer AllocateBufferByOrder(int order) { - Assert.True(!HeapBuffer.IsEmpty); + Assert.SdkRequires(!HeapBuffer.IsEmpty); void* address = AllocateByOrder(order); @@ -624,11 +625,11 @@ namespace LibHac.FsSystem return Buffer.Empty; nuint size = GetBytesFromOrder(order); - Assert.True(size <= int.MaxValue); + Assert.SdkLessEqual(size, (nuint)int.MaxValue); // Get the offset relative to the heap start nuint offset = (nuint)address - (nuint)PinnedHeapMemoryHandle.Pointer; - Assert.True(offset <= (nuint)HeapBuffer.Length); + Assert.SdkLessEqual(offset, (nuint)HeapBuffer.Length); // Get a slice of the Memory containing the entire heap return new Buffer(HeapBuffer.Slice((int)offset, (int)size)); @@ -636,8 +637,8 @@ namespace LibHac.FsSystem public void Free(Buffer buffer) { - Assert.True(!HeapBuffer.IsEmpty); - Assert.True(!buffer.IsNull); + Assert.SdkRequires(!HeapBuffer.IsEmpty); + Assert.SdkRequires(!buffer.IsNull); int order = GetOrderFromBytes((nuint)buffer.Length); void* pointer = Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer.Span)); diff --git a/src/LibHac/FsSystem/Buffers/FileSystemBufferManager.cs b/src/LibHac/FsSystem/Buffers/FileSystemBufferManager.cs index 336eb099..049c7cf9 100644 --- a/src/LibHac/FsSystem/Buffers/FileSystemBufferManager.cs +++ b/src/LibHac/FsSystem/Buffers/FileSystemBufferManager.cs @@ -56,7 +56,7 @@ namespace LibHac.FsSystem public void AddCacheSize(int diff) => _cacheSize += diff; public void SubtractCacheSize(int diff) { - Assert.True(_cacheSize >= diff); + Assert.SdkRequiresGreaterEqual(_cacheSize, diff); _cacheSize -= diff; } } @@ -75,7 +75,7 @@ namespace LibHac.FsSystem // This function is left here anyway for completion's sake. public static int QueryWorkBufferSize(int maxCacheCount) { - Assert.True(maxCacheCount > 0); + Assert.SdkRequiresGreater(maxCacheCount, 0); int entryAlignment = sizeof(CacheHandle); int attrInfoAlignment = Unsafe.SizeOf(); @@ -89,7 +89,7 @@ namespace LibHac.FsSystem public Result Initialize(int maxCacheCount) { // Validate pre-conditions. - Assert.True(Entries == null); + Assert.SdkRequiresNull(Entries); // Note: We don't have the option of using an external Entry buffer like the original C++ code // because Entry includes managed references so we can't cast a byte* to Entry* without pinning. @@ -106,7 +106,7 @@ namespace LibHac.FsSystem EntryCount = 0; EntryCountMax = maxCacheCount; - Assert.True(Entries != null); + Assert.SdkNotNull(Entries); CacheCountMin = maxCacheCount / 16; CacheSizeMin = CacheCountMin * 0x100; @@ -131,8 +131,8 @@ namespace LibHac.FsSystem UnsafeHelpers.SkipParamInit(out handle); // Validate pre-conditions. - Assert.True(Entries != null); - Assert.True(!Unsafe.IsNullRef(ref handle)); + Assert.SdkRequiresNotNull(Entries); + Assert.SdkRequiresNotNull(ref handle); // Get the entry. ref Entry entry = ref AcquireEntry(buffer, attr); @@ -165,8 +165,8 @@ namespace LibHac.FsSystem { // Validate pre-conditions. Unsafe.SkipInit(out buffer); - Assert.True(Entries != null); - Assert.True(!Unsafe.IsNullRef(ref buffer)); + Assert.SdkRequiresNotNull(Entries); + Assert.SdkRequiresNotNull(ref buffer); UnsafeHelpers.SkipParamInit(out buffer); @@ -189,8 +189,8 @@ namespace LibHac.FsSystem { // Validate pre-conditions. Unsafe.SkipInit(out buffer); - Assert.True(Entries != null); - Assert.True(!Unsafe.IsNullRef(ref buffer)); + Assert.SdkRequiresNotNull(Entries); + Assert.SdkRequiresNotNull(ref buffer); UnsafeHelpers.SkipParamInit(out buffer); @@ -203,7 +203,7 @@ namespace LibHac.FsSystem static bool CanUnregister(CacheHandleTable table, ref Entry entry) { ref AttrInfo attrInfo = ref table.FindAttrInfo(entry.GetBufferAttribute()); - Assert.True(!Unsafe.IsNullRef(ref attrInfo)); + Assert.SdkNotNull(ref attrInfo); int ccm = table.GetCacheCountMin(entry.GetBufferAttribute()); int csm = table.GetCacheSizeMin(entry.GetBufferAttribute()); @@ -227,32 +227,33 @@ namespace LibHac.FsSystem entry = ref Entries[0]; } - Assert.True(!Unsafe.IsNullRef(ref entry)); + Assert.SdkNotNull(ref entry); UnregisterCore(out buffer, ref entry); return true; } private void UnregisterCore(out Buffer buffer, ref Entry entry) { - // Validate pre-conditions. Unsafe.SkipInit(out buffer); - Assert.True(Entries != null); - Assert.True(!Unsafe.IsNullRef(ref buffer)); - Assert.True(!Unsafe.IsNullRef(ref entry)); + Assert.SdkRequiresNotNull(Entries); + Assert.SdkRequiresNotNull(ref buffer); + Assert.SdkRequiresNotNull(ref entry); + + UnsafeHelpers.SkipParamInit(out buffer); // Get the attribute info. ref AttrInfo attrInfo = ref FindAttrInfo(entry.GetBufferAttribute()); - Assert.True(!Unsafe.IsNullRef(ref attrInfo)); - Assert.True(attrInfo.GetCacheCount() > 0); - Assert.True(attrInfo.GetCacheSize() >= entry.GetSize()); + Assert.SdkNotNull(ref attrInfo); + Assert.SdkGreater(attrInfo.GetCacheCount(), 0); + Assert.SdkGreaterEqual(attrInfo.GetCacheSize(), entry.GetSize()); // Release from the attr info. attrInfo.DecrementCacheCount(); attrInfo.SubtractCacheSize(entry.GetSize()); // Release from cached size. - Assert.True(TotalCacheSize >= entry.GetSize()); + Assert.SdkGreaterEqual(TotalCacheSize, entry.GetSize()); TotalCacheSize -= entry.GetSize(); // Release the entry. @@ -262,7 +263,7 @@ namespace LibHac.FsSystem public CacheHandle PublishCacheHandle() { - Assert.True(Entries != null); + Assert.SdkRequires(Entries != null); return ++CurrentHandle; } @@ -274,7 +275,7 @@ namespace LibHac.FsSystem private ref Entry AcquireEntry(Buffer buffer, BufferAttribute attr) { // Validate pre-conditions. - Assert.True(Entries != null); + Assert.SdkRequiresNotNull(Entries); ref Entry entry = ref Unsafe.NullRef(); if (EntryCount < EntryCountMax) @@ -282,7 +283,7 @@ namespace LibHac.FsSystem entry = ref Entries[EntryCount]; entry.Initialize(PublishCacheHandle(), buffer, attr); EntryCount++; - Assert.True(EntryCount == 1 || Entries[EntryCount - 2].GetHandle() < entry.GetHandle()); + Assert.SdkAssert(EntryCount == 1 || Entries[EntryCount - 2].GetHandle() < entry.GetHandle()); } return ref entry; @@ -291,13 +292,13 @@ namespace LibHac.FsSystem private void ReleaseEntry(ref Entry entry) { // Validate pre-conditions. - Assert.True(Entries != null); - Assert.True(!Unsafe.IsNullRef(ref entry)); + Assert.SdkRequiresNotNull(Entries); + Assert.SdkRequiresNotNull(ref entry); // Ensure the entry is valid. Span entryBuffer = Entries; - Assert.True(!Unsafe.IsAddressLessThan(ref entry, ref MemoryMarshal.GetReference(entryBuffer))); - Assert.True(Unsafe.IsAddressLessThan(ref entry, + Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref entry, ref MemoryMarshal.GetReference(entryBuffer))); + Assert.SdkAssert(Unsafe.IsAddressLessThan(ref entry, ref Unsafe.Add(ref MemoryMarshal.GetReference(entryBuffer), entryBuffer.Length))); // Get the index of the entry. @@ -378,7 +379,7 @@ namespace LibHac.FsSystem private Buffer AllocateBufferImpl(int size, BufferAttribute attribute) { int order = BuddyHeap.GetOrderFromBytes((nuint)size); - Assert.True(order >= 0); + Assert.SdkAssert(order >= 0); // Allocate space on the heap Buffer buffer; @@ -397,7 +398,7 @@ namespace LibHac.FsSystem // Successfully allocated a buffer. int allocatedSize = (int)BuddyHeap.GetBytesFromOrder(order); - Assert.True(size <= allocatedSize); + Assert.SdkAssert(size <= allocatedSize); // Update heap stats int freeSize = (int)BuddyHeap.GetTotalFreeSize(); @@ -419,7 +420,7 @@ namespace LibHac.FsSystem private void DeallocateBufferImpl(Buffer buffer) { - Assert.True(BitUtil.IsPowerOfTwo(buffer.Length)); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(buffer.Length)); BuddyHeap.Free(buffer); } diff --git a/src/LibHac/FsSystem/FsPath.cs b/src/LibHac/FsSystem/FsPath.cs index ab311210..433f681e 100644 --- a/src/LibHac/FsSystem/FsPath.cs +++ b/src/LibHac/FsSystem/FsPath.cs @@ -25,7 +25,7 @@ namespace LibHac.FsSystem public static Result FromSpan(out FsPath fsPath, ReadOnlySpan path) { - Unsafe.SkipInit(out fsPath); + UnsafeHelpers.SkipParamInit(out fsPath); // Ensure null terminator even if the creation fails for safety fsPath.Str[MaxLength] = 0; diff --git a/src/LibHac/FsSystem/IndirectStorage.cs b/src/LibHac/FsSystem/IndirectStorage.cs index c5070fc4..ed07578c 100644 --- a/src/LibHac/FsSystem/IndirectStorage.cs +++ b/src/LibHac/FsSystem/IndirectStorage.cs @@ -71,22 +71,22 @@ namespace LibHac.FsSystem public void SetStorage(int index, SubStorage storage) { - Assert.InRange(index, 0, StorageCount); + Assert.SdkRequiresInRange(index, 0, StorageCount); DataStorage[index] = storage; } public void SetStorage(int index, IStorage storage, long offset, long size) { - Assert.InRange(index, 0, StorageCount); + Assert.SdkRequiresInRange(index, 0, StorageCount); DataStorage[index] = new SubStorage(storage, offset, size); } public Result GetEntryList(Span entryBuffer, out int outputEntryCount, long offset, long size) { // Validate pre-conditions - Assert.True(offset >= 0); - Assert.True(size >= 0); - Assert.True(IsInitialized()); + Assert.SdkRequiresLessEqual(0, offset); + Assert.SdkRequiresLessEqual(0, size); + Assert.SdkRequires(IsInitialized()); // Clear the out count outputEntryCount = 0; @@ -153,8 +153,8 @@ namespace LibHac.FsSystem protected override unsafe Result DoRead(long offset, Span destination) { // Validate pre-conditions - Assert.True(offset >= 0); - Assert.True(IsInitialized()); + Assert.SdkRequiresLessEqual(0, offset); + Assert.SdkRequires(IsInitialized()); // Succeed if there's nothing to read if (destination.Length == 0) @@ -206,9 +206,9 @@ namespace LibHac.FsSystem private Result OperatePerEntry(long offset, long size, OperateFunc func) { // Validate preconditions - Assert.True(offset >= 0); - Assert.True(size >= 0); - Assert.True(IsInitialized()); + Assert.SdkRequiresLessEqual(0, offset); + Assert.SdkRequiresLessEqual(0, size); + Assert.SdkRequires(IsInitialized()); // Succeed if there's nothing to operate on if (size == 0) @@ -272,12 +272,12 @@ namespace LibHac.FsSystem // Get the offset of the entry in the data we read long dataOffset = currentOffset - currentEntryOffset; long dataSize = nextEntryOffset - currentEntryOffset - dataOffset; - Assert.True(dataSize > 0); + Assert.SdkLess(0, dataSize); // Determine how much is left long remainingSize = endOffset - currentOffset; long currentSize = Math.Min(remainingSize, dataSize); - Assert.True(currentSize <= size); + Assert.SdkLessEqual(currentSize, size); { SubStorage currentStorage = DataStorage[currentEntry.StorageIndex]; diff --git a/src/LibHac/FsSystem/NcaUtils/Nca.cs b/src/LibHac/FsSystem/NcaUtils/Nca.cs index ebe3ad34..714595d7 100644 --- a/src/LibHac/FsSystem/NcaUtils/Nca.cs +++ b/src/LibHac/FsSystem/NcaUtils/Nca.cs @@ -659,7 +659,7 @@ namespace LibHac.FsSystem.NcaUtils { // NCA0 encrypts the entire NCA body using AES-XTS instead of // using different encryption types and IVs for each section. - Assert.Equal(0, Header.Version); + Assert.SdkEqual(0, Header.Version); if (openEncrypted == IsEncrypted) { diff --git a/src/LibHac/FsSystem/NcaUtils/NcaHeader.cs b/src/LibHac/FsSystem/NcaUtils/NcaHeader.cs index ce254b7d..92d59158 100644 --- a/src/LibHac/FsSystem/NcaUtils/NcaHeader.cs +++ b/src/LibHac/FsSystem/NcaUtils/NcaHeader.cs @@ -254,7 +254,7 @@ namespace LibHac.FsSystem.NcaUtils private static bool CheckIfDecrypted(ReadOnlySpan header) { - Assert.True(header.Length >= 0x400); + Assert.SdkRequiresGreaterEqual(header.Length, 0x400); // Check the magic value if (header[0x200] != 'N' || header[0x201] != 'C' || header[0x202] != 'A') diff --git a/src/LibHac/FsSystem/PooledBuffer.cs b/src/LibHac/FsSystem/PooledBuffer.cs index e2d84bd9..c410172b 100644 --- a/src/LibHac/FsSystem/PooledBuffer.cs +++ b/src/LibHac/FsSystem/PooledBuffer.cs @@ -33,13 +33,13 @@ namespace LibHac.FsSystem public Span GetBuffer() { - Assert.NotNull(Array); + Assert.SdkRequiresNotNull(Array); return Array.AsSpan(0, Length); } public int GetSize() { - Assert.NotNull(Array); + Assert.SdkRequiresNotNull(Array); return Length; } @@ -56,10 +56,10 @@ namespace LibHac.FsSystem private void AllocateCore(int idealSize, int requiredSize, bool enableLargeCapacity) { - Assert.Null(Array); + Assert.SdkRequiresNull(Array); // Check that we can allocate this size. - Assert.True(requiredSize <= GetAllocatableSizeMaxCore(enableLargeCapacity)); + Assert.SdkRequiresLessEqual(requiredSize, GetAllocatableSizeMaxCore(enableLargeCapacity)); int targetSize = Math.Min(Math.Max(idealSize, requiredSize), GetAllocatableSizeMaxCore(enableLargeCapacity)); @@ -80,17 +80,17 @@ namespace LibHac.FsSystem { // Shrink the buffer to empty. Shrink(0); - Assert.Null(Array); + Assert.SdkNull(Array); } public void Shrink(int idealSize) { - Assert.True(idealSize <= GetAllocatableSizeMaxCore(true)); + Assert.SdkRequiresLessEqual(idealSize, GetAllocatableSizeMaxCore(true)); // Check if we actually need to shrink. if (Length > idealSize) { - Assert.NotNull(Array); + Assert.SdkRequiresNotNull(Array); // Pretend we shrank the buffer. Length = idealSize; diff --git a/src/LibHac/FsSystem/Save/BufferedStorage.cs b/src/LibHac/FsSystem/Save/BufferedStorage.cs index 4494e757..9e3dd1b5 100644 --- a/src/LibHac/FsSystem/Save/BufferedStorage.cs +++ b/src/LibHac/FsSystem/Save/BufferedStorage.cs @@ -61,8 +61,8 @@ namespace LibHac.FsSystem.Save PrevIndex = InvalidIndex; // End default constructor code - Assert.NotNull(bufferedStorage); - Assert.True(BufferedStorage == null); + Assert.SdkRequiresNotNull(bufferedStorage); + Assert.SdkRequires(BufferedStorage == null); BufferedStorage = bufferedStorage; Link(); @@ -70,9 +70,9 @@ namespace LibHac.FsSystem.Save public void FinalizeObject() { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.Equal(0, ReferenceCount); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequiresEqual(0, ReferenceCount); // If we're valid, acquire our cache handle and free our buffer. if (IsValid()) @@ -80,7 +80,7 @@ namespace LibHac.FsSystem.Save IBufferManager bufferManager = BufferedStorage.BufferManager; if (!_isDirty) { - Assert.True(MemoryRange.IsNull); + Assert.SdkAssert(MemoryRange.IsNull); MemoryRange = bufferManager.AcquireCache(CacheHandle); } @@ -107,15 +107,15 @@ namespace LibHac.FsSystem.Save /// public void Link() { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.True(ReferenceCount > 0); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequiresLess(0, ReferenceCount); ReferenceCount--; if (ReferenceCount == 0) { - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); + Assert.SdkAssert(NextIndex == InvalidIndex); + Assert.SdkAssert(PrevIndex == InvalidIndex); // If the fetch list is empty we can simply add it as the only cache in the list. if (BufferedStorage.NextFetchCacheIndex == InvalidIndex) @@ -140,8 +140,8 @@ namespace LibHac.FsSystem.Save } while (cache.Index != BufferedStorage.NextFetchCacheIndex); // Verify the end of the fetch list loops back to the start. - Assert.True(BufferedStorage.NextFetchCache.PrevIndex != InvalidIndex); - Assert.Equal(BufferedStorage.NextFetchCache.Prev.NextIndex, + Assert.SdkAssert(BufferedStorage.NextFetchCache.PrevIndex != InvalidIndex); + Assert.SdkEqual(BufferedStorage.NextFetchCache.Prev.NextIndex, BufferedStorage.NextFetchCacheIndex); // Link into the fetch list. @@ -190,17 +190,17 @@ namespace LibHac.FsSystem.Save /// public void Unlink() { - Assert.NotNull(BufferedStorage); - Assert.True(ReferenceCount >= 0); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresGreaterEqual(ReferenceCount, 0); ReferenceCount++; if (ReferenceCount == 1) { // If we're the first to grab this Cache, the Cache should be in the BufferedStorage's fetch list. - Assert.True(NextIndex != InvalidIndex); - Assert.True(PrevIndex != InvalidIndex); - Assert.True(Next.PrevIndex == Index); - Assert.True(Prev.NextIndex == Index); + Assert.SdkNotEqual(NextIndex, InvalidIndex); + Assert.SdkNotEqual(PrevIndex, InvalidIndex); + Assert.SdkEqual(Next.PrevIndex, Index); + Assert.SdkEqual(Prev.NextIndex, Index); // Set the new fetch list head if this Cache is the current head if (BufferedStorage.NextFetchCacheIndex == Index) @@ -224,8 +224,8 @@ namespace LibHac.FsSystem.Save } else { - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); + Assert.SdkEqual(NextIndex, InvalidIndex); + Assert.SdkEqual(PrevIndex, InvalidIndex); } } @@ -238,18 +238,18 @@ namespace LibHac.FsSystem.Save /// The buffer in which to place the read data. public void Read(long offset, Span buffer) { - Assert.NotNull(BufferedStorage); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(IsValid()); - Assert.True(Hits(offset, 1)); - Assert.True(!MemoryRange.IsNull); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(IsValid()); + Assert.SdkRequires(Hits(offset, 1)); + Assert.SdkRequires(!MemoryRange.IsNull); long readOffset = offset - Offset; long readableOffsetMax = BufferedStorage.BlockSize - buffer.Length; - Assert.True(readOffset >= 0); - Assert.True(readOffset <= readableOffsetMax); + Assert.SdkLessEqual(0, readOffset); + Assert.SdkLessEqual(readOffset, readableOffsetMax); Span cacheBuffer = MemoryRange.Span.Slice((int)readOffset, buffer.Length); cacheBuffer.CopyTo(buffer); @@ -264,18 +264,18 @@ namespace LibHac.FsSystem.Save /// The buffer containing the data to be written. public void Write(long offset, ReadOnlySpan buffer) { - Assert.NotNull(BufferedStorage); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(IsValid()); - Assert.True(Hits(offset, 1)); - Assert.True(!MemoryRange.IsNull); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(IsValid()); + Assert.SdkRequires(Hits(offset, 1)); + Assert.SdkRequires(!MemoryRange.IsNull); long writeOffset = offset - Offset; long writableOffsetMax = BufferedStorage.BlockSize - buffer.Length; - Assert.True(writeOffset >= 0); - Assert.True(writeOffset <= writableOffsetMax); + Assert.SdkLessEqual(0, writeOffset); + Assert.SdkLessEqual(writeOffset, writableOffsetMax); Span cacheBuffer = MemoryRange.Span.Slice((int)writeOffset, buffer.Length); buffer.CopyTo(cacheBuffer); @@ -289,14 +289,14 @@ namespace LibHac.FsSystem.Save /// The of the operation. public Result Flush() { - Assert.NotNull(BufferedStorage); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(IsValid()); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(IsValid()); if (_isDirty) { - Assert.True(!MemoryRange.IsNull); + Assert.SdkRequires(!MemoryRange.IsNull); long baseSize = BufferedStorage.BaseStorageSize; long blockSize = BufferedStorage.BlockSize; @@ -304,7 +304,7 @@ namespace LibHac.FsSystem.Save SubStorage baseStorage = BufferedStorage.BaseStorage; Span cacheBuffer = MemoryRange.Span; - Assert.True(flushSize == cacheBuffer.Length); + Assert.SdkEqual(flushSize, cacheBuffer.Length); Result rc = baseStorage.Write(Offset, cacheBuffer); if (rc.IsFailure()) return rc; @@ -327,12 +327,12 @@ namespace LibHac.FsSystem.Save /// is prepared to fetch; if not. public (Result Result, bool IsPrepared) PrepareFetch() { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(IsValid()); - Assert.True(Monitor.IsEntered(BufferedStorage.Locker)); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(IsValid()); + Assert.SdkRequires(Monitor.IsEntered(BufferedStorage.Locker)); (Result Result, bool IsPrepared) result = (Result.Success, false); @@ -357,13 +357,13 @@ namespace LibHac.FsSystem.Save /// public void UnprepareFetch() { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(!IsValid()); - Assert.True(!_isDirty); - Assert.True(Monitor.IsEntered(BufferedStorage.Locker)); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(!IsValid()); + Assert.SdkRequires(!_isDirty); + Assert.SdkRequires(Monitor.IsEntered(BufferedStorage.Locker)); _isValid = true; ReferenceCount = 1; @@ -377,12 +377,12 @@ namespace LibHac.FsSystem.Save /// : A buffer could not be allocated. public Result Fetch(long offset) { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(!IsValid()); - Assert.True(!_isDirty); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(!IsValid()); + Assert.SdkRequires(!_isDirty); Result rc; @@ -399,7 +399,7 @@ namespace LibHac.FsSystem.Save if (rc.IsFailure()) return rc; Offset = fetchParam.Offset; - Assert.True(Hits(offset, 1)); + Assert.SdkAssert(Hits(offset, 1)); return Result.Success; } @@ -415,13 +415,13 @@ namespace LibHac.FsSystem.Save /// : A buffer could not be allocated. public Result FetchFromBuffer(long offset, ReadOnlySpan buffer) { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.True(NextIndex == InvalidIndex); - Assert.True(PrevIndex == InvalidIndex); - Assert.True(!IsValid()); - Assert.True(!_isDirty); - Assert.True(Alignment.IsAlignedPow2(offset, (uint)BufferedStorage.BlockSize)); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequiresEqual(NextIndex, InvalidIndex); + Assert.SdkRequiresEqual(PrevIndex, InvalidIndex); + Assert.SdkRequires(!IsValid()); + Assert.SdkRequires(!_isDirty); + Assert.SdkRequiresAligned((ulong)offset, (int)BufferedStorage.BlockSize); // Make sure this Cache has an allocated buffer if (MemoryRange.IsNull) @@ -431,12 +431,12 @@ namespace LibHac.FsSystem.Save } CalcFetchParameter(out FetchParameter fetchParam, offset); - Assert.Equal(fetchParam.Offset, offset); - Assert.True(fetchParam.Buffer.Length <= buffer.Length); + Assert.SdkEqual(fetchParam.Offset, offset); + Assert.SdkLessEqual(fetchParam.Buffer.Length, buffer.Length); buffer.Slice(0, fetchParam.Buffer.Length).CopyTo(fetchParam.Buffer); Offset = fetchParam.Offset; - Assert.True(Hits(offset, 1)); + Assert.SdkAssert(Hits(offset, 1)); return Result.Success; } @@ -448,9 +448,9 @@ namespace LibHac.FsSystem.Save /// if the buffer has been evicted from the cache. public bool TryAcquireCache() { - Assert.NotNull(BufferedStorage); - Assert.NotNull(BufferedStorage.BufferManager); - Assert.True(IsValid()); + Assert.SdkRequiresNotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage.BufferManager); + Assert.SdkRequires(IsValid()); if (!MemoryRange.IsNull) return true; @@ -465,7 +465,7 @@ namespace LibHac.FsSystem.Save /// public void Invalidate() { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); _isValid = false; } @@ -476,7 +476,7 @@ namespace LibHac.FsSystem.Save /// or if anybody currently has a reference to this Cache. Otherwise, . public bool IsValid() { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); return _isValid || ReferenceCount > 0; } @@ -489,7 +489,7 @@ namespace LibHac.FsSystem.Save /// Otherwise, . public bool IsDirty() { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); return _isDirty; } @@ -503,7 +503,7 @@ namespace LibHac.FsSystem.Save /// Otherwise, . public bool Hits(long offset, long size) { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); long blockSize = BufferedStorage.BlockSize; return (offset < Offset + blockSize) && (Offset < offset + size); @@ -518,7 +518,7 @@ namespace LibHac.FsSystem.Save private Result AllocateFetchBuffer() { IBufferManager bufferManager = BufferedStorage.BufferManager; - Assert.True(bufferManager.AcquireCache(CacheHandle).IsNull); + Assert.SdkAssert(bufferManager.AcquireCache(CacheHandle).IsNull); Result rc = BufferManagerUtility.AllocateBufferUsingBufferManagerContext(out Buffer bufferTemp, bufferManager, (int)BufferedStorage.BlockSize, new IBufferManager.BufferAttribute(), @@ -545,8 +545,8 @@ namespace LibHac.FsSystem.Save long cacheSize = Math.Min(blockSize, remainingSize); Span cacheBuffer = MemoryRange.Span.Slice(0, (int)cacheSize); - Assert.True(offset >= 0); - Assert.True(offset < baseSize); + Assert.SdkLessEqual(0, offset); + Assert.SdkLess(offset, baseSize); fetchParam = new FetchParameter { @@ -569,7 +569,7 @@ namespace LibHac.FsSystem.Save public SharedCache(BufferedStorage bufferedStorage) { - Assert.NotNull(bufferedStorage); + Assert.SdkRequiresNotNull(bufferedStorage); Cache = default; StartCache = new Ref(ref bufferedStorage.NextAcquireCache); BufferedStorage = bufferedStorage; @@ -593,23 +593,23 @@ namespace LibHac.FsSystem.Save /// or if all matching Caches have already been iterated. public bool AcquireNextOverlappedCache(long offset, long size) { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); bool isFirst = Cache.IsNull; ref Cache start = ref isFirst ? ref StartCache.Value : ref Unsafe.Add(ref Cache.Value, 1); // Make sure the Cache instance is in-range. - Assert.False(Unsafe.IsAddressLessThan(ref start, + Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref start, ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches))); - Assert.False(Unsafe.IsAddressGreaterThan(ref start, + Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref start, ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches), BufferedStorage.CacheCount))); lock (BufferedStorage.Locker) { Release(); - Assert.True(Cache.IsNull); + Assert.SdkAssert(Cache.IsNull); for (ref Cache cache = ref start; ; cache = ref Unsafe.Add(ref cache, 1)) { @@ -650,7 +650,7 @@ namespace LibHac.FsSystem.Save /// or if all dirty Caches have already been iterated. public bool AcquireNextDirtyCache() { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); ref Cache start = ref Cache.IsNull ? ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches) @@ -660,13 +660,13 @@ namespace LibHac.FsSystem.Save BufferedStorage.CacheCount); // Validate the range. - Assert.False(Unsafe.IsAddressLessThan(ref start, + Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref start, ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches))); - Assert.False(Unsafe.IsAddressGreaterThan(ref start, ref end)); + Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref start, ref end)); Release(); - Assert.True(Cache.IsNull); + Assert.SdkAssert(Cache.IsNull); // Find the next dirty Cache for (ref Cache cache = ref start; @@ -693,7 +693,7 @@ namespace LibHac.FsSystem.Save /// or if all valid Caches have already been iterated. public bool AcquireNextValidCache() { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); ref Cache start = ref Cache.IsNull ? ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches) @@ -703,13 +703,13 @@ namespace LibHac.FsSystem.Save BufferedStorage.CacheCount); // Validate the range. - Assert.False(Unsafe.IsAddressLessThan(ref start, + Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref start, ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches))); - Assert.False(Unsafe.IsAddressGreaterThan(ref start, ref end)); + Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref start, ref end)); Release(); - Assert.True(Cache.IsNull); + Assert.SdkAssert(Cache.IsNull); // Find the next valid Cache for (ref Cache cache = ref start; @@ -736,12 +736,12 @@ namespace LibHac.FsSystem.Save /// Otherwise, . public bool AcquireFetchableCache() { - Assert.NotNull(BufferedStorage); + Assert.SdkRequiresNotNull(BufferedStorage); lock (BufferedStorage.Locker) { Release(); - Assert.True(Cache.IsNull); + Assert.SdkAssert(Cache.IsNull); Cache = new Ref(ref BufferedStorage.NextFetchCache); @@ -766,7 +766,7 @@ namespace LibHac.FsSystem.Save /// The buffer in which to place the read data. public void Read(long offset, Span buffer) { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); Cache.Value.Read(offset, buffer); } @@ -779,7 +779,7 @@ namespace LibHac.FsSystem.Save /// The buffer containing the data to be written. public void Write(long offset, ReadOnlySpan buffer) { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); Cache.Value.Write(offset, buffer); } @@ -790,7 +790,7 @@ namespace LibHac.FsSystem.Save /// The of the operation. public Result Flush() { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); return Cache.Value.Flush(); } @@ -800,7 +800,7 @@ namespace LibHac.FsSystem.Save /// public void Invalidate() { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); Cache.Value.Invalidate(); } @@ -813,7 +813,7 @@ namespace LibHac.FsSystem.Save /// covers any of the input range. Otherwise, . public bool Hits(long offset, long size) { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); return Cache.Value.Hits(offset, size); } @@ -825,10 +825,10 @@ namespace LibHac.FsSystem.Save if (!Cache.IsNull) { // Make sure the Cache instance is in-range. - Assert.False(Unsafe.IsAddressLessThan(ref Cache.Value, + Assert.SdkAssert(!Unsafe.IsAddressLessThan(ref Cache.Value, ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches))); - Assert.False(Unsafe.IsAddressGreaterThan(ref Cache.Value, + Assert.SdkAssert(!Unsafe.IsAddressGreaterThan(ref Cache.Value, ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(BufferedStorage.Caches), BufferedStorage.CacheCount))); @@ -850,7 +850,7 @@ namespace LibHac.FsSystem.Save public UniqueCache(BufferedStorage bufferedStorage) { - Assert.NotNull(bufferedStorage); + Assert.SdkRequiresNotNull(bufferedStorage); Cache = default; BufferedStorage = bufferedStorage; } @@ -878,8 +878,8 @@ namespace LibHac.FsSystem.Save /// access to the was gained; if not. public (Result Result, bool wasUpgradeSuccessful) Upgrade(in SharedCache sharedCache) { - Assert.True(BufferedStorage == sharedCache.BufferedStorage); - Assert.True(!sharedCache.Cache.IsNull); + Assert.SdkRequires(BufferedStorage == sharedCache.BufferedStorage); + Assert.SdkRequires(!sharedCache.Cache.IsNull); lock (BufferedStorage.Locker) { @@ -901,7 +901,7 @@ namespace LibHac.FsSystem.Save /// : A buffer could not be allocated. public Result Fetch(long offset) { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); return Cache.Value.Fetch(offset); } @@ -917,7 +917,7 @@ namespace LibHac.FsSystem.Save /// : A buffer could not be allocated. public Result FetchFromBuffer(long offset, ReadOnlySpan buffer) { - Assert.True(!Cache.IsNull); + Assert.SdkRequires(!Cache.IsNull); return Cache.Value.FetchFromBuffer(offset, buffer); } @@ -987,11 +987,11 @@ namespace LibHac.FsSystem.Save /// public Result Initialize(SubStorage baseStorage, IBufferManager bufferManager, int blockSize, int cacheCount) { - Assert.NotNull(baseStorage); - Assert.NotNull(bufferManager); - Assert.True(blockSize > 0); - Assert.True(BitUtil.IsPowerOfTwo(blockSize)); - Assert.True(cacheCount > 0); + Assert.SdkRequiresNotNull(baseStorage); + Assert.SdkRequiresNotNull(bufferManager); + Assert.SdkRequiresLess(0, blockSize); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(blockSize)); + Assert.SdkRequiresLess(0, cacheCount); // Get the base storage size. Result rc = baseStorage.GetSize(out _baseStorageSize); @@ -1055,7 +1055,7 @@ namespace LibHac.FsSystem.Save protected override Result DoRead(long offset, Span destination) { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); // Succeed if zero size. if (destination.Length == 0) @@ -1067,7 +1067,7 @@ namespace LibHac.FsSystem.Save protected override Result DoWrite(long offset, ReadOnlySpan source) { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); // Succeed if zero size. if (source.Length == 0) @@ -1079,7 +1079,7 @@ namespace LibHac.FsSystem.Save protected override Result DoGetSize(out long size) { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); size = BaseStorageSize; return Result.Success; @@ -1087,7 +1087,7 @@ namespace LibHac.FsSystem.Save protected override Result DoSetSize(long size) { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); Result rc; long prevSize = BaseStorageSize; @@ -1108,7 +1108,7 @@ namespace LibHac.FsSystem.Save cache.Invalidate(); } - Assert.True(!cache.AcquireNextOverlappedCache(invalidateOffset, invalidateSize)); + Assert.SdkAssert(!cache.AcquireNextOverlappedCache(invalidateOffset, invalidateSize)); } } else if (size < prevSize) @@ -1146,7 +1146,7 @@ namespace LibHac.FsSystem.Save protected override Result DoOperateRange(Span outBuffer, OperationId operationId, long offset, long size, ReadOnlySpan inBuffer) { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); // Invalidate caches if needed. if (operationId == OperationId.InvalidateCache) @@ -1162,7 +1162,7 @@ namespace LibHac.FsSystem.Save protected override Result DoFlush() { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); // Flush caches. using var cache = new SharedCache(this); @@ -1181,7 +1181,7 @@ namespace LibHac.FsSystem.Save /// public void InvalidateCaches() { - Assert.True(IsInitialized()); + Assert.SdkRequires(IsInitialized()); using var cache = new SharedCache(this); while (cache.AcquireNextValidCache()) @@ -1252,7 +1252,8 @@ namespace LibHac.FsSystem.Save /// The of the operation. private Result ReadCore(long offset, Span destination) { - Assert.NotNull(Caches); + Assert.SdkRequiresNotNull(Caches); + Assert.SdkRequiresNotNull(destination); // Validate the offset. long baseStorageSize = BaseStorageSize; @@ -1469,7 +1470,7 @@ namespace LibHac.FsSystem.Save } long currentOffset = currentOffsetEnd - currentSize; - Assert.True(currentOffset >= 0); + Assert.SdkGreaterEqual(currentOffset, 0); using var cache = new SharedCache(this); @@ -1617,7 +1618,8 @@ namespace LibHac.FsSystem.Save private Result WriteCore(long offset, ReadOnlySpan source) { - Assert.NotNull(Caches); + Assert.SdkRequiresNotNull(Caches); + Assert.SdkRequiresNotNull(source); // Validate the offset. long baseStorageSize = BaseStorageSize; diff --git a/src/LibHac/FsSystem/UniqueLockSemaphore.cs b/src/LibHac/FsSystem/UniqueLockSemaphore.cs index 1a326e6f..766dab15 100644 --- a/src/LibHac/FsSystem/UniqueLockSemaphore.cs +++ b/src/LibHac/FsSystem/UniqueLockSemaphore.cs @@ -80,7 +80,7 @@ namespace LibHac.FsSystem Shared.Move(out _semaphore, ref semaphore); Shared.Move(out _pinnedObject, ref pinnedObject); - Assert.True(_semaphore.IsLocked); + Assert.SdkAssert(_semaphore.IsLocked); } public void Dispose() diff --git a/src/LibHac/Kernel/InitialProcessBinaryReader.cs b/src/LibHac/Kernel/InitialProcessBinaryReader.cs index dc53891e..041ee2e9 100644 --- a/src/LibHac/Kernel/InitialProcessBinaryReader.cs +++ b/src/LibHac/Kernel/InitialProcessBinaryReader.cs @@ -64,7 +64,7 @@ namespace LibHac.Kernel private static Result GetKipOffsets(out (int offset, int size)[] kipOffsets, IStorage iniStorage, int processCount) { - Assert.True(processCount <= MaxProcessCount); + Assert.SdkRequiresLessEqual(processCount, MaxProcessCount); UnsafeHelpers.SkipParamInit(out kipOffsets); diff --git a/src/LibHac/Kvdb/FlatMapKeyValueStore.cs b/src/LibHac/Kvdb/FlatMapKeyValueStore.cs index 55bdc945..a4af8343 100644 --- a/src/LibHac/Kvdb/FlatMapKeyValueStore.cs +++ b/src/LibHac/Kvdb/FlatMapKeyValueStore.cs @@ -410,8 +410,8 @@ namespace LibHac.Kvdb public Result Initialize(int capacity, MemoryResource memoryResource) { // Initialize must only be called once. - Assert.Null(_entries); - Assert.NotNull(memoryResource); + Assert.SdkRequiresNull(_entries); + Assert.SdkRequiresNotNull(memoryResource); // FS uses the provided MemoryResource to allocate the KeyValue array. // We can't do that here because the array will contain managed references. @@ -487,7 +487,7 @@ namespace LibHac.Kvdb if (_count > 0) { // The key being added must be greater than the last key in the list. - Assert.True(key.CompareTo(_entries[_count - 1].Key) > 0); + Assert.SdkGreater(key, _entries[_count - 1].Key); } _entries[_count] = new KeyValue(in key, value); @@ -671,7 +671,7 @@ namespace LibHac.Kvdb // An entry was added. entryIndex is the index of the new entry. // Only one entry can be added at a time. - Assert.Equal(newLength, _length + 1); + Assert.SdkEqual(newLength, _length + 1); if (entryIndex <= _index) { @@ -687,7 +687,7 @@ namespace LibHac.Kvdb // An entry was removed. entryIndex is the index where the removed entry used to be. // Only one entry can be removed at a time. - Assert.Equal(newLength, _length - 1); + Assert.SdkEqual(newLength, _length - 1); if (entryIndex < _index) { diff --git a/src/LibHac/Kvdb/KeyValueArchive.cs b/src/LibHac/Kvdb/KeyValueArchive.cs index 3f08a10a..90db410b 100644 --- a/src/LibHac/Kvdb/KeyValueArchive.cs +++ b/src/LibHac/Kvdb/KeyValueArchive.cs @@ -75,7 +75,7 @@ namespace LibHac.Kvdb UnsafeHelpers.SkipParamInit(out count); // This should only be called at the start of reading stream. - Assert.True(_offset == 0); + Assert.SdkRequiresEqual(_offset, 0); // Read and validate header. var header = new KeyValueArchiveHeader(); @@ -95,7 +95,7 @@ namespace LibHac.Kvdb UnsafeHelpers.SkipParamInit(out keySize, out valueSize); // This should only be called after ReadEntryCount. - Assert.NotEqual(_offset, 0); + Assert.SdkNotEqual(_offset, 0); // Peek the next entry header. Unsafe.SkipInit(out KeyValueArchiveEntryHeader header); @@ -115,7 +115,7 @@ namespace LibHac.Kvdb public Result ReadKeyValue(Span keyBuffer, Span valueBuffer) { // This should only be called after ReadEntryCount. - Assert.NotEqual(_offset, 0); + Assert.SdkNotEqual(_offset, 0); // Read the next entry header. Unsafe.SkipInit(out KeyValueArchiveEntryHeader header); @@ -127,8 +127,8 @@ namespace LibHac.Kvdb return ResultKvdb.InvalidKeyValue.Log(); // Key size and Value size must be correct. - Assert.Equal(keyBuffer.Length, header.KeySize); - Assert.Equal(valueBuffer.Length, header.ValueSize); + Assert.SdkEqual(keyBuffer.Length, header.KeySize); + Assert.SdkEqual(valueBuffer.Length, header.ValueSize); rc = Read(keyBuffer); if (rc.IsFailure()) return rc; @@ -176,8 +176,8 @@ namespace LibHac.Kvdb private void Write(ReadOnlySpan source) { // Bounds check. - Assert.True(_offset + source.Length <= _buffer.Length && - _offset + source.Length > _offset); + Abort.DoAbortUnless(_offset + source.Length <= _buffer.Length && + _offset + source.Length > _offset); source.CopyTo(_buffer.Slice(_offset)); _offset += source.Length; @@ -186,7 +186,7 @@ namespace LibHac.Kvdb public void WriteHeader(int entryCount) { // This should only be called at start of write. - Assert.Equal(_offset, 0); + Assert.SdkEqual(_offset, 0); var header = new KeyValueArchiveHeader(entryCount); Write(SpanHelpers.AsByteSpan(ref header)); @@ -195,7 +195,7 @@ namespace LibHac.Kvdb public void WriteEntry(ReadOnlySpan key, ReadOnlySpan value) { // This should only be called after writing header. - Assert.NotEqual(_offset, 0); + Assert.SdkNotEqual(_offset, 0); var header = new KeyValueArchiveEntryHeader(key.Length, value.Length); Write(SpanHelpers.AsByteSpan(ref header)); diff --git a/src/LibHac/LibHac.csproj b/src/LibHac/LibHac.csproj index c17ad8a7..ea2edf22 100644 --- a/src/LibHac/LibHac.csproj +++ b/src/LibHac/LibHac.csproj @@ -29,6 +29,10 @@ $(NoWarn);1591 + + $(DefineConstants);ENABLE_ASSERTS + + diff --git a/src/LibHac/Lr/Path.cs b/src/LibHac/Lr/Path.cs index f2dadc64..0196420d 100644 --- a/src/LibHac/Lr/Path.cs +++ b/src/LibHac/Lr/Path.cs @@ -24,7 +24,7 @@ namespace LibHac.Lr [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void InitEmpty(out Path path) { - Unsafe.SkipInit(out path); + UnsafeHelpers.SkipParamInit(out path); SpanHelpers.AsByteSpan(ref path)[0] = 0; } diff --git a/src/LibHac/Os/Impl/InternalConditionVariable-os.net.cs b/src/LibHac/Os/Impl/InternalConditionVariable-os.net.cs index b6d571b3..a8c64a41 100644 --- a/src/LibHac/Os/Impl/InternalConditionVariable-os.net.cs +++ b/src/LibHac/Os/Impl/InternalConditionVariable-os.net.cs @@ -12,7 +12,7 @@ namespace LibHac.Os.Impl public void Signal() { - Assert.False(Monitor.IsEntered(_obj)); + Assert.SdkRequires(!Monitor.IsEntered(_obj)); Monitor.Enter(_obj); Monitor.Pulse(_obj); @@ -21,7 +21,7 @@ namespace LibHac.Os.Impl public void Broadcast() { - Assert.False(Monitor.IsEntered(_obj)); + Assert.SdkRequires(!Monitor.IsEntered(_obj)); Monitor.Enter(_obj); Monitor.PulseAll(_obj); @@ -30,7 +30,7 @@ namespace LibHac.Os.Impl public void Wait(ref InternalCriticalSection cs) { - Assert.False(Monitor.IsEntered(_obj)); + Assert.SdkRequires(!Monitor.IsEntered(_obj)); Abort.DoAbortUnless(cs.IsLockedByCurrentThread()); // Monitor.Wait doesn't allow specifying a separate mutex object. Workaround this by manually @@ -45,7 +45,7 @@ namespace LibHac.Os.Impl public ConditionVariableStatus TimedWait(ref InternalCriticalSection cs, in TimeoutHelper timeoutHelper) { - Assert.False(Monitor.IsEntered(_obj)); + Assert.SdkRequires(!Monitor.IsEntered(_obj)); Abort.DoAbortUnless(cs.IsLockedByCurrentThread()); TimeSpan remainingTime = timeoutHelper.GetTimeLeftOnTarget(); diff --git a/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs b/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs index ae06a2df..1c0c9f67 100644 --- a/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs +++ b/src/LibHac/Os/Impl/ReaderWriterLockImpl-os.net.cs @@ -13,7 +13,7 @@ namespace LibHac.Os.Impl // If we already own the lock, no additional action is needed if (rwLock.OwnerThread == Environment.CurrentManagedThreadId) { - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1); + Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u); } // Otherwise we might need to block until we can acquire the read lock else @@ -27,8 +27,8 @@ namespace LibHac.Os.Impl DecReadLockWaiterCount(ref GetLockCount(ref rwLock)); } - Assert.True(GetWriteLockCount(in rwLock) == 0); - Assert.True(rwLock.OwnerThread == 0); + Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkEqual(rwLock.OwnerThread, 0); } IncReadLockCount(ref GetLockCount(ref rwLock)); @@ -41,7 +41,7 @@ namespace LibHac.Os.Impl // Acquire the lock if we already have write access if (rwLock.OwnerThread == Environment.CurrentManagedThreadId) { - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1); + Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u); IncReadLockCount(ref GetLockCount(ref rwLock)); return true; @@ -55,8 +55,8 @@ namespace LibHac.Os.Impl } // Otherwise acquire the lock - Assert.True(GetWriteLockCount(in rwLock) == 0); - Assert.True(rwLock.OwnerThread == 0); + Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkEqual(rwLock.OwnerThread, 0); IncReadLockCount(ref GetLockCount(ref rwLock)); return true; @@ -66,13 +66,13 @@ namespace LibHac.Os.Impl { using ScopedLock lk = ScopedLock.Lock(ref GetLockCount(ref rwLock).Cs); - Assert.True(GetReadLockCount(in GetLockCount(ref rwLock)) > 0); - DecReadLockWaiterCount(ref GetLockCount(ref rwLock)); + Assert.SdkLess(0u, GetReadLockCount(in GetLockCount(ref rwLock))); + DecReadLockCount(ref GetLockCount(ref rwLock)); // If we own the lock, check if we need to release ownership and signal any waiting threads if (rwLock.OwnerThread == Environment.CurrentManagedThreadId) { - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1); + Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u); // Return if we still hold any locks if (GetWriteLockCount(in rwLock) != 0 || GetReadLockCount(in GetLockCount(ref rwLock)) != 0) @@ -98,9 +98,9 @@ namespace LibHac.Os.Impl // Otherwise we need to signal the next writer if we were the only reader else { - Assert.True(GetWriteLockCount(in rwLock) == 0); - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 0); - Assert.True(rwLock.OwnerThread == 0); + Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 0u); + Assert.SdkEqual(rwLock.OwnerThread, 0); // Signal the next writer if no readers are left if (GetReadLockCount(in GetLockCount(ref rwLock)) == 0 && @@ -121,7 +121,7 @@ namespace LibHac.Os.Impl // Increase the write lock count if we already own the lock if (rwLock.OwnerThread == currentThread) { - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1); + Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u); IncWriteLockCount(ref rwLock); return; @@ -136,8 +136,8 @@ namespace LibHac.Os.Impl DecWriteLockWaiterCount(ref GetLockCount(ref rwLock)); } - Assert.True(GetWriteLockCount(in rwLock) == 0); - Assert.True(rwLock.OwnerThread == 0); + Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkEqual(rwLock.OwnerThread, 0); // Acquire the lock IncWriteLockCount(ref rwLock); @@ -154,7 +154,7 @@ namespace LibHac.Os.Impl // Acquire the lock if we already have write access if (rwLock.OwnerThread == currentThread) { - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) == 1); + Assert.SdkEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 1u); IncWriteLockCount(ref rwLock); return true; @@ -168,8 +168,8 @@ namespace LibHac.Os.Impl } // Otherwise acquire the lock - Assert.True(GetWriteLockCount(in rwLock) == 0); - Assert.True(rwLock.OwnerThread == 0); + Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkEqual(rwLock.OwnerThread, 0); IncWriteLockCount(ref rwLock); SetWriteLocked(ref GetLockCount(ref rwLock)); @@ -181,9 +181,9 @@ namespace LibHac.Os.Impl { using ScopedLock lk = ScopedLock.Lock(ref GetLockCount(ref rwLock).Cs); - Assert.True(GetWriteLockCount(in rwLock) > 0); - Assert.True(GetWriteLocked(in GetLockCount(ref rwLock)) != 0); - Assert.True(rwLock.OwnerThread == Environment.CurrentManagedThreadId); + Assert.SdkEqual(GetWriteLockCount(in rwLock), 0u); + Assert.SdkNotEqual(GetWriteLocked(in GetLockCount(ref rwLock)), 0u); + Assert.SdkEqual(rwLock.OwnerThread, Environment.CurrentManagedThreadId); DecWriteLockCount(ref rwLock); diff --git a/src/LibHac/Os/Impl/ReaderWriterLockImpl.cs b/src/LibHac/Os/Impl/ReaderWriterLockImpl.cs index 318ff295..6d751a3a 100644 --- a/src/LibHac/Os/Impl/ReaderWriterLockImpl.cs +++ b/src/LibHac/Os/Impl/ReaderWriterLockImpl.cs @@ -67,56 +67,56 @@ namespace LibHac.Os.Impl public static void IncReadLockCount(ref ReaderWriterLockType.LockCountType lc) { uint readLockCount = lc.Counter.ReadLockCount; - Assert.True(readLockCount < ReaderWriterLock.ReaderWriterLockCountMax); + Assert.SdkLess(readLockCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax); lc.Counter.ReadLockCount = readLockCount + 1; } public static void DecReadLockCount(ref ReaderWriterLockType.LockCountType lc) { uint readLockCount = lc.Counter.ReadLockCount; - Assert.True(readLockCount > 0); + Assert.SdkGreater(readLockCount, 0u); lc.Counter.ReadLockCount = readLockCount - 1; } public static void IncReadLockWaiterCount(ref ReaderWriterLockType.LockCountType lc) { uint readLockWaiterCount = lc.Counter.ReadLockWaiterCount; - Assert.True(readLockWaiterCount < ReaderWriterLock.ReadWriteLockWaiterCountMax); + Assert.SdkLess(readLockWaiterCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax); lc.Counter.ReadLockWaiterCount = readLockWaiterCount + 1; } public static void DecReadLockWaiterCount(ref ReaderWriterLockType.LockCountType lc) { uint readLockWaiterCount = lc.Counter.ReadLockWaiterCount; - Assert.True(readLockWaiterCount > 0); + Assert.SdkGreater(readLockWaiterCount, 0u); lc.Counter.ReadLockWaiterCount = readLockWaiterCount - 1; } public static void IncWriteLockWaiterCount(ref ReaderWriterLockType.LockCountType lc) { uint writeLockWaiterCount = lc.Counter.WriteLockWaiterCount; - Assert.True(writeLockWaiterCount < ReaderWriterLock.ReadWriteLockWaiterCountMax); + Assert.SdkLess(writeLockWaiterCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax); lc.Counter.WriteLockWaiterCount = writeLockWaiterCount + 1; } public static void DecWriteLockWaiterCount(ref ReaderWriterLockType.LockCountType lc) { uint writeLockWaiterCount = lc.Counter.WriteLockWaiterCount; - Assert.True(writeLockWaiterCount > 0); + Assert.SdkGreater(writeLockWaiterCount, 0u); lc.Counter.WriteLockWaiterCount = writeLockWaiterCount - 1; } public static void IncWriteLockCount(ref ReaderWriterLockType rwLock) { uint writeLockCount = rwLock.LockCount.WriteLockCount; - Assert.True(writeLockCount < ReaderWriterLock.ReaderWriterLockCountMax); + Assert.SdkLess(writeLockCount, (uint)ReaderWriterLock.ReaderWriterLockCountMax); rwLock.LockCount.WriteLockCount = writeLockCount + 1; } public static void DecWriteLockCount(ref ReaderWriterLockType rwLock) { uint writeLockCount = rwLock.LockCount.WriteLockCount; - Assert.True(writeLockCount > 0); + Assert.SdkGreater(writeLockCount, 0u); rwLock.LockCount.WriteLockCount = writeLockCount - 1; } diff --git a/src/LibHac/Os/Impl/TickManager.cs b/src/LibHac/Os/Impl/TickManager.cs index 3d868c7e..03909399 100644 --- a/src/LibHac/Os/Impl/TickManager.cs +++ b/src/LibHac/Os/Impl/TickManager.cs @@ -42,7 +42,7 @@ namespace LibHac.Os.Impl // Get the tick frequency. long tickFreq = GetTickFrequency(); - Assert.True(tickFreq < MaxTickFrequency); + Assert.SdkLess(tickFreq, MaxTickFrequency); // Clamp tick to range. if (ticks > GetMaxTick()) @@ -63,7 +63,7 @@ namespace LibHac.Os.Impl TimeSpan ts = TimeSpan.FromSeconds(seconds) + TimeSpan.FromNanoSeconds(frac * nanoSecondsPerSecond / tickFreq); - Assert.True(!(ticks > 0 && ts < default(TimeSpan) || ticks < 0 && ts > default(TimeSpan))); + Assert.SdkAssert(!(ticks > 0 && ts < default(TimeSpan) || ticks < 0 && ts > default(TimeSpan))); return ts; } @@ -87,7 +87,7 @@ namespace LibHac.Os.Impl { // Get the tick frequency. long tickFreq = GetTickFrequency(); - Assert.True(tickFreq < MaxTickFrequency); + Assert.SdkLess(tickFreq, MaxTickFrequency); // Convert to tick. long nanoSecondsPerSecond = TimeSpan.FromSeconds(1).GetNanoSeconds(); diff --git a/src/LibHac/Os/ReaderWriterLock.cs b/src/LibHac/Os/ReaderWriterLock.cs index c77a4067..4021df8f 100644 --- a/src/LibHac/Os/ReaderWriterLock.cs +++ b/src/LibHac/Os/ReaderWriterLock.cs @@ -27,11 +27,11 @@ namespace LibHac.Os public static void FinalizeReaderWriterLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); // Don't allow finalizing a locked lock. - Assert.True(ReaderWriterLockImpl.GetReadLockCount(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0); - Assert.True(ReaderWriterLockImpl.GetWriteLocked(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0); + Assert.SdkRequires(ReaderWriterLockImpl.GetReadLockCount(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0); + Assert.SdkRequires(ReaderWriterLockImpl.GetWriteLocked(in ReaderWriterLockImpl.GetLockCount(ref rwLock)) == 0); // Mark not initialized. rwLock.LockState = ReaderWriterLockType.State.NotInitialized; @@ -42,43 +42,43 @@ namespace LibHac.Os public static void AcquireReadLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); os.Impl.AcquireReadLockImpl(ref rwLock); } public static bool TryAcquireReadLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); return os.Impl.TryAcquireReadLockImpl(ref rwLock); } public static void ReleaseReadLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); os.Impl.ReleaseReadLockImpl(ref rwLock); } public static void AcquireWriteLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); os.Impl.AcquireWriteLockImpl(ref rwLock); } public static bool TryAcquireWriteLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); return os.Impl.TryAcquireWriteLockImpl(ref rwLock); } public static void ReleaseWriteLock(this OsState os, ref ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); os.Impl.ReleaseWriteLockImpl(ref rwLock); } public static bool IsReadLockHeld(this OsState os, in ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); return ReaderWriterLockImpl.GetReadLockCount(in ReaderWriterLockImpl.GetLockCountRo(in rwLock)) != 0; } @@ -86,14 +86,14 @@ namespace LibHac.Os // Todo: Use Horizon thread APIs public static bool IsWriteLockHeldByCurrentThread(this OsState os, in ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); return rwLock.OwnerThread == Environment.CurrentManagedThreadId && ReaderWriterLockImpl.GetWriteLockCount(in rwLock) != 0; } public static bool IsReaderWriterLockOwnerThread(this OsState os, in ReaderWriterLockType rwLock) { - Assert.True(rwLock.LockState == ReaderWriterLockType.State.Initialized); + Assert.SdkRequires(rwLock.LockState == ReaderWriterLockType.State.Initialized); return rwLock.OwnerThread == Environment.CurrentManagedThreadId; } } diff --git a/src/LibHac/Util/Alignment.cs b/src/LibHac/Util/Alignment.cs index c5f72718..19cf41c8 100644 --- a/src/LibHac/Util/Alignment.cs +++ b/src/LibHac/Util/Alignment.cs @@ -11,7 +11,7 @@ namespace LibHac.Util public static ulong AlignUpPow2(ulong value, uint alignment) { - Assert.True(BitUtil.IsPowerOfTwo(alignment)); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment)); ulong invMask = alignment - 1; return ((value + invMask) & ~invMask); @@ -19,7 +19,7 @@ namespace LibHac.Util public static ulong AlignDownPow2(ulong value, uint alignment) { - Assert.True(BitUtil.IsPowerOfTwo(alignment)); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment)); ulong invMask = alignment - 1; return (value & ~invMask); @@ -27,7 +27,7 @@ namespace LibHac.Util public static bool IsAlignedPow2(ulong value, uint alignment) { - Assert.True(BitUtil.IsPowerOfTwo(alignment)); + Assert.SdkRequires(BitUtil.IsPowerOfTwo(alignment)); ulong invMask = alignment - 1; return (value & invMask) == 0; diff --git a/src/LibHac/Util/Optional.cs b/src/LibHac/Util/Optional.cs index 1dd037b4..cac1eda0 100644 --- a/src/LibHac/Util/Optional.cs +++ b/src/LibHac/Util/Optional.cs @@ -14,17 +14,17 @@ namespace LibHac.Util { get { - Assert.True(_hasValue); - // It's beautiful - return ref MemoryMarshal.CreateSpan(ref _value, 1)[0]; + Assert.SdkRequires(_hasValue); + // It's beautiful, working around C# rules + return ref MemoryMarshal.GetReference(SpanHelpers.CreateSpan(ref _value, 1)); } } public readonly ref readonly T ValueRo { get { - Assert.True(_hasValue); - return ref SpanHelpers.CreateReadOnlySpan(in _value, 1)[0]; + Assert.SdkRequires(_hasValue); + return ref MemoryMarshal.GetReference(SpanHelpers.CreateReadOnlySpan(in _value, 1)); } }