Add new assert system

Mostly imitates nnsdk's assert system. The assert handler object is global because passing around a HorizonClient object just to do asserts would be annoying
This commit is contained in:
Alex Barney 2021-03-26 20:07:20 -07:00
parent 12575da37d
commit 7269c0a215
49 changed files with 1743 additions and 467 deletions

View File

@ -335,7 +335,7 @@ namespace LibHac.Boot
private bool VerifyPk11Sizes()
{
Assert.True(IsDecrypted);
Assert.SdkRequires(IsDecrypted);
int pk11Size = Unsafe.SizeOf<Package1Pk11Header>() + GetSectionSize(Package1Section.WarmBoot) +
GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor);

View File

@ -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;

View File

@ -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<char> 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<char> keyName, ref int keyIndex, out bool isDev)
{
Assert.Equal((int)KeyRangeType.Range, (int)RangeType);
Assert.SdkRequiresEqual((int)KeyRangeType.Range, (int)RangeType);
isDev = false;

View File

@ -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;
}

View File

@ -296,7 +296,7 @@ namespace LibHac.Crypto
private static void LeftShiftBytes(ReadOnlySpan<byte> input, Span<byte> output)
{
Assert.True(output.Length >= input.Length);
Assert.SdkRequiresGreaterEqual(output.Length, input.Length);
byte carry = 0;

View File

@ -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)
{

File diff suppressed because it is too large Load Diff

View File

@ -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<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable<T>
{
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<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
string rhsText, string functionName, string fileName, int lineNumber) where T : IEquatable<T>
{
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<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
{
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<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
{
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<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
{
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<T>(AssertionType assertionType, T lhs, T rhs, string lhsText,
string rhsText, string functionName, string fileName, int lineNumber) where T : IComparable<T>
{
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>(T item) where T : class
{
return item is null;
}
public static bool Null<T>(ref T item)
{
return Unsafe.IsNullRef(ref item);
}
public static bool NotNull<T>(T item) where T : class
{
return item is not null;
}
public static bool NotNull<T>(ref T item)
{
return !Unsafe.IsNullRef(ref item);
}
public static bool NotNull<T>(Span<T> span)
{
return !Unsafe.IsNullRef(ref MemoryMarshal.GetReference(span));
}
public static bool NotNull<T>(ReadOnlySpan<T> 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>(T lhs, T rhs) where T : IEquatable<T>
{
return lhs.Equals(rhs);
}
public static bool Equal<T>(ref T lhs, ref T rhs) where T : IEquatable<T>
{
return lhs.Equals(rhs);
}
public static bool NotEqual<T>(T lhs, T rhs) where T : IEquatable<T>
{
return !lhs.Equals(rhs);
}
public static bool NotEqual<T>(ref T lhs, ref T rhs) where T : IEquatable<T>
{
return !lhs.Equals(rhs);
}
public static bool Less<T>(T lhs, T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) < 0;
}
public static bool Less<T>(ref T lhs, ref T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) < 0;
}
public static bool LessEqual<T>(T lhs, T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) <= 0;
}
public static bool LessEqual<T>(ref T lhs, ref T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) <= 0;
}
public static bool Greater<T>(T lhs, T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) > 0;
}
public static bool Greater<T>(ref T lhs, ref T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) > 0;
}
public static bool GreaterEqual<T>(T lhs, T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) >= 0;
}
public static bool GreaterEqual<T>(ref T lhs, ref T rhs) where T : IComparable<T>
{
return lhs.CompareTo(rhs) >= 0;
}
public static bool IsAligned(ulong value, int alignment)
{
return Alignment.IsAlignedPow2(value, (uint)alignment);
}
}
}

View File

@ -23,7 +23,7 @@ namespace LibHac.Diag.Impl
public void RegisterObserver(TObserver observerHolder)
{
Assert.False(observerHolder.IsRegistered);
Assert.SdkRequires(!observerHolder.IsRegistered);
using ScopedLock<ReaderWriterLock> 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<ReaderWriterLock> 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<ReaderWriterLock> 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<ReaderWriterLock> lk = ScopedLock.Lock(ref _rwLock);

View File

@ -139,7 +139,8 @@ namespace LibHac.Fs.Impl
private ReadOnlySpan<byte> 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<byte> 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)

View File

@ -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;
}

View File

@ -68,7 +68,7 @@ namespace LibHac.Fs.Impl
public bool CanAcceptMountName(U8Span name)
{
Assert.True(_mutex.IsLockedByCurrentThread());
Assert.SdkAssert(_mutex.IsLockedByCurrentThread());
for (LinkedListNode<FileSystemAccessor> currentNode = _fileSystemList.First;
currentNode is not null;

View File

@ -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];
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);
}
/// <summary>
@ -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);
}
/// <summary>
@ -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;

View File

@ -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
{

View File

@ -36,7 +36,7 @@ namespace LibHac.FsSrv.Impl
private static Result EnsureDirectoryImpl(IFileSystem fileSystem, Span<byte> 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<byte> 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)

View File

@ -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);

View File

@ -533,7 +533,7 @@ namespace LibHac.FsSrv
private FlatMapKeyValueStore<SaveDataAttribute>.Iterator GetBeginIterator()
{
Assert.True(IsKvdbLoaded);
Assert.SdkRequires(IsKvdbLoaded);
return KvDatabase.GetBeginIterator();
}

View File

@ -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)

View File

@ -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)]

View File

@ -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:

View File

@ -31,7 +31,7 @@ namespace LibHac.FsSrv.Storage
out ReferenceCountedDisposable<IStorageDeviceManager> deviceManager, StorageDevicePortId portId)
{
IStorageDeviceManagerFactory factory = storage.GetStorageDeviceManagerFactory(null);
Assert.NotNull(factory);
Assert.SdkNotNull(factory);
return factory.Create(out deviceManager, portId);
}

View File

@ -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<NodeHeader>());
Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
Assert.True(BitUtil.IsPowerOfTwo(nodeSize));
Assert.True(!IsInitialized());
Assert.SdkRequiresLessEqual(sizeof(long), entrySize);
Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf<NodeHeader>(), 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<NodeHeader>());
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<NodeHeader>(), 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<NodeHeader>());
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<NodeHeader>(), 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<NodeHeader>());
Assert.SdkRequiresGreaterEqual(_header.Length / sizeof(long), Unsafe.SizeOf<NodeHeader>());
return ref Unsafe.As<long, NodeHeader>(ref _header[0]);
}
@ -322,8 +322,9 @@ namespace LibHac.FsSystem
{
_buffer = buffer;
Assert.True(_buffer.Length >= Unsafe.SizeOf<NodeHeader>());
Assert.True(_buffer.Length >= Unsafe.SizeOf<NodeHeader>() + GetHeader().Count * Unsafe.SizeOf<TEntry>());
Assert.SdkRequiresGreaterEqual(_buffer.Length, Unsafe.SizeOf<NodeHeader>());
Assert.SdkRequiresGreaterEqual(_buffer.Length,
Unsafe.SizeOf<NodeHeader>() + GetHeader().Count * Unsafe.SizeOf<TEntry>());
}
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)
{

View File

@ -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<NodeHeader>());
Assert.True(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
Assert.True(BitUtil.IsPowerOfTwo(nodeSize));
Assert.SdkRequiresLessEqual(sizeof(long), entrySize);
Assert.SdkRequiresLessEqual(entrySize + Unsafe.SizeOf<NodeHeader>(), 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
/// <returns>The <see cref="Result"/> of the operation.</returns>
public Result Add<T>(ref T entry) where T : unmanaged
{
Assert.True(Unsafe.SizeOf<T>() == EntrySize);
Assert.SdkRequiresEqual(Unsafe.SizeOf<T>(), EntrySize);
if (CurrentEntryIndex >= EntryCount)
return ResultFs.OutOfRange.Log();

View File

@ -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;
}

View File

@ -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<PageList>();
uint pageListAlignment = (uint)Unsafe.SizeOf<nint>();
@ -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<nint>();
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<byte> 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));

View File

@ -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<nuint>();
@ -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<Entry>();
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<Entry> 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);
}

View File

@ -25,7 +25,7 @@ namespace LibHac.FsSystem
public static Result FromSpan(out FsPath fsPath, ReadOnlySpan<byte> path)
{
Unsafe.SkipInit(out fsPath);
UnsafeHelpers.SkipParamInit(out fsPath);
// Ensure null terminator even if the creation fails for safety
fsPath.Str[MaxLength] = 0;

View File

@ -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<Entry> 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<byte> 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];

View File

@ -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)
{

View File

@ -254,7 +254,7 @@ namespace LibHac.FsSystem.NcaUtils
private static bool CheckIfDecrypted(ReadOnlySpan<byte> 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')

View File

@ -33,13 +33,13 @@ namespace LibHac.FsSystem
public Span<byte> 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;

View File

@ -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
/// </summary>
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
/// </summary>
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
/// <param name="buffer">The buffer in which to place the read data.</param>
public void Read(long offset, Span<byte> 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<byte> cacheBuffer = MemoryRange.Span.Slice((int)readOffset, buffer.Length);
cacheBuffer.CopyTo(buffer);
@ -264,18 +264,18 @@ namespace LibHac.FsSystem.Save
/// <param name="buffer">The buffer containing the data to be written.</param>
public void Write(long offset, ReadOnlySpan<byte> 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<byte> cacheBuffer = MemoryRange.Span.Slice((int)writeOffset, buffer.Length);
buffer.CopyTo(cacheBuffer);
@ -289,14 +289,14 @@ namespace LibHac.FsSystem.Save
/// <returns>The <see cref="Result"/> of the operation.</returns>
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<byte> 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
/// <see cref="Cache"/> is prepared to fetch; <see langword="false"/> if not.</returns>
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
/// </summary>
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
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
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
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
public Result FetchFromBuffer(long offset, ReadOnlySpan<byte> 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
/// <see langword="false"/> if the buffer has been evicted from the <see cref="IBufferManager"/> cache.</returns>
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
/// </summary>
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, <see langword="false"/>.</returns>
public bool IsValid()
{
Assert.NotNull(BufferedStorage);
Assert.SdkRequiresNotNull(BufferedStorage);
return _isValid || ReferenceCount > 0;
}
@ -489,7 +489,7 @@ namespace LibHac.FsSystem.Save
/// Otherwise, <see langword="false"/>.</returns>
public bool IsDirty()
{
Assert.NotNull(BufferedStorage);
Assert.SdkRequiresNotNull(BufferedStorage);
return _isDirty;
}
@ -503,7 +503,7 @@ namespace LibHac.FsSystem.Save
/// Otherwise, <see langword="false"/>.</returns>
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<byte> 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<Cache>(ref bufferedStorage.NextAcquireCache);
BufferedStorage = bufferedStorage;
@ -593,23 +593,23 @@ namespace LibHac.FsSystem.Save
/// or if all matching Caches have already been iterated.</returns>
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.</returns>
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.</returns>
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, <see langword="false"/>.</returns>
public bool AcquireFetchableCache()
{
Assert.NotNull(BufferedStorage);
Assert.SdkRequiresNotNull(BufferedStorage);
lock (BufferedStorage.Locker)
{
Release();
Assert.True(Cache.IsNull);
Assert.SdkAssert(Cache.IsNull);
Cache = new Ref<Cache>(ref BufferedStorage.NextFetchCache);
@ -766,7 +766,7 @@ namespace LibHac.FsSystem.Save
/// <param name="buffer">The buffer in which to place the read data.</param>
public void Read(long offset, Span<byte> buffer)
{
Assert.True(!Cache.IsNull);
Assert.SdkRequires(!Cache.IsNull);
Cache.Value.Read(offset, buffer);
}
@ -779,7 +779,7 @@ namespace LibHac.FsSystem.Save
/// <param name="buffer">The buffer containing the data to be written.</param>
public void Write(long offset, ReadOnlySpan<byte> buffer)
{
Assert.True(!Cache.IsNull);
Assert.SdkRequires(!Cache.IsNull);
Cache.Value.Write(offset, buffer);
}
@ -790,7 +790,7 @@ namespace LibHac.FsSystem.Save
/// <returns>The <see cref="Result"/> of the operation.</returns>
public Result Flush()
{
Assert.True(!Cache.IsNull);
Assert.SdkRequires(!Cache.IsNull);
return Cache.Value.Flush();
}
@ -800,7 +800,7 @@ namespace LibHac.FsSystem.Save
/// </summary>
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, <see langword="false"/>.</returns>
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 <see cref="Cache"/> was gained; <see langword="false"/> if not.</returns>
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
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
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
/// <see cref="ResultFs.BufferAllocationFailed"/>: A buffer could not be allocated.</returns>
public Result FetchFromBuffer(long offset, ReadOnlySpan<byte> buffer)
{
Assert.True(!Cache.IsNull);
Assert.SdkRequires(!Cache.IsNull);
return Cache.Value.FetchFromBuffer(offset, buffer);
}
@ -987,11 +987,11 @@ namespace LibHac.FsSystem.Save
/// <returns></returns>
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<byte> 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<byte> 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<byte> outBuffer, OperationId operationId, long offset, long size,
ReadOnlySpan<byte> 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
/// </summary>
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
/// <returns>The <see cref="Result"/> of the operation.</returns>
private Result ReadCore(long offset, Span<byte> 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<byte> source)
{
Assert.NotNull(Caches);
Assert.SdkRequiresNotNull(Caches);
Assert.SdkRequiresNotNull(source);
// Validate the offset.
long baseStorageSize = BaseStorageSize;

View File

@ -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()

View File

@ -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);

View File

@ -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)
{

View File

@ -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<byte> keyBuffer, Span<byte> 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<byte> 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<byte> key, ReadOnlySpan<byte> 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));

View File

@ -29,6 +29,10 @@
<NoWarn>$(NoWarn);1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>$(DefineConstants);ENABLE_ASSERTS</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Condition="Exists('ResultNameResolver.Generated.cs')" Remove="ResultNameResolver.Archive.cs" />
<Compile Condition="Exists('Common\Keys\DefaultKeySet.Generated.cs')" Remove="Common\Keys\DefaultKeySet.Empty.cs" />

View File

@ -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;
}

View File

@ -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();

View File

@ -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<InternalCriticalSection> 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<InternalCriticalSection> 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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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));
}
}