using System; using System.Buffers; using System.CodeDom.Compiler; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.IO; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.Toolkit.HighPerformance.Buffers; using Microsoft.Toolkit.HighPerformance.Buffers.Internals; using Microsoft.Toolkit.HighPerformance.Buffers.Internals.Interfaces; using Microsoft.Toolkit.HighPerformance.Buffers.Views; using Microsoft.Toolkit.HighPerformance.Enumerables; using Microsoft.Toolkit.HighPerformance.Helpers; using Microsoft.Toolkit.HighPerformance.Helpers.Internals; using Microsoft.Toolkit.HighPerformance.Memory.Internals; using Microsoft.Toolkit.HighPerformance.Memory.Views; using Microsoft.Toolkit.HighPerformance.Streams; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyFileVersion("7.1.2.1")] [assembly: AssemblyInformationalVersion("7.1.2+da6d7d3f6c")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")] [assembly: AssemblyMetadata("CommitHash", "da6d7d3f6ca9914dbe86d7d394e9a4abef25c9b6")] [assembly: AssemblyCompany(".NET Foundation")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("(c) .NET Foundation and Contributors. All rights reserved.")] [assembly: AssemblyDescription("\r\n This package includes high performance .NET Standard helpers such as:\r\n - Memory2D and Span2D: two types providing fast and allocation-free abstraction over 2D memory areas.\r\n - ArrayPoolBufferWriter: an IBufferWriter implementation using pooled arrays, which also supports IMemoryOwner.\r\n - MemoryBufferWriter: an IBufferWriter: implementation that can wrap external Memory: instances.\r\n - MemoryOwner: an IMemoryOwner implementation with an embedded length and a fast Span accessor.\r\n - SpanOwner: a stack-only type with the ability to rent a buffer of a specified length and getting a Span from it.\r\n - StringPool: a configurable pool for string instances that be used to minimize allocations when creating multiple strings from char buffers.\r\n - String, array, Memory, Span extensions and more, all focused on high performance.\r\n - HashCode: a SIMD-enabled extension of HashCode to quickly process sequences of values.\r\n - BitHelper: a class with helper methods to perform bit operations on numeric types.\r\n - ParallelHelper: helpers to work with parallel code in a highly optimized manner.\r\n - Box: a type mapping boxed value types and exposing some utility and high performance methods.\r\n - Ref: a stack-only struct that can store a reference to a value of a specified type.\r\n - NullableRef: a stack-only struct similar to Ref, which also supports nullable references.\r\n ")] [assembly: AssemblyProduct("Windows Community Toolkit")] [assembly: AssemblyTitle("Microsoft.Toolkit.HighPerformance")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/CommunityToolkit/WindowsCommunityToolkit")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("7.1.0.0")] [module: UnverifiableCode] [module: SkipLocalsInit] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] internal sealed class IsUnmanagedAttribute : Attribute { } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] P_0) { TransformFlags = P_0; } } } [GeneratedCode("Nerdbank.GitVersioning.Tasks", "3.3.37.35081")] [ExcludeFromCodeCoverage] internal static class ThisAssembly { internal const string AssemblyVersion = "7.1.0.0"; internal const string AssemblyFileVersion = "7.1.2.1"; internal const string AssemblyInformationalVersion = "7.1.2+da6d7d3f6c"; internal const string AssemblyName = "Microsoft.Toolkit.HighPerformance"; internal const string AssemblyTitle = "Microsoft.Toolkit.HighPerformance"; internal const string AssemblyConfiguration = "Release"; internal const string GitCommitId = "da6d7d3f6ca9914dbe86d7d394e9a4abef25c9b6"; internal const string PublicKey = "002400000480000094000000060200000024000052534131000400000100010041753af735ae6140c9508567666c51c6ab929806adb0d210694b30ab142a060237bc741f9682e7d8d4310364b4bba4ee89cc9d3d5ce7e5583587e8ea44dca09977996582875e71fb54fa7b170798d853d5d8010b07219633bdb761d01ac924da44576d6180cdceae537973982bb461c541541d58417a3794e34f45e6f2d129e2"; internal const string PublicKeyToken = "4aff67a105548ee2"; internal const bool IsPublicRelease = true; internal const bool IsPrerelease = false; internal static readonly DateTime GitCommitDate = new DateTime(637728688180000000L, DateTimeKind.Utc); internal const string RootNamespace = "Microsoft.Toolkit.HighPerformance"; } namespace Microsoft.Toolkit.HighPerformance { [DebuggerDisplay("{ToString(),raw}")] public sealed class Box where T : struct { private Box() { throw new InvalidOperationException("The Microsoft.Toolkit.HighPerformance.Box constructor should never be used"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Box GetFrom(object obj) { if (obj.GetType() != typeof(T)) { ThrowInvalidCastExceptionForGetFrom(); } return Unsafe.As>(obj); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Box DangerousGetFrom(object obj) { return Unsafe.As>(obj); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryGetFrom(object obj, [NotNullWhen(true)] out Box? box) { if (obj.GetType() == typeof(T)) { box = Unsafe.As>(obj); return true; } box = null; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator T(Box box) { return (T)box; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator Box(T value) { return Unsafe.As>(value); } public override string ToString() { return this.GetReference().ToString(); } public override bool Equals(object? obj) { return object.Equals(this, obj); } public override int GetHashCode() { return this.GetReference().GetHashCode(); } private static void ThrowInvalidCastExceptionForGetFrom() { throw new InvalidCastException($"Can't cast the input object to the type Box<{typeof(T)}>"); } } public static class BoxExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T GetReference(this Box box) where T : struct { return ref Unsafe.Unbox(box); } } public static class ArrayExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReference(this T[] array) { IntPtr arrayDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayDataByteOffset(); return ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, arrayDataByteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this T[] array, int i) { IntPtr arrayDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayDataByteOffset(); return ref Unsafe.Add(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, arrayDataByteOffset), (nint)(uint)i); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this T[] array, T value) where T : IEquatable { ref T r = ref array.DangerousGetReference(); nint arrayNativeLength = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayNativeLength(array); nint num = SpanHelper.Count(ref r, arrayNativeLength, value); if ((nuint)num > (nuint)2147483647u) { ThrowOverflowException(); } return (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanEnumerable Enumerate(this T[] array) { return new SpanEnumerable(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanTokenizer Tokenize(this T[] array, T separator) where T : IEquatable { return new SpanTokenizer(array, separator); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetDjb2HashCode(this T[] array) where T : notnull { ref T r = ref array.DangerousGetReference(); nint arrayNativeLength = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayNativeLength(array); return SpanHelper.GetDjb2HashCode(ref r, arrayNativeLength); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsCovariant(this T[] array) { if (default(T) == null) { return array.GetType() != typeof(T[]); } return false; } private static void ThrowOverflowException() { throw new OverflowException(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReference(this T[,] array) { IntPtr array2DDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray2DDataByteOffset(); return ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, array2DDataByteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this T[,] array, int i, int j) { int length = array.GetLength(1); nint elementOffset = (nint)(uint)i * (nint)(uint)length + (nint)(uint)j; IntPtr array2DDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray2DDataByteOffset(); return ref Unsafe.Add(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, array2DDataByteOffset), elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RefEnumerable GetRow(this T[,] array, int row) { if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } int length = array.GetLength(0); if ((uint)row >= (uint)length) { ThrowArgumentOutOfRangeExceptionForRow(); } int length2 = array.GetLength(1); return new RefEnumerable(ref array.DangerousGetReferenceAt(row, 0), length2, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static RefEnumerable GetColumn(this T[,] array, int column) { if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } int length = array.GetLength(1); if ((uint)column >= (uint)length) { ThrowArgumentOutOfRangeExceptionForColumn(); } int length2 = array.GetLength(0); return new RefEnumerable(ref array.DangerousGetReferenceAt(0, column), length2, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span2D AsSpan2D(this T[,]? array) { return new Span2D(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span2D AsSpan2D(this T[,]? array, int row, int column, int height, int width) { return new Span2D(array, row, column, height, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory2D AsMemory2D(this T[,]? array) { return new Memory2D(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory2D AsMemory2D(this T[,]? array, int row, int column, int height, int width) { return new Memory2D(array, row, column, height, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span GetRowSpan(this T[,] array, int row) { if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } if ((uint)row >= (uint)array.GetLength(0)) { ThrowArgumentOutOfRangeExceptionForRow(); } return MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(row, 0), array.GetLength(1)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory GetRowMemory(this T[,] array, int row) { if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } if ((uint)row >= (uint)array.GetLength(0)) { ThrowArgumentOutOfRangeExceptionForRow(); } IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, 0)); return new RawObjectMemoryManager(array, offset, array.GetLength(1)).Memory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory AsMemory(this T[,]? array) { if (array == null) { return default(Memory); } if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } IntPtr array2DDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray2DDataByteOffset(); int length = array.Length; return new RawObjectMemoryManager(array, array2DDataByteOffset, length).Memory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this T[,]? array) { if (array == null) { return default(Span); } if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } ref T reference = ref array.DangerousGetReference(); int length = array.Length; return MemoryMarshal.CreateSpan(ref reference, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this T[,] array, T value) where T : IEquatable { ref T r = ref array.DangerousGetReference(); nint arrayNativeLength = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayNativeLength(array); nint num = SpanHelper.Count(ref r, arrayNativeLength, value); if ((nuint)num > (nuint)2147483647u) { ThrowOverflowException(); } return (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetDjb2HashCode(this T[,] array) where T : notnull { ref T r = ref array.DangerousGetReference(); nint arrayNativeLength = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayNativeLength(array); return SpanHelper.GetDjb2HashCode(ref r, arrayNativeLength); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsCovariant(this T[,] array) { if (default(T) == null) { return array.GetType() != typeof(T[,]); } return false; } private static void ThrowArrayTypeMismatchException() { throw new ArrayTypeMismatchException("The given array doesn't match the specified type T"); } private static void ThrowArgumentOutOfRangeExceptionForRow() { throw new ArgumentOutOfRangeException("row"); } private static void ThrowArgumentOutOfRangeExceptionForColumn() { throw new ArgumentOutOfRangeException("column"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReference(this T[,,] array) { IntPtr array3DDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray3DDataByteOffset(); return ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, array3DDataByteOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this T[,,] array, int i, int j, int k) { int length = array.GetLength(1); int length2 = array.GetLength(2); nint elementOffset = (nint)(uint)i * (nint)(uint)length * (nint)(uint)length2 + (nint)(uint)j * (nint)(uint)length2 + (nint)(uint)k; IntPtr array3DDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray3DDataByteOffset(); return ref Unsafe.Add(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, array3DDataByteOffset), elementOffset); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory AsMemory(this T[,,]? array) { if (array == null) { return default(Memory); } if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } IntPtr array3DDataByteOffset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray3DDataByteOffset(); int length = array.Length; return new RawObjectMemoryManager(array, array3DDataByteOffset, length).Memory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this T[,,]? array) { if (array == null) { return default(Span); } if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } ref T reference = ref array.DangerousGetReference(); int length = array.Length; return MemoryMarshal.CreateSpan(ref reference, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsSpan(this T[,,] array, int depth) { if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowArgumentOutOfRangeExceptionForDepth(); } ref T reference = ref array.DangerousGetReferenceAt(depth, 0, 0); int length = checked(array.GetLength(1) * array.GetLength(2)); return MemoryMarshal.CreateSpan(ref reference, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory AsMemory(this T[,,] array, int depth) { if (array.IsCovariant()) { ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowArgumentOutOfRangeExceptionForDepth(); } IntPtr offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0)); int length = checked(array.GetLength(1) * array.GetLength(2)); return new RawObjectMemoryManager(array, offset, length).Memory; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span2D AsSpan2D(this T[,,] array, int depth) { return new Span2D(array, depth); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory2D AsMemory2D(this T[,,] array, int depth) { return new Memory2D(array, depth); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this T[,,] array, T value) where T : IEquatable { ref T r = ref array.DangerousGetReference(); nint arrayNativeLength = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayNativeLength(array); nint num = SpanHelper.Count(ref r, arrayNativeLength, value); if ((nuint)num > (nuint)2147483647u) { ThrowOverflowException(); } return (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetDjb2HashCode(this T[,,] array) where T : notnull { ref T r = ref array.DangerousGetReference(); nint arrayNativeLength = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArrayNativeLength(array); return SpanHelper.GetDjb2HashCode(ref r, arrayNativeLength); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsCovariant(this T[,,] array) { if (default(T) == null) { return array.GetType() != typeof(T[,,]); } return false; } private static void ThrowArgumentOutOfRangeExceptionForDepth() { throw new ArgumentOutOfRangeException("depth"); } } public static class ArrayPoolBufferWriterExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Stream AsStream(this ArrayPoolBufferWriter writer) { return new IBufferWriterStream(new ArrayBufferWriterOwner(writer)); } } public static class ArrayPoolExtensions { public static void Resize(this ArrayPool pool, ref T[]? array, int newSize, bool clearArray = false) { if (array == null) { array = pool.Rent(newSize); } else if (array.Length != newSize) { T[] array2 = pool.Rent(newSize); int length = Math.Min(array.Length, newSize); Array.Copy(array, 0, array2, 0, length); pool.Return(array, clearArray); array = array2; } } } public static class BoolExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte ToByte(this bool flag) { bool flag2 = flag; return flag2 ? ((byte)1) : ((byte)0); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ToBitwiseMask32(this bool flag) { bool flag2 = flag; return ~((flag2 ? 1 : 0) - 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static long ToBitwiseMask64(this bool flag) { bool flag2 = flag; return ~((flag2 ? 1L : 0L) - 1L); } } public static class HashCodeExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Add(this ref HashCode hashCode, ReadOnlySpan span) where T : notnull { int value = HashCode.CombineValues(span); hashCode.Add(value); } } public static class IBufferWriterExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Stream AsStream(this IBufferWriter writer) { if (writer.GetType() == typeof(ArrayPoolBufferWriter)) { return new IBufferWriterStream(new ArrayBufferWriterOwner(Unsafe.As>(writer))); } return new IBufferWriterStream(new IBufferWriterOwner(writer)); } public static void Write(this IBufferWriter writer, T value) where T : unmanaged { int num = Unsafe.SizeOf(); Span span = writer.GetSpan(1); if (span.Length < num) { ThrowArgumentExceptionForEndOfBuffer(); } Unsafe.WriteUnaligned(ref MemoryMarshal.GetReference(span), value); writer.Advance(num); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Write(this IBufferWriter writer, T value) { Span span = writer.GetSpan(1); if (span.Length < 1) { ThrowArgumentExceptionForEndOfBuffer(); } MemoryMarshal.GetReference(span) = value; writer.Advance(1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Write(this IBufferWriter writer, ReadOnlySpan span) where T : unmanaged { ReadOnlySpan readOnlySpan = MemoryMarshal.AsBytes(span); Span span2 = writer.GetSpan(readOnlySpan.Length); readOnlySpan.CopyTo(span2); writer.Advance(readOnlySpan.Length); } private static void ThrowArgumentExceptionForEndOfBuffer() { throw new ArgumentException("The current buffer writer can't contain the requested input data."); } } public static class IMemoryOwnerExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Stream AsStream(this IMemoryOwner memoryOwner) { return Microsoft.Toolkit.HighPerformance.Streams.MemoryStream.Create(memoryOwner); } } public static class MemoryExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory2D AsMemory2D(this Memory memory, int height, int width) { return new Memory2D(memory, height, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory2D AsMemory2D(this Memory memory, int offset, int height, int width, int pitch) { return new Memory2D(memory, offset, height, width, pitch); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory AsBytes(this Memory memory) where T : unmanaged { return MemoryMarshal.AsMemory(ReadOnlyMemoryExtensions.Cast(memory)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory Cast(this Memory memory) where TFrom : unmanaged where TTo : unmanaged { return MemoryMarshal.AsMemory(ReadOnlyMemoryExtensions.Cast(memory)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Stream AsStream(this Memory memory) { return Microsoft.Toolkit.HighPerformance.Streams.MemoryStream.Create(memory, isReadOnly: false); } } public static class ReadOnlyMemoryExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlyMemory2D AsMemory2D(this ReadOnlyMemory memory, int height, int width) { return new ReadOnlyMemory2D(memory, height, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlyMemory2D AsMemory2D(this ReadOnlyMemory memory, int offset, int height, int width, int pitch) { return new ReadOnlyMemory2D(memory, offset, height, width, pitch); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlyMemory AsBytes(this ReadOnlyMemory memory) where T : unmanaged { return memory.Cast(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlyMemory Cast(this ReadOnlyMemory memory) where TFrom : unmanaged where TTo : unmanaged { if (memory.IsEmpty) { return default(ReadOnlyMemory); } if (typeof(TFrom) == typeof(char) && MemoryMarshal.TryGetString((ReadOnlyMemory)(object)memory, out string text, out int start, out int length)) { return new StringMemoryManager(text, start, length).Memory; } if (MemoryMarshal.TryGetArray(memory, out var segment)) { return new ArrayMemoryManager(segment.Array, segment.Offset, segment.Count).Memory; } if (MemoryMarshal.TryGetMemoryManager>(memory, out MemoryManager manager, out start, out length)) { if (manager is IMemoryManager memoryManager) { return memoryManager.GetMemory(start, length); } return new ProxyMemoryManager(manager, start, length).Memory; } return ThrowArgumentExceptionForUnsupportedMemory(); static ReadOnlyMemory ThrowArgumentExceptionForUnsupportedMemory() { throw new ArgumentException("The input instance doesn't have a supported underlying data store."); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Stream AsStream(this ReadOnlyMemory memory) { return Microsoft.Toolkit.HighPerformance.Streams.MemoryStream.Create(memory, isReadOnly: true); } } public static class ReadOnlySpanExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReference(this ReadOnlySpan span) { return ref MemoryMarshal.GetReference(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this ReadOnlySpan span, int i) { return ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)i); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this ReadOnlySpan span, nint i) { return ref Unsafe.Add(ref MemoryMarshal.GetReference(span), i); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref readonly T DangerousGetLookupReferenceAt(this ReadOnlySpan span, int i) { bool flag = (uint)i < (uint)span.Length; uint num = (uint)(~((flag ? 1 : 0) - 1)); uint num2 = (uint)i & num; return ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)num2); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan2D AsSpan2D(this ReadOnlySpan span, int height, int width) { return new ReadOnlySpan2D(span, height, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan2D AsSpan2D(this ReadOnlySpan span, int offset, int height, int width, int pitch) { return new ReadOnlySpan2D(span, offset, height, width, pitch); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(this ReadOnlySpan span, in T value) { nint num = (nint)Unsafe.ByteOffset(in MemoryMarshal.GetReference(span), in Unsafe.AsRef(in value)) / (nint)(uint)Unsafe.SizeOf(); if ((nuint)num >= (nuint)(uint)span.Length) { SpanExtensions.ThrowArgumentOutOfRangeExceptionForInvalidReference(); } return (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this ReadOnlySpan span, T value) where T : IEquatable { ref T reference = ref MemoryMarshal.GetReference(span); nint length = (nint)(uint)span.Length; return (int)SpanHelper.Count(ref reference, length, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan AsBytes(this ReadOnlySpan span) where T : unmanaged { return MemoryMarshal.AsBytes(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan Cast(this ReadOnlySpan span) where TFrom : unmanaged where TTo : unmanaged { return MemoryMarshal.Cast(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpanEnumerable Enumerate(this ReadOnlySpan span) { return new ReadOnlySpanEnumerable(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpanTokenizer Tokenize(this ReadOnlySpan span, T separator) where T : IEquatable { return new ReadOnlySpanTokenizer(span, separator); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetDjb2HashCode(this ReadOnlySpan span) where T : notnull { ref T reference = ref MemoryMarshal.GetReference(span); nint length = (nint)(uint)span.Length; return SpanHelper.GetDjb2HashCode(ref reference, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo(this ReadOnlySpan span, RefEnumerable destination) { destination.CopyFrom(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryCopyTo(this ReadOnlySpan span, RefEnumerable destination) { return destination.TryCopyFrom(span); } } public static class SpanExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReference(this Span span) { return ref MemoryMarshal.GetReference(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this Span span, int i) { return ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)i); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetReferenceAt(this Span span, nint i) { return ref Unsafe.Add(ref MemoryMarshal.GetReference(span), i); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span2D AsSpan2D(this Span span, int height, int width) { return new Span2D(span, height, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span2D AsSpan2D(this Span span, int offset, int height, int width, int pitch) { return new Span2D(span, offset, height, width, pitch); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span AsBytes(this Span span) where T : unmanaged { return MemoryMarshal.AsBytes(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span Cast(this Span span) where TFrom : unmanaged where TTo : unmanaged { return MemoryMarshal.Cast(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int IndexOf(this Span span, ref T value) { nint num = (nint)Unsafe.ByteOffset(in MemoryMarshal.GetReference(span), in value) / (nint)(uint)Unsafe.SizeOf(); if ((nuint)num >= (nuint)(uint)span.Length) { ThrowArgumentOutOfRangeExceptionForInvalidReference(); } return (int)num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this Span span, T value) where T : IEquatable { ref T reference = ref MemoryMarshal.GetReference(span); nint length = (nint)(uint)span.Length; return (int)SpanHelper.Count(ref reference, length, value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanEnumerable Enumerate(this Span span) { return new SpanEnumerable(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanTokenizer Tokenize(this Span span, T separator) where T : IEquatable { return new SpanTokenizer(span, separator); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetDjb2HashCode(this Span span) where T : notnull { ref T reference = ref MemoryMarshal.GetReference(span); nint length = (nint)(uint)span.Length; return SpanHelper.GetDjb2HashCode(ref reference, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void CopyTo(this Span span, RefEnumerable destination) { destination.CopyFrom(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryCopyTo(this Span span, RefEnumerable destination) { return destination.TryCopyFrom(span); } internal static void ThrowArgumentOutOfRangeExceptionForInvalidReference() { throw new ArgumentOutOfRangeException("value", "The input reference does not belong to an element of the input span"); } } public static class SpinLockExtensions { [EditorBrowsable(EditorBrowsableState.Never)] public readonly ref struct UnsafeLock { private unsafe readonly SpinLock* spinLock; private readonly bool lockTaken; [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe UnsafeLock(SpinLock* spinLock) { this.spinLock = spinLock; lockTaken = false; spinLock->Enter(ref lockTaken); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void Dispose() { if (lockTaken) { spinLock->Exit(); } } } [EditorBrowsable(EditorBrowsableState.Never)] public readonly ref struct Lock { private readonly Ref spinLock; private readonly bool lockTaken; [MethodImpl(MethodImplOptions.AggressiveInlining)] public Lock(ref SpinLock spinLock) { this.spinLock = new Ref(ref spinLock); lockTaken = false; spinLock.Enter(ref lockTaken); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { if (lockTaken) { spinLock.Value.Exit(); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static UnsafeLock Enter(SpinLock* spinLock) { return new UnsafeLock(spinLock); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Lock Enter(this ref SpinLock spinLock) { return new Lock(ref spinLock); } } public static class StreamExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static T Read(this Stream stream) where T : unmanaged { T result = default(T); int num = Unsafe.SizeOf(); if (stream.Read(new Span(&result, num)) != num) { ThrowInvalidOperationExceptionForEndOfStream(); } return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Write(this Stream stream, in T value) where T : unmanaged { ref byte reference = ref Unsafe.As(ref Unsafe.AsRef(in value)); int length = Unsafe.SizeOf(); ReadOnlySpan buffer = MemoryMarshal.CreateReadOnlySpan(in reference, length); stream.Write(buffer); } private static void ThrowInvalidOperationExceptionForEndOfStream() { throw new InvalidOperationException("The stream didn't contain enough data to read the requested item"); } } public static class StringExtensions { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref char DangerousGetReference(this string text) { return ref MemoryMarshal.GetReference(text.AsSpan()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref char DangerousGetReferenceAt(this string text, int i) { return ref Unsafe.Add(ref MemoryMarshal.GetReference(text.AsSpan()), (nint)(uint)i); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Count(this string text, char c) { ref char r = ref text.DangerousGetReference(); nint length = (nint)(uint)text.Length; return (int)SpanHelper.Count(ref r, length, c); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpanEnumerable Enumerate(this string text) { return new ReadOnlySpanEnumerable(text.AsSpan()); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpanTokenizer Tokenize(this string text, char separator) { return new ReadOnlySpanTokenizer(text.AsSpan(), separator); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int GetDjb2HashCode(this string text) { ref char r = ref text.DangerousGetReference(); nint length = (nint)(uint)text.Length; return SpanHelper.GetDjb2HashCode(ref r, length); } } [DebuggerTypeProxy(typeof(MemoryDebugView2D<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly struct Memory2D : IEquatable> { private readonly object? instance; private readonly IntPtr offset; private readonly int height; private readonly int width; private readonly int pitch; public static Memory2D Empty => default(Memory2D); public bool IsEmpty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (height != 0) { return width == 0; } return true; } } public nint Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return (nint)(uint)height * (nint)(uint)width; } } public int Height { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return height; } } public int Width { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return width; } } public Span2D Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (instance != null) { if (instance is MemoryManager memoryManager) { return new Span2D(ref Unsafe.Add(ref memoryManager.GetSpan().DangerousGetReference(), offset), height, width, pitch); } return new Span2D(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(instance, offset), height, width, pitch); } return default(Span2D); } } public Memory2D this[Range rows, Range columns] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { var (row, num) = rows.GetOffsetAndLength(height); var (column, num2) = columns.GetOffsetAndLength(width); return Slice(row, column, num, num2); } } public Memory2D(T[] array, int height, int width) : this(array, 0, height, width, 0) { } public Memory2D(T[] array, int offset, int height, int width, int pitch) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)offset > (uint)array.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = array.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } instance = array; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset)); this.height = height; this.width = width; this.pitch = pitch; } public Memory2D(T[,]? array) { if (array == null) { this = default(Memory2D); return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } instance = array; offset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray2DDataByteOffset(); height = array.GetLength(0); width = array.GetLength(1); pitch = 0; } public Memory2D(T[,]? array, int row, int column, int height, int width) { if (array == null) { if (row != 0 || column != 0 || height != 0 || width != 0) { ThrowHelper.ThrowArgumentException(); } this = default(Memory2D); return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } int length = array.GetLength(0); int length2 = array.GetLength(1); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } instance = array; offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column)); this.height = height; this.width = width; pitch = length2 - width; } public Memory2D(T[,,] array, int depth) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } instance = array; offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0)); height = array.GetLength(1); width = array.GetLength(2); pitch = 0; } public Memory2D(T[,,] array, int depth, int row, int column, int height, int width) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } int length = array.GetLength(1); int length2 = array.GetLength(2); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } instance = array; offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column)); this.height = height; this.width = width; pitch = length2 - width; } public Memory2D(MemoryManager memoryManager, int height, int width) : this(memoryManager, 0, height, width, 0) { } public Memory2D(MemoryManager memoryManager, int offset, int height, int width, int pitch) { int length = memoryManager.GetSpan().Length; if ((uint)offset > (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(Memory2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } instance = memoryManager; this.offset = (nint)(uint)offset; this.height = height; this.width = width; this.pitch = pitch; } internal Memory2D(Memory memory, int height, int width) : this(memory, 0, height, width, 0) { } internal Memory2D(Memory memory, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)memory.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(Memory2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = memory.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } ArraySegment segment; MemoryManager manager; int start2; if (typeof(T) == typeof(char) && MemoryMarshal.TryGetString(Unsafe.As, Memory>(ref memory), out string text, out int start, out int length)) { ref char data = ref text.DangerousGetReferenceAt(start + offset); instance = text; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref data); } else if (MemoryMarshal.TryGetArray((ReadOnlyMemory)memory, out segment)) { T[] array = (T[])(instance = segment.Array); this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(segment.Offset + offset)); } else if (MemoryMarshal.TryGetMemoryManager>(memory, out manager, out start2, out length)) { instance = manager; this.offset = (nint)(uint)(start2 + offset); } else { ThrowHelper.ThrowArgumentExceptionForUnsupportedType(); instance = null; this.offset = default(IntPtr); } this.height = height; this.width = width; this.pitch = pitch; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private Memory2D(object instance, IntPtr offset, int height, int width, int pitch) { this.instance = instance; this.offset = offset; this.height = height; this.width = width; this.pitch = pitch; } public static Memory2D DangerousCreate(object instance, ref T value, int height, int width, int pitch) { if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch); IntPtr intPtr = ObjectMarshal.DangerousGetObjectDataByteOffset(instance, ref value); return new Memory2D(instance, intPtr, height, width, pitch); } public Memory2D Slice(int row, int column, int height, int width) { if ((uint)row >= Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= this.width) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > Height - row) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > this.width - column) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } int num = (this.width + pitch) * row + column; int num2 = pitch + (this.width - width); IntPtr intPtr = offset + num * Unsafe.SizeOf(); return new Memory2D(instance, intPtr, height, width, num2); } public void CopyTo(Memory destination) { Span.CopyTo(destination.Span); } public bool TryCopyTo(Memory destination) { return Span.TryCopyTo(destination.Span); } public void CopyTo(Memory2D destination) { Span.CopyTo(destination.Span); } public bool TryCopyTo(Memory2D destination) { return Span.TryCopyTo(destination.Span); } public unsafe MemoryHandle Pin() { if (instance != null) { if (instance is MemoryManager memoryManager) { return memoryManager.Pin(); } GCHandle handle = GCHandle.Alloc(instance, GCHandleType.Pinned); return new MemoryHandle(Unsafe.AsPointer(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(instance, offset)), handle); } return default(MemoryHandle); } public bool TryGetMemory(out Memory memory) { if (pitch == 0 && Length <= int.MaxValue) { if (instance == null) { memory = default(Memory); } else if (typeof(T) == typeof(char) && instance.GetType() == typeof(string)) { string text = Unsafe.As(instance); int start = text.AsSpan().IndexOf(in ObjectMarshal.DangerousGetObjectDataReferenceAt(text, offset)); ReadOnlyMemory source = text.AsMemory(start, (int)Length); memory = MemoryMarshal.AsMemory(Unsafe.As, Memory>(ref source)); } else if (instance is MemoryManager memoryManager) { memory = memoryManager.Memory.Slice((int)(nint)offset, height * width); } else if (instance.GetType() == typeof(T[])) { T[] array = Unsafe.As(instance); int start2 = array.AsSpan().IndexOf(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, offset)); memory = array.AsMemory(start2, height * width); } else { if (!(instance.GetType() == typeof(T[,])) && !(instance.GetType() == typeof(T[,,]))) { goto IL_01bd; } memory = new RawObjectMemoryManager(instance, offset, height * width).Memory; } return true; } goto IL_01bd; IL_01bd: memory = default(Memory); return false; } public T[,] ToArray() { return Span.ToArray(); } [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { if (obj is Memory2D other) { return Equals(other); } if (obj is ReadOnlyMemory2D readOnlyMemory2D) { return readOnlyMemory2D.Equals(this); } return false; } public bool Equals(Memory2D other) { if (instance == other.instance && offset == other.offset && height == other.height && width == other.width) { return pitch == other.pitch; } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { if (instance != null) { return HashCode.Combine(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(instance), offset, height, width, pitch); } return 0; } public override string ToString() { return $"Microsoft.Toolkit.HighPerformance.Memory2D<{typeof(T)}>[{height}, {width}]"; } public static implicit operator Memory2D(T[,]? array) { return new Memory2D(array); } } [DebuggerTypeProxy(typeof(MemoryDebugView2D<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly struct ReadOnlyMemory2D : IEquatable> { private readonly object? instance; private readonly IntPtr offset; private readonly int height; private readonly int width; private readonly int pitch; public static ReadOnlyMemory2D Empty => default(ReadOnlyMemory2D); public bool IsEmpty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (height != 0) { return width == 0; } return true; } } public nint Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return (nint)(uint)height * (nint)(uint)width; } } public int Height { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return height; } } public int Width { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return width; } } public ReadOnlySpan2D Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (instance != null) { if (instance is MemoryManager memoryManager) { return new ReadOnlySpan2D(in Unsafe.Add(ref memoryManager.GetSpan().DangerousGetReference(), offset), height, width, pitch); } return new ReadOnlySpan2D(in ObjectMarshal.DangerousGetObjectDataReferenceAt(instance, offset), height, width, pitch); } return default(ReadOnlySpan2D); } } public ReadOnlyMemory2D this[Range rows, Range columns] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { var (row, num) = rows.GetOffsetAndLength(height); var (column, num2) = columns.GetOffsetAndLength(width); return Slice(row, column, num, num2); } } public ReadOnlyMemory2D(string text, int height, int width) : this(text, 0, height, width, 0) { } public ReadOnlyMemory2D(string text, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)text.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = text.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } instance = text; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref text.DangerousGetReferenceAt(offset)); this.height = height; this.width = width; this.pitch = pitch; } public ReadOnlyMemory2D(T[] array, int height, int width) : this(array, 0, height, width, 0) { } public ReadOnlyMemory2D(T[] array, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)array.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = array.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } instance = array; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(offset)); this.height = height; this.width = width; this.pitch = pitch; } public ReadOnlyMemory2D(T[,]? array) { if (array == null) { this = default(ReadOnlyMemory2D); return; } instance = array; offset = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.GetArray2DDataByteOffset(); height = array.GetLength(0); width = array.GetLength(1); pitch = 0; } public ReadOnlyMemory2D(T[,]? array, int row, int column, int height, int width) { if (array == null) { if (row != 0 || column != 0 || height != 0 || width != 0) { ThrowHelper.ThrowArgumentException(); } this = default(ReadOnlyMemory2D); return; } int length = array.GetLength(0); int length2 = array.GetLength(1); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } instance = array; offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(row, column)); this.height = height; this.width = width; pitch = length2 - width; } public ReadOnlyMemory2D(T[,,] array, int depth) { if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } instance = array; offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, 0, 0)); height = array.GetLength(1); width = array.GetLength(2); pitch = 0; } public ReadOnlyMemory2D(T[,,] array, int depth, int row, int column, int height, int width) { if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } int length = array.GetLength(1); int length2 = array.GetLength(2); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } instance = array; offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(depth, row, column)); this.height = height; this.width = width; pitch = length2 - width; } public ReadOnlyMemory2D(MemoryManager memoryManager, int height, int width) : this(memoryManager, 0, height, width, 0) { } public ReadOnlyMemory2D(MemoryManager memoryManager, int offset, int height, int width, int pitch) { int length = memoryManager.GetSpan().Length; if ((uint)offset > (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(ReadOnlyMemory2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } instance = memoryManager; this.offset = (nint)(uint)offset; this.height = height; this.width = width; this.pitch = pitch; } internal ReadOnlyMemory2D(ReadOnlyMemory memory, int height, int width) : this(memory, 0, height, width, 0) { } internal ReadOnlyMemory2D(ReadOnlyMemory memory, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)memory.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(ReadOnlyMemory2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = memory.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } ArraySegment segment; MemoryManager manager; int start2; if (typeof(T) == typeof(char) && MemoryMarshal.TryGetString(Unsafe.As, ReadOnlyMemory>(ref memory), out string text, out int start, out int length)) { ref char data = ref text.DangerousGetReferenceAt(start + offset); instance = text; this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(text, ref data); } else if (MemoryMarshal.TryGetArray(memory, out segment)) { T[] array = (T[])(instance = segment.Array); this.offset = ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array.DangerousGetReferenceAt(segment.Offset + offset)); } else if (MemoryMarshal.TryGetMemoryManager>(memory, out manager, out start2, out length)) { instance = manager; this.offset = (nint)(uint)(start2 + offset); } else { ThrowHelper.ThrowArgumentExceptionForUnsupportedType(); instance = null; this.offset = default(IntPtr); } this.height = height; this.width = width; this.pitch = pitch; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private ReadOnlyMemory2D(object instance, IntPtr offset, int height, int width, int pitch) { this.instance = instance; this.offset = offset; this.height = height; this.width = width; this.pitch = pitch; } public static ReadOnlyMemory2D DangerousCreate(object instance, ref T value, int height, int width, int pitch) { if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch); IntPtr intPtr = ObjectMarshal.DangerousGetObjectDataByteOffset(instance, ref value); return new ReadOnlyMemory2D(instance, intPtr, height, width, pitch); } public ReadOnlyMemory2D Slice(int row, int column, int height, int width) { if ((uint)row >= Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= this.width) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > Height - row) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > this.width - column) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } int num = (this.width + pitch) * row + column; int num2 = pitch + (this.width - width); IntPtr intPtr = offset + num * Unsafe.SizeOf(); return new ReadOnlyMemory2D(instance, intPtr, height, width, num2); } public void CopyTo(Memory destination) { Span.CopyTo(destination.Span); } public bool TryCopyTo(Memory destination) { return Span.TryCopyTo(destination.Span); } public void CopyTo(Memory2D destination) { Span.CopyTo(destination.Span); } public bool TryCopyTo(Memory2D destination) { return Span.TryCopyTo(destination.Span); } public unsafe MemoryHandle Pin() { if (instance != null) { if (instance is MemoryManager memoryManager) { return memoryManager.Pin(); } GCHandle handle = GCHandle.Alloc(instance, GCHandleType.Pinned); return new MemoryHandle(Unsafe.AsPointer(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(instance, offset)), handle); } return default(MemoryHandle); } public bool TryGetMemory(out ReadOnlyMemory memory) { if (pitch == 0 && Length <= int.MaxValue) { if (instance == null) { memory = default(ReadOnlyMemory); } else if (typeof(T) == typeof(char) && instance.GetType() == typeof(string)) { string text = Unsafe.As(instance); int start = text.AsSpan().IndexOf(in ObjectMarshal.DangerousGetObjectDataReferenceAt(text, offset)); ReadOnlyMemory source = text.AsMemory(start, (int)Length); memory = Unsafe.As, ReadOnlyMemory>(ref source); } else if (instance is MemoryManager memoryManager) { memory = memoryManager.Memory.Slice((int)(nint)offset, height * width); } else if (instance.GetType() == typeof(T[])) { T[] array = Unsafe.As(instance); int start2 = array.AsSpan().IndexOf(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(array, offset)); memory = array.AsMemory(start2, height * width); } else { if (!(instance.GetType() == typeof(T[,])) && !(instance.GetType() == typeof(T[,,]))) { goto IL_01c2; } memory = new RawObjectMemoryManager(instance, offset, height * width).Memory; } return true; } goto IL_01c2; IL_01c2: memory = default(ReadOnlyMemory); return false; } public T[,] ToArray() { return Span.ToArray(); } [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { if (obj is ReadOnlyMemory2D other) { return Equals(other); } if (obj is Memory2D memory2D) { return Equals(memory2D); } return false; } public bool Equals(ReadOnlyMemory2D other) { if (instance == other.instance && offset == other.offset && height == other.height && width == other.width) { return pitch == other.pitch; } return false; } [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { if (instance != null) { return HashCode.Combine(System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(instance), offset, height, width, pitch); } return 0; } public override string ToString() { return $"Microsoft.Toolkit.HighPerformance.ReadOnlyMemory2D<{typeof(T)}>[{height}, {width}]"; } public static implicit operator ReadOnlyMemory2D(T[,]? array) { return new ReadOnlyMemory2D(array); } public static implicit operator ReadOnlyMemory2D(Memory2D memory) { return Unsafe.As, ReadOnlyMemory2D>(ref memory); } } [DebuggerTypeProxy(typeof(MemoryDebugView2D<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly ref struct ReadOnlySpan2D { public ref struct Enumerator { private readonly ReadOnlySpan span; private readonly int width; private readonly int stride; private int x; private int y; public readonly ref readonly T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { ref T reference = ref MemoryMarshal.GetReference(span); nint elementOffset = (nint)(uint)y * (nint)(uint)stride + (nint)(uint)x; return ref Unsafe.Add(ref reference, elementOffset); } } internal Enumerator(ReadOnlySpan2D span) { this.span = span.span; width = span.width; stride = span.stride; x = -1; y = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int num = x + 1; if (num < width) { x = num; return true; } x = 0; return ++y < span.Length; } } private readonly ReadOnlySpan span; private readonly int width; private readonly int stride; public static ReadOnlySpan2D Empty => default(ReadOnlySpan2D); public bool IsEmpty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (Height != 0) { return width == 0; } return true; } } public nint Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return (nint)(uint)Height * (nint)(uint)width; } } public int Height { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Length; } } public int Width { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return width; } } public ref readonly T this[int row, int column] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)row >= (uint)Height || (uint)column >= (uint)Width) { ThrowHelper.ThrowIndexOutOfRangeException(); } return ref DangerousGetReferenceAt(row, column); } } public ref readonly T this[Index row, Index column] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref this[row.GetOffset(Height), column.GetOffset(width)]; } } public ReadOnlySpan2D this[Range rows, Range columns] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { var (row, height) = rows.GetOffsetAndLength(Height); var (column, num) = columns.GetOffsetAndLength(width); return Slice(row, column, height, num); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ReadOnlySpan2D(in T value, int height, int width, int pitch) { span = MemoryMarshal.CreateReadOnlySpan(in Unsafe.AsRef(in value), height); this.width = width; stride = width + pitch; } public unsafe ReadOnlySpan2D(void* pointer, int height, int width, int pitch) { if (System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences()) { ThrowHelper.ThrowArgumentExceptionForManagedType(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch); span = new ReadOnlySpan(pointer, height); this.width = width; stride = width + pitch; } public ReadOnlySpan2D(T[] array, int height, int width) : this(array, 0, height, width, 0) { } public ReadOnlySpan2D(T[] array, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)array.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(ReadOnlySpan2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = array.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } span = MemoryMarshal.CreateReadOnlySpan(in array.DangerousGetReferenceAt(offset), height); this.width = width; stride = width + pitch; } public ReadOnlySpan2D(T[,]? array) { if (array == null) { this = default(ReadOnlySpan2D); return; } span = MemoryMarshal.CreateReadOnlySpan(in array.DangerousGetReference(), array.GetLength(0)); width = (stride = array.GetLength(1)); } public ReadOnlySpan2D(T[,]? array, int row, int column, int height, int width) { if (array == null) { if (row != 0 || column != 0 || height != 0 || width != 0) { ThrowHelper.ThrowArgumentException(); } this = default(ReadOnlySpan2D); return; } int length = array.GetLength(0); int length2 = array.GetLength(1); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } span = MemoryMarshal.CreateReadOnlySpan(in array.DangerousGetReferenceAt(row, column), height); this.width = width; stride = length2; } public ReadOnlySpan2D(T[,,] array, int depth) { if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } span = MemoryMarshal.CreateReadOnlySpan(in array.DangerousGetReferenceAt(depth, 0, 0), array.GetLength(1)); width = (stride = array.GetLength(2)); } public ReadOnlySpan2D(T[,,] array, int depth, int row, int column, int height, int width) { if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } int length = array.GetLength(1); int length2 = array.GetLength(2); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } span = MemoryMarshal.CreateReadOnlySpan(in array.DangerousGetReferenceAt(depth, row, column), height); this.width = width; stride = length2; } internal ReadOnlySpan2D(ReadOnlySpan span, int height, int width) : this(span, 0, height, width, 0) { } internal ReadOnlySpan2D(ReadOnlySpan span, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)span.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(ReadOnlySpan2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = span.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } this.span = MemoryMarshal.CreateSpan(ref span.DangerousGetReferenceAt(offset), height); this.width = width; stride = width + pitch; } public static ReadOnlySpan2D DangerousCreate(in T value, int height, int width, int pitch) { if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch); return new ReadOnlySpan2D(in value, height, width, pitch); } public void CopyTo(Span destination) { if (IsEmpty) { return; } if (TryGetSpan(out var readOnlySpan)) { readOnlySpan.CopyTo(destination); return; } if (Length > destination.Length) { ThrowHelper.ThrowArgumentExceptionForDestinationTooShort(); } int num = 0; int num2 = 0; while (num < Height) { GetRowSpan(num).CopyTo(destination.Slice(num2)); num++; num2 += width; } } public void CopyTo(Span2D destination) { if (destination.Height != Height || destination.Width != Width) { ThrowHelper.ThrowArgumentExceptionForDestinationWithNotSameShape(); } if (IsEmpty) { return; } if (destination.TryGetSpan(out Span destination2)) { CopyTo(destination2); return; } for (int i = 0; i < Height; i++) { GetRowSpan(i).CopyTo(destination.GetRowSpan(i)); } } public bool TryCopyTo(Span destination) { if (destination.Length >= Length) { CopyTo(destination); return true; } return false; } public bool TryCopyTo(Span2D destination) { if (destination.Height == Height && destination.Width == Width) { CopyTo(destination); return true; } return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] [EditorBrowsable(EditorBrowsableState.Never)] public unsafe ref T GetPinnableReference() { ref T result = ref Unsafe.AsRef(null); if (Length != 0) { result = ref MemoryMarshal.GetReference(span); } return ref result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T DangerousGetReference() { return ref MemoryMarshal.GetReference(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T DangerousGetReferenceAt(int i, int j) { ref T reference = ref MemoryMarshal.GetReference(span); nint elementOffset = (nint)(uint)i * (nint)(uint)stride + (nint)(uint)j; return ref Unsafe.Add(ref reference, elementOffset); } public ReadOnlySpan2D Slice(int row, int column, int height, int width) { if ((uint)row >= Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= this.width) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > Height - row) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > this.width - column) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } nint i = (nint)(uint)stride * (nint)(uint)row + (nint)(uint)column; int pitch = stride - width; return new ReadOnlySpan2D(in span.DangerousGetReferenceAt(i), height, width, pitch); } public ReadOnlySpan GetRowSpan(int row) { if ((uint)row >= (uint)Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } return MemoryMarshal.CreateReadOnlySpan(in DangerousGetReferenceAt(row, 0), width); } public bool TryGetSpan(out ReadOnlySpan span) { if (stride == width && Length <= int.MaxValue) { span = MemoryMarshal.CreateReadOnlySpan(in MemoryMarshal.GetReference(this.span), (int)Length); return true; } span = default(ReadOnlySpan); return false; } public T[,] ToArray() { T[,] array = new T[Height, width]; CopyTo(array.AsSpan()); return array; } [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Equals() on Span will always throw an exception. Use == instead.")] public override bool Equals(object? obj) { throw new NotSupportedException("Microsoft.Toolkit.HighPerformance.ReadOnlySpan2D.Equals(object) is not supported"); } [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("GetHashCode() on Span will always throw an exception.")] public override int GetHashCode() { throw new NotSupportedException("Microsoft.Toolkit.HighPerformance.ReadOnlySpan2D.GetHashCode() is not supported"); } public override string ToString() { return $"Microsoft.Toolkit.HighPerformance.ReadOnlySpan2D<{typeof(T)}>[{Height}, {width}]"; } public static bool operator ==(ReadOnlySpan2D left, ReadOnlySpan2D right) { if (left.span == right.span && left.width == right.width) { return left.stride == right.stride; } return false; } public static bool operator !=(ReadOnlySpan2D left, ReadOnlySpan2D right) { return !(left == right); } public static implicit operator ReadOnlySpan2D(T[,]? array) { return new ReadOnlySpan2D(array); } public static implicit operator ReadOnlySpan2D(Span2D span) { return new ReadOnlySpan2D(in span.DangerousGetReference(), span.Height, span.Width, span.Stride - span.Width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyRefEnumerable GetRow(int row) { if ((uint)row >= Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } nint elementOffset = (nint)(uint)stride * (nint)(uint)row; return new ReadOnlyRefEnumerable(in Unsafe.Add(ref DangerousGetReference(), elementOffset), Width, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyRefEnumerable GetColumn(int column) { if ((uint)column >= Width) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } return new ReadOnlyRefEnumerable(in Unsafe.Add(ref DangerousGetReference(), (nint)(uint)column), Height, stride); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { return new Enumerator(this); } } [DebuggerTypeProxy(typeof(MemoryDebugView2D<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly ref struct Span2D { public ref struct Enumerator { private readonly Span span; private readonly int width; private readonly int stride; private int x; private int y; public readonly ref T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { ref T reference = ref MemoryMarshal.GetReference(span); nint elementOffset = (nint)(uint)y * (nint)(uint)stride + (nint)(uint)x; return ref Unsafe.Add(ref reference, elementOffset); } } internal Enumerator(Span2D span) { this.span = span.span; width = span.width; stride = span.Stride; x = -1; y = 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int num = x + 1; if (num < width) { x = num; return true; } x = 0; return ++y < span.Length; } } private readonly Span span; private readonly int width; internal readonly int Stride; public static Span2D Empty => default(Span2D); public bool IsEmpty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (Height != 0) { return width == 0; } return true; } } public nint Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return (nint)(uint)Height * (nint)(uint)width; } } public int Height { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Length; } } public int Width { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return width; } } public ref T this[int row, int column] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)row >= (uint)Height || (uint)column >= (uint)width) { ThrowHelper.ThrowIndexOutOfRangeException(); } return ref DangerousGetReferenceAt(row, column); } } public ref T this[Index row, Index column] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref this[row.GetOffset(Height), column.GetOffset(width)]; } } public Span2D this[Range rows, Range columns] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { var (row, height) = rows.GetOffsetAndLength(Height); var (column, num) = columns.GetOffsetAndLength(width); return Slice(row, column, height, num); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Span2D(ref T value, int height, int width, int pitch) { span = MemoryMarshal.CreateSpan(ref value, height); this.width = width; Stride = width + pitch; } public unsafe Span2D(void* pointer, int height, int width, int pitch) { if (System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences()) { ThrowHelper.ThrowArgumentExceptionForManagedType(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch); span = new Span(pointer, height); this.width = width; Stride = width + pitch; } public Span2D(T[] array, int height, int width) : this(array, 0, height, width, 0) { } public Span2D(T[] array, int offset, int height, int width, int pitch) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)offset > (uint)array.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = array.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(offset), height); this.width = width; Stride = width + pitch; } public Span2D(T[,]? array) { if (array == null) { this = default(Span2D); return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } span = MemoryMarshal.CreateSpan(ref array.DangerousGetReference(), array.GetLength(0)); width = (Stride = array.GetLength(1)); } public Span2D(T[,]? array, int row, int column, int height, int width) { if (array == null) { if (row != 0 || column != 0 || height != 0 || width != 0) { ThrowHelper.ThrowArgumentException(); } this = default(Span2D); return; } if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } int length = array.GetLength(0); int length2 = array.GetLength(1); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(row, column), height); this.width = width; Stride = length2; } public Span2D(T[,,] array, int depth) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(depth, 0, 0), array.GetLength(1)); width = (Stride = array.GetLength(2)); } public Span2D(T[,,] array, int depth, int row, int column, int height, int width) { if (array.IsCovariant()) { ThrowHelper.ThrowArrayTypeMismatchException(); } if ((uint)depth >= (uint)array.GetLength(0)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForDepth(); } int length = array.GetLength(1); int length2 = array.GetLength(2); if ((uint)row >= (uint)length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= (uint)length2) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > (uint)(length - row)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > (uint)(length2 - column)) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } span = MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(depth, row, column), height); this.width = width; Stride = length2; } internal Span2D(Span span, int height, int width) : this(span, 0, height, width, 0) { } internal Span2D(Span span, int offset, int height, int width, int pitch) { if ((uint)offset > (uint)span.Length) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForOffset(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } if (width == 0 || height == 0) { this = default(Span2D); return; } int num = OverflowHelper.ComputeInt32Area(height, width, pitch); int num2 = span.Length - offset; if (num > num2) { ThrowHelper.ThrowArgumentException(); } this.span = MemoryMarshal.CreateSpan(ref span.DangerousGetReferenceAt(offset), height); this.width = width; Stride = width + pitch; } public static Span2D DangerousCreate(ref T value, int height, int width, int pitch) { if (width < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } if (height < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if (pitch < 0) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } OverflowHelper.EnsureIsInNativeIntRange(height, width, pitch); return new Span2D(ref value, height, width, pitch); } public void Clear() { if (IsEmpty) { return; } if (TryGetSpan(out var span)) { span.Clear(); return; } for (int i = 0; i < Height; i++) { GetRowSpan(i).Clear(); } } public void CopyTo(Span destination) { if (IsEmpty) { return; } if (TryGetSpan(out var span)) { span.CopyTo(destination); return; } if (Length > destination.Length) { ThrowHelper.ThrowArgumentExceptionForDestinationTooShort(); } int num = 0; int num2 = 0; while (num < Height) { GetRowSpan(num).CopyTo(destination.Slice(num2)); num++; num2 += width; } } public void CopyTo(Span2D destination) { if (destination.Height != Height || destination.width != width) { ThrowHelper.ThrowArgumentExceptionForDestinationWithNotSameShape(); } if (IsEmpty) { return; } if (destination.TryGetSpan(out Span destination2)) { CopyTo(destination2); return; } for (int i = 0; i < Height; i++) { GetRowSpan(i).CopyTo(destination.GetRowSpan(i)); } } public bool TryCopyTo(Span destination) { if (destination.Length >= Length) { CopyTo(destination); return true; } return false; } public bool TryCopyTo(Span2D destination) { if (destination.Height == Height && destination.Width == width) { CopyTo(destination); return true; } return false; } public void Fill(T value) { if (IsEmpty) { return; } if (TryGetSpan(out var span)) { span.Fill(value); return; } for (int i = 0; i < Height; i++) { GetRowSpan(i).Fill(value); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] [EditorBrowsable(EditorBrowsableState.Never)] public unsafe ref T GetPinnableReference() { ref T result = ref Unsafe.AsRef(null); if (Length != 0) { result = ref MemoryMarshal.GetReference(span); } return ref result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T DangerousGetReference() { return ref MemoryMarshal.GetReference(span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T DangerousGetReferenceAt(int i, int j) { ref T reference = ref MemoryMarshal.GetReference(span); nint elementOffset = (nint)(uint)i * (nint)(uint)Stride + (nint)(uint)j; return ref Unsafe.Add(ref reference, elementOffset); } public Span2D Slice(int row, int column, int height, int width) { if ((uint)row >= Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } if ((uint)column >= this.width) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } if ((uint)height > Height - row) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForHeight(); } if ((uint)width > this.width - column) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForWidth(); } nint i = (nint)(uint)Stride * (nint)(uint)row + (nint)(uint)column; int pitch = Stride - width; return new Span2D(ref span.DangerousGetReferenceAt(i), height, width, pitch); } public Span GetRowSpan(int row) { if ((uint)row >= (uint)Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } return MemoryMarshal.CreateSpan(ref DangerousGetReferenceAt(row, 0), width); } public bool TryGetSpan(out Span span) { if (Stride == width && Length <= int.MaxValue) { span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(this.span), (int)Length); return true; } span = default(Span); return false; } public T[,] ToArray() { T[,] array = new T[Height, width]; CopyTo(array.AsSpan()); return array; } [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("Equals() on Span will always throw an exception. Use == instead.")] public override bool Equals(object? obj) { throw new NotSupportedException("Microsoft.Toolkit.HighPerformance.Span2D.Equals(object) is not supported"); } [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("GetHashCode() on Span will always throw an exception.")] public override int GetHashCode() { throw new NotSupportedException("Microsoft.Toolkit.HighPerformance.Span2D.GetHashCode() is not supported"); } public override string ToString() { return $"Microsoft.Toolkit.HighPerformance.Span2D<{typeof(T)}>[{Height}, {width}]"; } public static bool operator ==(Span2D left, Span2D right) { if (left.span == right.span && left.width == right.width) { return left.Stride == right.Stride; } return false; } public static bool operator !=(Span2D left, Span2D right) { return !(left == right); } public static implicit operator Span2D(T[,]? array) { return new Span2D(array); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RefEnumerable GetRow(int row) { if ((uint)row >= Height) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForRow(); } nint elementOffset = (nint)(uint)Stride * (nint)(uint)row; return new RefEnumerable(ref Unsafe.Add(ref DangerousGetReference(), elementOffset), Width, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public RefEnumerable GetColumn(int column) { if ((uint)column >= Width) { ThrowHelper.ThrowArgumentOutOfRangeExceptionForColumn(); } return new RefEnumerable(ref Unsafe.Add(ref DangerousGetReference(), (nint)(uint)column), Height, Stride); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { return new Enumerator(this); } } public readonly ref struct NullableReadOnlyRef { private readonly ReadOnlySpan span; public static NullableReadOnlyRef Null { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return default(NullableReadOnlyRef); } } public bool HasValue { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { byte b = (byte)span.Length; return b != 0; } } public ref readonly T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (!HasValue) { ThrowInvalidOperationException(); } return ref MemoryMarshal.GetReference(span); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public NullableReadOnlyRef(in T value) { span = MemoryMarshal.CreateReadOnlySpan(in Unsafe.AsRef(in value), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private NullableReadOnlyRef(ReadOnlySpan span) { this.span = span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator NullableReadOnlyRef(Ref reference) { return new NullableReadOnlyRef(reference.Span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator NullableReadOnlyRef(ReadOnlyRef reference) { return new NullableReadOnlyRef(reference.Span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator NullableReadOnlyRef(NullableRef reference) { return new NullableReadOnlyRef(reference.Span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator T(NullableReadOnlyRef reference) { return reference.Value; } private static void ThrowInvalidOperationException() { throw new InvalidOperationException("The current instance doesn't have a value that can be accessed"); } } public readonly ref struct NullableRef { internal readonly Span Span; public static NullableRef Null { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return default(NullableRef); } } public bool HasValue { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { byte b = (byte)Span.Length; return b != 0; } } public ref T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (!HasValue) { ThrowInvalidOperationException(); } return ref MemoryMarshal.GetReference(Span); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public NullableRef(ref T value) { Span = MemoryMarshal.CreateSpan(ref value, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private NullableRef(Span span) { Span = span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator NullableRef(Ref reference) { return new NullableRef(reference.Span); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static explicit operator T(NullableRef reference) { return reference.Value; } private static void ThrowInvalidOperationException() { throw new InvalidOperationException("The current instance doesn't have a value that can be accessed"); } } public readonly ref struct ReadOnlyRef { internal readonly ReadOnlySpan Span; public ref readonly T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref MemoryMarshal.GetReference(Span); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyRef(in T value) { Span = MemoryMarshal.CreateReadOnlySpan(in Unsafe.AsRef(in value), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ReadOnlyRef(void* pointer) : this(in Unsafe.AsRef(pointer)) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator ReadOnlyRef(Ref reference) { return new ReadOnlyRef(in reference.Value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator T(ReadOnlyRef reference) { return reference.Value; } } public readonly ref struct Ref { internal readonly Span Span; public ref T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref MemoryMarshal.GetReference(Span); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Ref(ref T value) { Span = MemoryMarshal.CreateSpan(ref value, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe Ref(void* pointer) : this(ref Unsafe.AsRef(pointer)) { } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator T(Ref reference) { return reference.Value; } } } namespace Microsoft.Toolkit.HighPerformance.Streams { internal sealed class IBufferWriterStream : Stream where TWriter : struct, IBufferWriter { private readonly TWriter bufferWriter; private bool disposed; public override bool CanRead => false; public override bool CanSeek => false; public override bool CanWrite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return !disposed; } } public override long Length { get { throw MemoryStream.GetNotSupportedException(); } } public override long Position { get { throw MemoryStream.GetNotSupportedException(); } set { throw MemoryStream.GetNotSupportedException(); } } public IBufferWriterStream(TWriter bufferWriter) { this.bufferWriter = bufferWriter; } public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { throw MemoryStream.GetNotSupportedException(); } public override void Flush() { } public override Task FlushAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } return Task.CompletedTask; } public override Task ReadAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) { throw MemoryStream.GetNotSupportedException(); } public override Task WriteAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } try { Write(buffer, offset, count); return Task.CompletedTask; } catch (OperationCanceledException ex) { return Task.FromCanceled(ex.CancellationToken); } catch (Exception exception) { return Task.FromException(exception); } } public override long Seek(long offset, SeekOrigin origin) { throw MemoryStream.GetNotSupportedException(); } public override void SetLength(long value) { throw MemoryStream.GetNotSupportedException(); } public override int Read(byte[]? buffer, int offset, int count) { throw MemoryStream.GetNotSupportedException(); } public override int ReadByte() { throw MemoryStream.GetNotSupportedException(); } public override void Write(byte[]? buffer, int offset, int count) { MemoryStream.ValidateDisposed(disposed); MemoryStream.ValidateBuffer(buffer, offset, count); Span span = buffer.AsSpan(offset, count); TWriter val = bufferWriter; Span span2 = val.GetSpan(count); if (!span.TryCopyTo(span2)) { MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); } val = bufferWriter; val.Advance(count); } public override void WriteByte(byte value) { MemoryStream.ValidateDisposed(disposed); TWriter val = bufferWriter; val.GetSpan(1)[0] = value; val = bufferWriter; val.Advance(1); } protected override void Dispose(bool disposing) { disposed = true; } public override void CopyTo(Stream destination, int bufferSize) { throw MemoryStream.GetNotSupportedException(); } public override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default(CancellationToken)) { throw MemoryStream.GetNotSupportedException(); } public override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return new ValueTask(Task.FromCanceled(cancellationToken)); } try { Write(buffer.Span); return default(ValueTask); } catch (OperationCanceledException ex) { return new ValueTask(Task.FromCanceled(ex.CancellationToken)); } catch (Exception exception) { return new ValueTask(Task.FromException(exception)); } } public override int Read(Span buffer) { throw MemoryStream.GetNotSupportedException(); } public override void Write(ReadOnlySpan buffer) { MemoryStream.ValidateDisposed(disposed); TWriter val = bufferWriter; Span span = val.GetSpan(buffer.Length); if (!buffer.TryCopyTo(span)) { MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); } val = bufferWriter; val.Advance(buffer.Length); } } internal sealed class IMemoryOwnerStream : MemoryStream where TSource : struct, ISpanOwner { private readonly IDisposable disposable; public IMemoryOwnerStream(TSource source, IDisposable disposable) : base(source, isReadOnly: false) { this.disposable = disposable; } protected override void Dispose(bool disposing) { base.Dispose(disposing); disposable.Dispose(); } } internal static class MemoryStream { public static Stream Create(ReadOnlyMemory memory, bool isReadOnly) { if (memory.IsEmpty) { return new MemoryStream(ArrayOwner.Empty, isReadOnly); } if (MemoryMarshal.TryGetArray(memory, out var segment)) { return new MemoryStream(new ArrayOwner(segment.Array, segment.Offset, segment.Count), isReadOnly); } if (MemoryMarshal.TryGetMemoryManager>(memory, out MemoryManager manager, out int start, out int length)) { return new MemoryStream(new MemoryManagerOwner(manager, start, length), isReadOnly); } return ThrowNotSupportedExceptionForInvalidMemory(); } public static Stream Create(IMemoryOwner memoryOwner) { Memory memory = memoryOwner.Memory; if (memory.IsEmpty) { return new IMemoryOwnerStream(ArrayOwner.Empty, memoryOwner); } if (MemoryMarshal.TryGetArray((ReadOnlyMemory)memory, out ArraySegment segment)) { return new IMemoryOwnerStream(new ArrayOwner(segment.Array, segment.Offset, segment.Count), memoryOwner); } if (MemoryMarshal.TryGetMemoryManager>(memory, out MemoryManager manager, out int start, out int length)) { return new IMemoryOwnerStream(new MemoryManagerOwner(manager, start, length), memoryOwner); } return ThrowNotSupportedExceptionForInvalidMemory(); } private static Stream ThrowNotSupportedExceptionForInvalidMemory() { throw new ArgumentException("The input instance doesn't have a valid underlying data store."); } public static Exception GetNotSupportedException() { return new NotSupportedException("The requested operation is not supported for this stream."); } public static void ThrowNotSupportedException() { throw GetNotSupportedException(); } public static void ThrowArgumentExceptionForEndOfStreamOnWrite() { throw new ArgumentException("The current stream can't contain the requested input data."); } public static long ThrowArgumentExceptionForSeekOrigin() { throw new ArgumentException("The input seek mode is not valid.", "origin"); } private static void ThrowArgumentOutOfRangeExceptionForPosition() { throw new ArgumentOutOfRangeException("Position", "The value for the property was not in the valid range."); } private static void ThrowArgumentNullExceptionForBuffer() { throw new ArgumentNullException("buffer", "The buffer is null."); } private static void ThrowArgumentOutOfRangeExceptionForOffset() { throw new ArgumentOutOfRangeException("offset", "Offset can't be negative."); } private static void ThrowArgumentOutOfRangeExceptionForCount() { throw new ArgumentOutOfRangeException("count", "Count can't be negative."); } private static void ThrowArgumentExceptionForLength() { throw new ArgumentException("The sum of offset and count can't be larger than the buffer length.", "buffer"); } private static void ThrowObjectDisposedException() { throw new ObjectDisposedException("source", "The current stream has already been disposed"); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ValidatePosition(long position, int length) { if ((ulong)position > (ulong)length) { ThrowArgumentOutOfRangeExceptionForPosition(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ValidateBuffer(byte[]? buffer, int offset, int count) { if (buffer == null) { ThrowArgumentNullExceptionForBuffer(); } if (offset < 0) { ThrowArgumentOutOfRangeExceptionForOffset(); } if (count < 0) { ThrowArgumentOutOfRangeExceptionForCount(); } if (offset + count > buffer.Length) { ThrowArgumentExceptionForLength(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ValidateCanWrite(bool canWrite) { if (!canWrite) { ThrowNotSupportedException(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ValidateDisposed(bool disposed) { if (disposed) { ThrowObjectDisposedException(); } } } internal class MemoryStream : Stream where TSource : struct, ISpanOwner { private readonly bool isReadOnly; private TSource source; private int position; private bool disposed; public sealed override bool CanRead { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return !disposed; } } public sealed override bool CanSeek { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return !disposed; } } public sealed override bool CanWrite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if (!isReadOnly) { return !disposed; } return false; } } public sealed override long Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { MemoryStream.ValidateDisposed(disposed); return source.Length; } } public sealed override long Position { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { MemoryStream.ValidateDisposed(disposed); return position; } [MethodImpl(MethodImplOptions.AggressiveInlining)] set { MemoryStream.ValidateDisposed(disposed); MemoryStream.ValidatePosition(value, source.Length); position = (int)value; } } public MemoryStream(TSource source, bool isReadOnly) { this.source = source; this.isReadOnly = isReadOnly; } public sealed override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } try { CopyTo(destination, bufferSize); return Task.CompletedTask; } catch (OperationCanceledException ex) { return Task.FromCanceled(ex.CancellationToken); } catch (Exception exception) { return Task.FromException(exception); } } public sealed override void Flush() { } public sealed override Task FlushAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } return Task.CompletedTask; } public sealed override Task ReadAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } try { return Task.FromResult(Read(buffer, offset, count)); } catch (OperationCanceledException ex) { return Task.FromCanceled(ex.CancellationToken); } catch (Exception exception) { return Task.FromException(exception); } } public sealed override Task WriteAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } try { Write(buffer, offset, count); return Task.CompletedTask; } catch (OperationCanceledException ex) { return Task.FromCanceled(ex.CancellationToken); } catch (Exception exception) { return Task.FromException(exception); } } public sealed override long Seek(long offset, SeekOrigin origin) { MemoryStream.ValidateDisposed(disposed); long num = origin switch { SeekOrigin.Begin => offset, SeekOrigin.Current => position + offset, SeekOrigin.End => source.Length + offset, _ => MemoryStream.ThrowArgumentExceptionForSeekOrigin(), }; MemoryStream.ValidatePosition(num, source.Length); position = (int)num; return num; } public sealed override void SetLength(long value) { throw MemoryStream.GetNotSupportedException(); } public sealed override int Read(byte[]? buffer, int offset, int count) { MemoryStream.ValidateDisposed(disposed); MemoryStream.ValidateBuffer(buffer, offset, count); int num = Math.Min(source.Length - position, count); Span span = source.Span.Slice(position, num); Span destination = buffer.AsSpan(offset, num); span.CopyTo(destination); position += num; return num; } public sealed override int ReadByte() { MemoryStream.ValidateDisposed(disposed); if (position == source.Length) { return -1; } return source.Span[position++]; } public sealed override void Write(byte[]? buffer, int offset, int count) { MemoryStream.ValidateDisposed(disposed); MemoryStream.ValidateCanWrite(CanWrite); MemoryStream.ValidateBuffer(buffer, offset, count); Span span = buffer.AsSpan(offset, count); Span destination = source.Span.Slice(position); if (!span.TryCopyTo(destination)) { MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); } position += span.Length; } public sealed override void WriteByte(byte value) { MemoryStream.ValidateDisposed(disposed); MemoryStream.ValidateCanWrite(CanWrite); if (position == source.Length) { MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); } source.Span[position++] = value; } protected override void Dispose(bool disposing) { if (!disposed) { disposed = true; source = default(TSource); } } public sealed override void CopyTo(Stream destination, int bufferSize) { MemoryStream.ValidateDisposed(disposed); Span span = source.Span.Slice(position); position += span.Length; destination.Write(span); } public sealed override ValueTask ReadAsync(Memory buffer, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return new ValueTask(Task.FromCanceled(cancellationToken)); } try { return new ValueTask(Read(buffer.Span)); } catch (OperationCanceledException ex) { return new ValueTask(Task.FromCanceled(ex.CancellationToken)); } catch (Exception exception) { return new ValueTask(Task.FromException(exception)); } } public sealed override ValueTask WriteAsync(ReadOnlyMemory buffer, CancellationToken cancellationToken = default(CancellationToken)) { if (cancellationToken.IsCancellationRequested) { return new ValueTask(Task.FromCanceled(cancellationToken)); } try { Write(buffer.Span); return default(ValueTask); } catch (OperationCanceledException ex) { return new ValueTask(Task.FromCanceled(ex.CancellationToken)); } catch (Exception exception) { return new ValueTask(Task.FromException(exception)); } } public sealed override int Read(Span buffer) { MemoryStream.ValidateDisposed(disposed); int num = Math.Min(source.Length - position, buffer.Length); source.Span.Slice(position, num).CopyTo(buffer); position += num; return num; } public sealed override void Write(ReadOnlySpan buffer) { MemoryStream.ValidateDisposed(disposed); MemoryStream.ValidateCanWrite(CanWrite); Span destination = source.Span.Slice(position); if (!buffer.TryCopyTo(destination)) { MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); } position += buffer.Length; } } internal readonly struct ArrayBufferWriterOwner : IBufferWriter { private readonly ArrayPoolBufferWriter writer; public ArrayBufferWriterOwner(ArrayPoolBufferWriter writer) { this.writer = writer; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Advance(int count) { writer.Advance(count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory GetMemory(int sizeHint = 0) { return writer.GetMemory(sizeHint); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetSpan(int sizeHint = 0) { return writer.GetSpan(sizeHint); } } internal readonly struct ArrayOwner : ISpanOwner { private readonly byte[] array; private readonly int offset; private readonly int length; public static ArrayOwner Empty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new ArrayOwner(Array.Empty(), 0, 0); } } public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return length; } } public Span Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return MemoryMarshal.CreateSpan(ref array.DangerousGetReferenceAt(offset), length); } } public ArrayOwner(byte[] array, int offset, int length) { this.array = array; this.offset = offset; this.length = length; } } internal readonly struct IBufferWriterOwner : IBufferWriter { private readonly IBufferWriter writer; public IBufferWriterOwner(IBufferWriter writer) { this.writer = writer; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Advance(int count) { writer.Advance(count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory GetMemory(int sizeHint = 0) { return writer.GetMemory(sizeHint); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span GetSpan(int sizeHint = 0) { return writer.GetSpan(sizeHint); } } internal interface ISpanOwner { int Length { get; } Span Span { get; } } internal readonly struct MemoryManagerOwner : ISpanOwner { private readonly MemoryManager memoryManager; private readonly int offset; private readonly int length; public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return length; } } public Span Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return memoryManager.GetSpan().Slice(offset, length); } } public MemoryManagerOwner(MemoryManager memoryManager, int offset, int length) { this.memoryManager = memoryManager; this.offset = offset; this.length = length; } } } namespace Microsoft.Toolkit.HighPerformance.Memory.Views { internal sealed class MemoryDebugView2D { [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] public T[,]? Items { get; } public MemoryDebugView2D(Memory2D memory) { Items = memory.ToArray(); } public MemoryDebugView2D(ReadOnlyMemory2D memory) { Items = memory.ToArray(); } public MemoryDebugView2D(Span2D span) { Items = span.ToArray(); } public MemoryDebugView2D(ReadOnlySpan2D span) { Items = span.ToArray(); } } } namespace Microsoft.Toolkit.HighPerformance.Memory.Internals { internal static class OverflowHelper { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void EnsureIsInNativeIntRange(int height, int width, int pitch) { checked { _ = unchecked((nint)checked(width + pitch)) * unchecked((nint)Math.Max(height - 1, 0)) + Math.Max(unchecked(width - 1), 0); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ComputeInt32Area(int height, int width, int pitch) { checked { return (width + pitch) * Math.Max(unchecked(height - 1), 0) + width; } } } internal static class ThrowHelper { public static void ThrowArgumentExceptionForManagedType() { throw new ArgumentException("Can't use a void* constructor when T is a managed type"); } public static void ThrowArgumentExceptionForDestinationTooShort() { throw new ArgumentException("The target span is too short to copy all the current items to"); } public static void ThrowArgumentExceptionForDestinationWithNotSameShape() { throw new ArgumentException("The target span does not have the same shape as the source one"); } public static void ThrowArrayTypeMismatchException() { throw new ArrayTypeMismatchException("The given array doesn't match the specified type T"); } public static void ThrowArgumentExceptionForUnsupportedType() { throw new ArgumentException("The specified object type is not supported"); } public static void ThrowIndexOutOfRangeException() { throw new IndexOutOfRangeException(); } public static void ThrowArgumentException() { throw new ArgumentException("One or more input parameters were invalid"); } public static void ThrowArgumentOutOfRangeExceptionForDepth() { throw new ArgumentOutOfRangeException("depth"); } public static void ThrowArgumentOutOfRangeExceptionForRow() { throw new ArgumentOutOfRangeException("row"); } public static void ThrowArgumentOutOfRangeExceptionForColumn() { throw new ArgumentOutOfRangeException("column"); } public static void ThrowArgumentOutOfRangeExceptionForOffset() { throw new ArgumentOutOfRangeException("offset"); } public static void ThrowArgumentOutOfRangeExceptionForHeight() { throw new ArgumentOutOfRangeException("height"); } public static void ThrowArgumentOutOfRangeExceptionForWidth() { throw new ArgumentOutOfRangeException("width"); } public static void ThrowArgumentOutOfRangeExceptionForPitch() { throw new ArgumentOutOfRangeException("pitch"); } } } namespace Microsoft.Toolkit.HighPerformance.Helpers { public static class BitHelper { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlag(uint value, int n) { byte b = (byte)((value >> n) & 1); return b != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasLookupFlag(uint table, int x, int min = 0) { int num = x - min; bool flag = (uint)num < 32u; int num2 = ~((flag ? 1 : 0) - 1); byte b = (byte)((table >> num) & 1 & (uint)num2); return b != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasZeroByte(uint value) { return ((value - 16843009) & ~value & 0x80808080u) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasZeroByte(ulong value) { return ((value - 72340172838076673L) & ~value & 0x8080808080808080uL) != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasByteEqualTo(uint value, byte target) { return HasZeroByte(value ^ (uint)(16843009 * target)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasByteEqualTo(ulong value, byte target) { return HasZeroByte(value ^ (ulong)(72340172838076673L * target)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetFlag(ref uint value, int n, bool flag) { value = SetFlag(value, n, flag); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint SetFlag(uint value, int n, bool flag) { uint num = (uint)(~(1 << n)); uint num2 = value & num; bool flag2 = flag; uint num3 = (flag2 ? 1u : 0u) << n; return num2 | num3; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint ExtractRange(uint value, byte start, byte length) { return (value >> (int)start) & (uint)((1 << (int)length) - 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetRange(ref uint value, byte start, byte length, uint flags) { value = SetRange(value, start, length, flags); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint SetRange(uint value, byte start, byte length, uint flags) { uint num = (uint)((1 << (int)length) - 1); uint num2 = num << (int)start; uint num3 = (flags & num) << (int)start; return (~num2 & value) | num3; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlag(ulong value, int n) { byte b = (byte)((value >> n) & 1); return b != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasLookupFlag(ulong table, int x, int min = 0) { int num = x - min; bool flag = (uint)num < 64u; int num2 = ~((flag ? 1 : 0) - 1); byte b = (byte)((int)((table >> num) & 1) & num2); return b != 0; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetFlag(ref ulong value, int n, bool flag) { value = SetFlag(value, n, flag); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong SetFlag(ulong value, int n, bool flag) { ulong num = (ulong)(~(1L << n)); ulong num2 = value & num; bool flag2 = flag; ulong num3 = (flag2 ? 1uL : 0uL) << n; return num2 | num3; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong ExtractRange(ulong value, byte start, byte length) { return (value >> (int)start) & (ulong)((1L << (int)length) - 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SetRange(ref ulong value, byte start, byte length, ulong flags) { value = SetRange(value, start, length, flags); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong SetRange(ulong value, byte start, byte length, ulong flags) { ulong num = (ulong)((1L << (int)length) - 1); ulong num2 = num << (int)start; ulong num3 = (flags & num) << (int)start; return (~num2 & value) | num3; } } [StructLayout(LayoutKind.Sequential, Size = 1)] public struct HashCode where T : notnull { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Combine(ReadOnlySpan span) { return HashCode.Combine(CombineValues(span)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static int CombineValues(ReadOnlySpan span) { ref T reference = ref MemoryMarshal.GetReference(span); if (System.Runtime.CompilerServices.RuntimeHelpers.IsReferenceOrContainsReferences()) { return SpanHelper.GetDjb2HashCode(ref reference, (nint)(uint)span.Length); } ref byte r = ref Unsafe.As(ref reference); nint length = (nint)(uint)(span.Length * Unsafe.SizeOf()); return SpanHelper.GetDjb2LikeByteHash(ref r, length); } } public static class ObjectMarshal { [StructLayout(LayoutKind.Explicit)] private sealed class RawObjectData { [FieldOffset(0)] public byte Data; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr DangerousGetObjectDataByteOffset(object obj, ref T data) { return Unsafe.ByteOffset(in Unsafe.As(obj).Data, in Unsafe.As(ref data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousGetObjectDataReferenceAt(object obj, IntPtr offset) { return ref Unsafe.As(ref Unsafe.AddByteOffset(ref Unsafe.As(obj).Data, offset)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryUnbox(this object obj, out T value) where T : struct { if (obj.GetType() == typeof(T)) { value = Unsafe.Unbox(obj); return true; } value = default(T); return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T DangerousUnbox(object obj) where T : struct { return ref Unsafe.Unbox(obj); } } public static class ParallelHelper { private readonly struct ActionInvoker where TAction : struct, IAction { private readonly int start; private readonly int end; private readonly int batchSize; private readonly TAction action; [MethodImpl(MethodImplOptions.AggressiveInlining)] public ActionInvoker(int start, int end, int batchSize, in TAction action) { this.start = start; this.end = end; this.batchSize = batchSize; this.action = action; } public void Invoke(int i) { int num = i * batchSize; int num2 = start + num; int num3 = Math.Min(num2 + batchSize, end); for (int j = num2; j < num3; j++) { Unsafe.AsRef(in action).Invoke(j); } } } private readonly struct Action2DInvoker where TAction : struct, IAction2D { private readonly int startY; private readonly int endY; private readonly int startX; private readonly int endX; private readonly int batchHeight; private readonly TAction action; [MethodImpl(MethodImplOptions.AggressiveInlining)] public Action2DInvoker(int startY, int endY, int startX, int endX, int batchHeight, in TAction action) { this.startY = startY; this.endY = endY; this.startX = startX; this.endX = endX; this.batchHeight = batchHeight; this.action = action; } public void Invoke(int i) { int num = i * batchHeight; int num2 = startY + num; int num3 = Math.Min(num2 + batchHeight, endY); for (int j = num2; j < num3; j++) { for (int k = startX; k < endX; k++) { Unsafe.AsRef(in action).Invoke(j, k); } } } } private readonly struct InActionInvoker where TAction : struct, IInAction { private readonly int batchSize; private readonly ReadOnlyMemory memory; private readonly TAction action; [MethodImpl(MethodImplOptions.AggressiveInlining)] public InActionInvoker(int batchSize, ReadOnlyMemory memory, in TAction action) { this.batchSize = batchSize; this.memory = memory; this.action = action; } public void Invoke(int i) { int num = i * batchSize; int elementOffset = Math.Min(num + batchSize, memory.Length); ref TItem reference = ref MemoryMarshal.GetReference(memory.Span); ref TItem reference2 = ref Unsafe.Add(ref reference, num); ref TItem right = ref Unsafe.Add(ref reference, elementOffset); while (Unsafe.IsAddressLessThan(in reference2, in right)) { Unsafe.AsRef(in action).Invoke(in reference2); reference2 = ref Unsafe.Add(ref reference2, 1); } } } private readonly struct InActionInvokerWithReadOnlyMemory2D where TAction : struct, IInAction { private readonly int batchHeight; private readonly ReadOnlyMemory2D memory; private readonly TAction action; [MethodImpl(MethodImplOptions.AggressiveInlining)] public InActionInvokerWithReadOnlyMemory2D(int batchHeight, ReadOnlyMemory2D memory, in TAction action) { this.batchHeight = batchHeight; this.memory = memory; this.action = action; } public void Invoke(int i) { int num = i * batchHeight; nint num2 = num + batchHeight; int num3 = (int)((num2 <= memory.Height) ? num2 : memory.Height); int width = memory.Width; ReadOnlySpan2D span = memory.Span; for (int j = num; j < num3; j++) { ref TItem reference = ref span.DangerousGetReferenceAt(j, 0); ref TItem right = ref Unsafe.Add(ref reference, width); while (Unsafe.IsAddressLessThan(in reference, in right)) { Unsafe.AsRef(in action).Invoke(in reference); reference = ref Unsafe.Add(ref reference, 1); } } } } private readonly struct RefActionInvoker where TAction : struct, IRefAction { private readonly int batchSize; private readonly ReadOnlyMemory memory; private readonly TAction action; [MethodImpl(MethodImplOptions.AggressiveInlining)] public RefActionInvoker(int batchSize, ReadOnlyMemory memory, in TAction action) { this.batchSize = batchSize; this.memory = memory; this.action = action; } public void Invoke(int i) { int num = i * batchSize; int elementOffset = Math.Min(num + batchSize, memory.Length); ref TItem reference = ref MemoryMarshal.GetReference(memory.Span); ref TItem reference2 = ref Unsafe.Add(ref reference, num); ref TItem right = ref Unsafe.Add(ref reference, elementOffset); while (Unsafe.IsAddressLessThan(in reference2, in right)) { Unsafe.AsRef(in action).Invoke(ref reference2); reference2 = ref Unsafe.Add(ref reference2, 1); } } } private readonly struct RefActionInvokerWithReadOnlyMemory2D where TAction : struct, IRefAction { private readonly int batchHeight; private readonly Memory2D memory; private readonly TAction action; [MethodImpl(MethodImplOptions.AggressiveInlining)] public RefActionInvokerWithReadOnlyMemory2D(int batchHeight, Memory2D memory, in TAction action) { this.batchHeight = batchHeight; this.memory = memory; this.action = action; } public void Invoke(int i) { int num = i * batchHeight; nint num2 = num + batchHeight; int num3 = (int)((num2 <= memory.Height) ? num2 : memory.Height); int width = memory.Width; ReadOnlySpan2D readOnlySpan2D = memory.Span; for (int j = num; j < num3; j++) { ref TItem reference = ref readOnlySpan2D.DangerousGetReferenceAt(j, 0); ref TItem right = ref Unsafe.Add(ref reference, width); while (Unsafe.IsAddressLessThan(in reference, in right)) { Unsafe.AsRef(in action).Invoke(ref reference); reference = ref Unsafe.Add(ref reference, 1); } } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(Range range) where TAction : struct, IAction { For(range, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(Range range, int minimumActionsPerThread) where TAction : struct, IAction { For(range, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(Range range, in TAction action) where TAction : struct, IAction { For(range, in action, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(Range range, in TAction action, int minimumActionsPerThread) where TAction : struct, IAction { if (range.Start.IsFromEnd || range.End.IsFromEnd) { ThrowArgumentExceptionForRangeIndexFromEnd("range"); } int value = range.Start.Value; int value2 = range.End.Value; For(value, value2, in action, minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(int start, int end) where TAction : struct, IAction { For(start, end, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(int start, int end, int minimumActionsPerThread) where TAction : struct, IAction { For(start, end, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For(int start, int end, in TAction action) where TAction : struct, IAction { For(start, end, in action, 1); } public static void For(int start, int end, in TAction action, int minimumActionsPerThread) where TAction : struct, IAction { if (minimumActionsPerThread <= 0) { ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread(); } if (start > end) { ThrowArgumentOutOfRangeExceptionForStartGreaterThanEnd(); } if (start == end) { return; } int num = Math.Abs(start - end); int val = 1 + (num - 1) / minimumActionsPerThread; int processorCount = Environment.ProcessorCount; int num2 = Math.Min(val, processorCount); if (num2 == 1) { for (int i = start; i < end; i++) { Unsafe.AsRef(in action).Invoke(i); } } else { int batchSize = 1 + (num - 1) / num2; ActionInvoker actionInvoker = new ActionInvoker(start, end, batchSize, in action); Parallel.For(0, num2, new ParallelOptions { MaxDegreeOfParallelism = num2 }, ((ActionInvoker)actionInvoker).Invoke); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Range i, Range j) where TAction : struct, IAction2D { For2D(i, j, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Range i, Range j, int minimumActionsPerThread) where TAction : struct, IAction2D { For2D(i, j, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Range i, Range j, in TAction action) where TAction : struct, IAction2D { For2D(i, j, in action, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Range i, Range j, in TAction action, int minimumActionsPerThread) where TAction : struct, IAction2D { if (i.Start.IsFromEnd || i.End.IsFromEnd) { ThrowArgumentExceptionForRangeIndexFromEnd("i"); } if (j.Start.IsFromEnd || j.End.IsFromEnd) { ThrowArgumentExceptionForRangeIndexFromEnd("j"); } int value = i.Start.Value; int value2 = i.End.Value; int value3 = j.Start.Value; int value4 = j.End.Value; For2D(value, value2, value3, value4, in action, minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Rectangle area) where TAction : struct, IAction2D { For2D(area.Top, area.Bottom, area.Left, area.Right, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Rectangle area, int minimumActionsPerThread) where TAction : struct, IAction2D { For2D(area.Top, area.Bottom, area.Left, area.Right, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Rectangle area, in TAction action) where TAction : struct, IAction2D { For2D(area.Top, area.Bottom, area.Left, area.Right, in action, 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(Rectangle area, in TAction action, int minimumActionsPerThread) where TAction : struct, IAction2D { For2D(area.Top, area.Bottom, area.Left, area.Right, in action, minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(int top, int bottom, int left, int right) where TAction : struct, IAction2D { For2D(top, bottom, left, right, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(int top, int bottom, int left, int right, int minimumActionsPerThread) where TAction : struct, IAction2D { For2D(top, bottom, left, right, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void For2D(int top, int bottom, int left, int right, in TAction action) where TAction : struct, IAction2D { For2D(top, bottom, left, right, in action, 1); } public static void For2D(int top, int bottom, int left, int right, in TAction action, int minimumActionsPerThread) where TAction : struct, IAction2D { if (minimumActionsPerThread <= 0) { ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread(); } if (top > bottom) { ThrowArgumentOutOfRangeExceptionForTopGreaterThanBottom(); } if (left > right) { ThrowArgumentOutOfRangeExceptionForLeftGreaterThanRight(); } if (top == bottom || left == right) { return; } int num = Math.Abs(top - bottom); int num2 = Math.Abs(left - right); int num3 = num * num2; int val = Math.Min(1 + (num3 - 1) / minimumActionsPerThread, num); int processorCount = Environment.ProcessorCount; int num4 = Math.Min(val, processorCount); if (num4 == 1) { for (int i = top; i < bottom; i++) { for (int j = left; j < right; j++) { Unsafe.AsRef(in action).Invoke(i, j); } } } else { int batchHeight = 1 + (num - 1) / num4; Action2DInvoker action2DInvoker = new Action2DInvoker(top, bottom, left, right, batchHeight, in action); Parallel.For(0, num4, new ParallelOptions { MaxDegreeOfParallelism = num4 }, ((Action2DInvoker)action2DInvoker).Invoke); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(ReadOnlyMemory memory) where TAction : struct, IInAction { ForEach(memory, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(ReadOnlyMemory memory, int minimumActionsPerThread) where TAction : struct, IInAction { ForEach(memory, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(ReadOnlyMemory memory, in TAction action) where TAction : struct, IInAction { ForEach(memory, in action, 1); } public static void ForEach(ReadOnlyMemory memory, in TAction action, int minimumActionsPerThread) where TAction : struct, IInAction { if (minimumActionsPerThread <= 0) { ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread(); } if (memory.IsEmpty) { return; } int val = 1 + (memory.Length - 1) / minimumActionsPerThread; int processorCount = Environment.ProcessorCount; int num = Math.Min(val, processorCount); if (num == 1) { ReadOnlySpan span = memory.Span; for (int i = 0; i < span.Length; i++) { TItem item = span[i]; Unsafe.AsRef(in action).Invoke(in item); } } else { int batchSize = 1 + (memory.Length - 1) / num; InActionInvoker inActionInvoker = new InActionInvoker(batchSize, memory, in action); Parallel.For(0, num, new ParallelOptions { MaxDegreeOfParallelism = num }, ((InActionInvoker)inActionInvoker).Invoke); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(ReadOnlyMemory2D memory) where TAction : struct, IInAction { ForEach(memory, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(ReadOnlyMemory2D memory, int minimumActionsPerThread) where TAction : struct, IInAction { ForEach(memory, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(ReadOnlyMemory2D memory, in TAction action) where TAction : struct, IInAction { ForEach(memory, in action, 1); } public static void ForEach(ReadOnlyMemory2D memory, in TAction action, int minimumActionsPerThread) where TAction : struct, IInAction { if (minimumActionsPerThread <= 0) { ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread(); } if (!memory.IsEmpty) { nint num = 1 + (memory.Length - 1) / minimumActionsPerThread; IntPtr intPtr = ((num <= memory.Height) ? num : memory.Height); int processorCount = Environment.ProcessorCount; int num2 = (int)(((nint)intPtr <= processorCount) ? ((nint)intPtr) : ((nint)processorCount)); int batchHeight = 1 + (memory.Height - 1) / num2; InActionInvokerWithReadOnlyMemory2D inActionInvokerWithReadOnlyMemory2D = new InActionInvokerWithReadOnlyMemory2D(batchHeight, memory, in action); if (num2 == 1) { inActionInvokerWithReadOnlyMemory2D.Invoke(0); return; } Parallel.For(0, num2, new ParallelOptions { MaxDegreeOfParallelism = num2 }, ((InActionInvokerWithReadOnlyMemory2D)inActionInvokerWithReadOnlyMemory2D).Invoke); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(Memory memory) where TAction : struct, IRefAction { ForEach(memory, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(Memory memory, int minimumActionsPerThread) where TAction : struct, IRefAction { ForEach(memory, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(Memory memory, in TAction action) where TAction : struct, IRefAction { ForEach(memory, in action, 1); } public static void ForEach(Memory memory, in TAction action, int minimumActionsPerThread) where TAction : struct, IRefAction { if (minimumActionsPerThread <= 0) { ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread(); } if (memory.IsEmpty) { return; } int val = 1 + (memory.Length - 1) / minimumActionsPerThread; int processorCount = Environment.ProcessorCount; int num = Math.Min(val, processorCount); if (num == 1) { Span span = memory.Span; for (int i = 0; i < span.Length; i++) { ref TItem item = ref span[i]; Unsafe.AsRef(in action).Invoke(ref item); } } else { int batchSize = 1 + (memory.Length - 1) / num; RefActionInvoker refActionInvoker = new RefActionInvoker(batchSize, memory, in action); Parallel.For(0, num, new ParallelOptions { MaxDegreeOfParallelism = num }, ((RefActionInvoker)refActionInvoker).Invoke); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(Memory2D memory) where TAction : struct, IRefAction { ForEach(memory, default(TAction), 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(Memory2D memory, int minimumActionsPerThread) where TAction : struct, IRefAction { ForEach(memory, default(TAction), minimumActionsPerThread); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ForEach(Memory2D memory, in TAction action) where TAction : struct, IRefAction { ForEach(memory, in action, 1); } public static void ForEach(Memory2D memory, in TAction action, int minimumActionsPerThread) where TAction : struct, IRefAction { if (minimumActionsPerThread <= 0) { ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread(); } if (!memory.IsEmpty) { nint num = 1 + (memory.Length - 1) / minimumActionsPerThread; IntPtr intPtr = ((num <= memory.Height) ? num : memory.Height); int processorCount = Environment.ProcessorCount; int num2 = (int)(((nint)intPtr <= processorCount) ? ((nint)intPtr) : ((nint)processorCount)); int batchHeight = 1 + (memory.Height - 1) / num2; RefActionInvokerWithReadOnlyMemory2D refActionInvokerWithReadOnlyMemory2D = new RefActionInvokerWithReadOnlyMemory2D(batchHeight, memory, in action); if (num2 == 1) { refActionInvokerWithReadOnlyMemory2D.Invoke(0); return; } Parallel.For(0, num2, new ParallelOptions { MaxDegreeOfParallelism = num2 }, ((RefActionInvokerWithReadOnlyMemory2D)refActionInvokerWithReadOnlyMemory2D).Invoke); } } private static void ThrowArgumentOutOfRangeExceptionForInvalidMinimumActionsPerThread() { throw new ArgumentOutOfRangeException("minimumActionsPerThread", "Each thread needs to perform at least one action"); } private static void ThrowArgumentOutOfRangeExceptionForStartGreaterThanEnd() { throw new ArgumentOutOfRangeException("start", "The start parameter must be less than or equal to end"); } private static void ThrowArgumentExceptionForRangeIndexFromEnd(string name) { throw new ArgumentException("The bounds of the range can't start from an end", name); } private static void ThrowArgumentOutOfRangeExceptionForTopGreaterThanBottom() { throw new ArgumentOutOfRangeException("top", "The top parameter must be less than or equal to bottom"); } private static void ThrowArgumentOutOfRangeExceptionForLeftGreaterThanRight() { throw new ArgumentOutOfRangeException("left", "The left parameter must be less than or equal to right"); } } public interface IAction { void Invoke(int i); } public interface IAction2D { void Invoke(int i, int j); } public interface IInAction { void Invoke(in T item); } public interface IRefAction { void Invoke(ref T item); } } namespace Microsoft.Toolkit.HighPerformance.Helpers.Internals { internal static class BitOperations { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int RoundUpPowerOfTwo(int x) { x--; x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x++; return x; } } internal static class RefEnumerableHelper { public static void Clear(ref T r0, nint length, nint step) { nint num = 0; while (length >= 8) { Unsafe.Add(ref r0, num) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); length -= 8; num += step; } if (length >= 4) { Unsafe.Add(ref r0, num) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); Unsafe.Add(ref r0, num += step) = default(T); length -= 4; num += step; } while (length > 0) { Unsafe.Add(ref r0, num) = default(T); length--; num += step; } } public static void CopyTo(ref T sourceRef, ref T destinationRef, nint length, nint sourceStep) { nint num = 0; nint num2 = 0; while (length >= 8) { Unsafe.Add(ref destinationRef, num2 + 0) = Unsafe.Add(ref sourceRef, num); Unsafe.Add(ref destinationRef, num2 + 1) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 2) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 3) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 4) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 5) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 6) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 7) = Unsafe.Add(ref sourceRef, num += sourceStep); length -= 8; num += sourceStep; num2 += 8; } if (length >= 4) { Unsafe.Add(ref destinationRef, num2 + 0) = Unsafe.Add(ref sourceRef, num); Unsafe.Add(ref destinationRef, num2 + 1) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 2) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 + 3) = Unsafe.Add(ref sourceRef, num += sourceStep); length -= 4; num += sourceStep; num2 += 4; } while (length > 0) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); length--; num += sourceStep; num2++; } } public static void CopyTo(ref T sourceRef, ref T destinationRef, nint length, nint sourceStep, nint destinationStep) { nint num = 0; nint num2 = 0; while (length >= 8) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); length -= 8; num += sourceStep; num2 += destinationStep; } if (length >= 4) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); Unsafe.Add(ref destinationRef, num2 += destinationStep) = Unsafe.Add(ref sourceRef, num += sourceStep); length -= 4; num += sourceStep; num2 += destinationStep; } while (length > 0) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); length--; num += sourceStep; num2 += destinationStep; } } public static void CopyFrom(ref T sourceRef, ref T destinationRef, nint length, nint sourceStep) { nint num = 0; nint num2 = 0; while (length >= 8) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 1); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 2); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 3); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 4); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 5); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 6); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 7); length -= 8; num += 8; num2 += sourceStep; } if (length >= 4) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 1); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 2); Unsafe.Add(ref destinationRef, num2 += sourceStep) = Unsafe.Add(ref sourceRef, num + 3); length -= 4; num += 4; num2 += sourceStep; } while (length > 0) { Unsafe.Add(ref destinationRef, num2) = Unsafe.Add(ref sourceRef, num); length--; num++; num2 += sourceStep; } } public static void Fill(ref T r0, nint length, nint step, T value) { nint num = 0; while (length >= 8) { Unsafe.Add(ref r0, num) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; length -= 8; num += step; } if (length >= 4) { Unsafe.Add(ref r0, num) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; Unsafe.Add(ref r0, num += step) = value; length -= 4; num += step; } while (length > 0) { Unsafe.Add(ref r0, num) = value; length--; num += step; } } } internal static class RuntimeHelpers { private static class TypeInfo { public static readonly IntPtr ArrayDataByteOffset = MeasureArrayDataByteOffset(); public static readonly IntPtr Array2DDataByteOffset = MeasureArray2DDataByteOffset(); public static readonly IntPtr Array3DDataByteOffset = MeasureArray3DDataByteOffset(); private static IntPtr MeasureArrayDataByteOffset() { T[] array = new T[1]; return ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0]); } private static IntPtr MeasureArray2DDataByteOffset() { T[,] array = new T[1, 1]; return ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0, 0]); } private static IntPtr MeasureArray3DDataByteOffset() { T[,,] array = new T[1, 1, 1]; return ObjectMarshal.DangerousGetObjectDataByteOffset(array, ref array[0, 0, 0]); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe static int ConvertLength(int length) where TFrom : unmanaged where TTo : unmanaged { if (sizeof(TFrom) == sizeof(TTo)) { return length; } if (sizeof(TFrom) == 1) { return (int)((uint)length / (uint)sizeof(TTo)); } checked { return (int)unchecked((ulong)((long)(uint)length * (long)(uint)sizeof(TFrom)) / (ulong)(uint)sizeof(TTo)); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static nint GetArrayNativeLength(T[] array) { return (nint)array.LongLength; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static nint GetArrayNativeLength(Array array) { return (nint)array.LongLength; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr GetArrayDataByteOffset() { return TypeInfo.ArrayDataByteOffset; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr GetArray2DDataByteOffset() { return TypeInfo.Array2DDataByteOffset; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr GetArray3DDataByteOffset() { return TypeInfo.Array3DDataByteOffset; } } internal static class SpanHelper { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static nint Count(ref T r0, nint length, T value) where T : IEquatable { if (!Vector.IsHardwareAccelerated) { return CountSequential(ref r0, length, value); } if (typeof(T) == typeof(byte) || typeof(T) == typeof(sbyte) || typeof(T) == typeof(bool)) { ref sbyte r1 = ref Unsafe.As(ref r0); sbyte value2 = Unsafe.As(ref value); return CountSimd(ref r1, length, value2); } if (typeof(T) == typeof(char) || typeof(T) == typeof(ushort) || typeof(T) == typeof(short)) { ref short r2 = ref Unsafe.As(ref r0); short value3 = Unsafe.As(ref value); return CountSimd(ref r2, length, value3); } if (typeof(T) == typeof(int) || typeof(T) == typeof(uint)) { ref int r3 = ref Unsafe.As(ref r0); int value4 = Unsafe.As(ref value); return CountSimd(ref r3, length, value4); } if (typeof(T) == typeof(long) || typeof(T) == typeof(ulong)) { ref long r4 = ref Unsafe.As(ref r0); long value5 = Unsafe.As(ref value); return CountSimd(ref r4, length, value5); } return CountSequential(ref r0, length, value); } private static nint CountSequential(ref T r0, nint length, T value) where T : IEquatable { nint num = 0; nint num2 = 0; while (length >= 8) { num += Unsafe.Add(ref r0, num2 + 0).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 1).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 2).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 3).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 4).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 5).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 6).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 7).Equals(value).ToByte(); length -= 8; num2 += 8; } if (length >= 4) { num += Unsafe.Add(ref r0, num2 + 0).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 1).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 2).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 3).Equals(value).ToByte(); length -= 4; num2 += 4; } while (length > 0) { num += Unsafe.Add(ref r0, num2).Equals(value).ToByte(); length--; num2++; } return num; } private static nint CountSimd(ref T r0, nint length, T value) where T : unmanaged, IEquatable { nint num = 0; nint num2 = 0; if (length >= Vector.Count) { Vector right = new Vector(value); do { nint upperBound = GetUpperBound(); nint num3 = ((length <= upperBound) ? length : upperBound); nint num4 = num2; Vector zero = Vector.Zero; if (typeof(T) != typeof(sbyte)) { while (num3 >= Vector.Count * 8) { nint num5 = num2; _ = Vector.Count; Vector vector = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num5 + 0)), right); zero -= vector; Vector vector2 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count)), right); zero -= vector2; Vector vector3 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count * 2)), right); zero -= vector3; Vector vector4 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count * 3)), right); zero -= vector4; Vector vector5 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count * 4)), right); zero -= vector5; Vector vector6 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count * 5)), right); zero -= vector6; Vector vector7 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count * 6)), right); zero -= vector7; Vector vector8 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2 + Vector.Count * 7)), right); zero -= vector8; num3 -= Vector.Count * 8; num2 += Vector.Count * 8; } } while (num3 >= Vector.Count) { Vector vector9 = Vector.Equals(Unsafe.As>(ref Unsafe.Add(ref r0, num2)), right); zero -= vector9; num3 -= Vector.Count; num2 += Vector.Count; } num += CastToNativeInt(Vector.Dot(zero, Vector.One)); length -= num2 - num4; } while (length >= Vector.Count); } if (Vector.Count > 8 && length >= 8) { num += Unsafe.Add(ref r0, num2 + 0).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 1).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 2).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 3).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 4).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 5).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 6).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 7).Equals(value).ToByte(); length -= 8; num2 += 8; } if (Vector.Count > 4 && length >= 4) { num += Unsafe.Add(ref r0, num2 + 0).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 1).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 2).Equals(value).ToByte(); num += Unsafe.Add(ref r0, num2 + 3).Equals(value).ToByte(); length -= 4; num2 += 4; } while (length > 0) { num += Unsafe.Add(ref r0, num2).Equals(value).ToByte(); length--; num2++; } return num; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private unsafe static nint GetUpperBound() where T : unmanaged { if (typeof(T) == typeof(sbyte)) { return 127; } if (typeof(T) == typeof(short)) { return 32767; } if (typeof(T) == typeof(int)) { return int.MaxValue; } if (typeof(T) == typeof(long)) { if (sizeof(IntPtr) == 4) { return int.MaxValue; } return unchecked((nint)long.MaxValue); } throw null; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static nint CastToNativeInt(T value) where T : unmanaged { if (typeof(T) == typeof(sbyte)) { return (byte)(sbyte)(object)value; } if (typeof(T) == typeof(short)) { return (ushort)(short)(object)value; } if (typeof(T) == typeof(int)) { return (nint)(uint)(int)(object)value; } if (typeof(T) == typeof(long)) { return (nint)(long)(object)value; } throw null; } public static int GetDjb2HashCode(ref T r0, nint length) where T : notnull { int num = 5381; nint num2 = 0; while (length >= 8) { num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 0).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 1).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 2).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 3).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 4).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 5).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 6).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 7).GetHashCode(); length -= 8; num2 += 8; } if (length >= 4) { num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 0).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 1).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 2).GetHashCode(); num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2 + 3).GetHashCode(); length -= 4; num2 += 4; } while (length > 0) { num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2).GetHashCode(); length--; num2++; } return num; } public unsafe static int GetDjb2LikeByteHash(ref byte r0, nint length) { int num = 5381; nint num2 = 0; if (Vector.IsHardwareAccelerated && length >= Vector.Count << 3) { Vector left = new Vector(5381); Vector right = new Vector(33); while (length >= Vector.Count << 3) { nint num3 = num2; _ = Vector.Count; Vector right2 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num3 + 0)); left = Vector.Xor(Vector.Multiply(left, right), right2); Vector right3 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count)); left = Vector.Xor(Vector.Multiply(left, right), right3); Vector right4 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count * 2)); left = Vector.Xor(Vector.Multiply(left, right), right4); Vector right5 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count * 3)); left = Vector.Xor(Vector.Multiply(left, right), right5); Vector right6 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count * 4)); left = Vector.Xor(Vector.Multiply(left, right), right6); Vector right7 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count * 5)); left = Vector.Xor(Vector.Multiply(left, right), right7); Vector right8 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count * 6)); left = Vector.Xor(Vector.Multiply(left, right), right8); Vector right9 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2 + Vector.Count * 7)); left = Vector.Xor(Vector.Multiply(left, right), right9); length -= Vector.Count << 3; num2 += Vector.Count << 3; } while (length >= Vector.Count) { Vector right10 = Unsafe.ReadUnaligned>(in Unsafe.Add(ref r0, num2)); left = Vector.Xor(Vector.Multiply(left, right), right10); length -= Vector.Count; num2 += Vector.Count; } for (int i = 0; i < Vector.Count; i++) { num = ((num << 5) + num) ^ left[i]; } } else { if (sizeof(IntPtr) == 8) { while (length >= 64) { ulong num4 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 0)); num = ((num << 5) + num) ^ (int)num4 ^ (int)(num4 >> 32); ulong num5 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 8)); num = ((num << 5) + num) ^ (int)num5 ^ (int)(num5 >> 32); ulong num6 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 16)); num = ((num << 5) + num) ^ (int)num6 ^ (int)(num6 >> 32); ulong num7 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 24)); num = ((num << 5) + num) ^ (int)num7 ^ (int)(num7 >> 32); ulong num8 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 32)); num = ((num << 5) + num) ^ (int)num8 ^ (int)(num8 >> 32); ulong num9 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 40)); num = ((num << 5) + num) ^ (int)num9 ^ (int)(num9 >> 32); ulong num10 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 48)); num = ((num << 5) + num) ^ (int)num10 ^ (int)(num10 >> 32); ulong num11 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 56)); num = ((num << 5) + num) ^ (int)num11 ^ (int)(num11 >> 32); length -= 64; num2 += 64; } } while (length >= 32) { uint num12 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 0)); num = ((num << 5) + num) ^ (int)num12; uint num13 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 4)); num = ((num << 5) + num) ^ (int)num13; uint num14 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 8)); num = ((num << 5) + num) ^ (int)num14; uint num15 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 12)); num = ((num << 5) + num) ^ (int)num15; uint num16 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 16)); num = ((num << 5) + num) ^ (int)num16; uint num17 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 20)); num = ((num << 5) + num) ^ (int)num17; uint num18 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 24)); num = ((num << 5) + num) ^ (int)num18; uint num19 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 28)); num = ((num << 5) + num) ^ (int)num19; length -= 32; num2 += 32; } } if (length >= 16) { ushort num20 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 0)); num = ((num << 5) + num) ^ num20; ushort num21 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 2)); num = ((num << 5) + num) ^ num21; ushort num22 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 4)); num = ((num << 5) + num) ^ num22; ushort num23 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 6)); num = ((num << 5) + num) ^ num23; ushort num24 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 8)); num = ((num << 5) + num) ^ num24; ushort num25 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 10)); num = ((num << 5) + num) ^ num25; ushort num26 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 12)); num = ((num << 5) + num) ^ num26; ushort num27 = Unsafe.ReadUnaligned(in Unsafe.Add(ref r0, num2 + 14)); num = ((num << 5) + num) ^ num27; length -= 16; num2 += 16; } while (length > 0) { num = ((num << 5) + num) ^ Unsafe.Add(ref r0, num2); length--; num2++; } return num; } } } namespace Microsoft.Toolkit.HighPerformance.Enumerables { public readonly ref struct ReadOnlyRefEnumerable { public ref struct Enumerator { private readonly ReadOnlySpan span; private readonly int step; private int position; public readonly ref readonly T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { ref T source = ref span.DangerousGetReference(); nint elementOffset = (nint)(uint)position * (nint)(uint)step; return ref Unsafe.Add(ref source, elementOffset); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(ReadOnlySpan span, int step) { this.span = span; this.step = step; position = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { return ++position < span.Length; } } private readonly ReadOnlySpan span; private readonly int step; public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Length; } } public ref readonly T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)index >= (uint)Length) { ThrowHelper.ThrowIndexOutOfRangeException(); } ref T reference = ref MemoryMarshal.GetReference(span); nint elementOffset = (nint)(uint)index * (nint)(uint)step; return ref Unsafe.Add(ref reference, elementOffset); } } public ref readonly T this[Index index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref this[index.GetOffset(Length)]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private ReadOnlyRefEnumerable(ReadOnlySpan span, int step) { this.span = span; this.step = step; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ReadOnlyRefEnumerable(in T reference, int length, int step) { span = MemoryMarshal.CreateReadOnlySpan(in Unsafe.AsRef(in reference), length); this.step = step; } public static ReadOnlyRefEnumerable DangerousCreate(in T value, int length, int step) { if (length < 0) { ThrowArgumentOutOfRangeExceptionForLength(); } if (step < 0) { ThrowArgumentOutOfRangeExceptionForStep(); } OverflowHelper.EnsureIsInNativeIntRange(length, 1, step); return new ReadOnlyRefEnumerable(in value, length, step); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { return new Enumerator(span, step); } public void CopyTo(RefEnumerable destination) { if (step == 1) { destination.CopyFrom(span); return; } if (destination.Step == 1) { CopyTo(destination.Span); return; } ref T sourceRef = ref span.DangerousGetReference(); ref T destinationRef = ref destination.Span.DangerousGetReference(); int length = span.Length; if ((uint)destination.Span.Length < (uint)length) { ThrowArgumentExceptionForDestinationTooShort(); } RefEnumerableHelper.CopyTo(ref sourceRef, ref destinationRef, (nint)(uint)length, (nint)(uint)step, (nint)(uint)destination.Step); } public bool TryCopyTo(RefEnumerable destination) { int length = span.Length; if (destination.Span.Length >= length) { CopyTo(destination); return true; } return false; } public void CopyTo(Span destination) { if (step == 1) { span.CopyTo(destination); return; } ref T sourceRef = ref span.DangerousGetReference(); int length = span.Length; if ((uint)destination.Length < (uint)length) { ThrowArgumentExceptionForDestinationTooShort(); } RefEnumerableHelper.CopyTo(ref sourceRef, ref destination.DangerousGetReference(), (nint)(uint)length, (nint)(uint)step); } public bool TryCopyTo(Span destination) { int length = span.Length; if (destination.Length >= length) { CopyTo(destination); return true; } return false; } public T[] ToArray() { int length = span.Length; if (length == 0) { return Array.Empty(); } T[] array = new T[length]; CopyTo(array); return array; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static implicit operator ReadOnlyRefEnumerable(RefEnumerable enumerable) { return new ReadOnlyRefEnumerable(enumerable.Span, enumerable.Step); } private static void ThrowArgumentOutOfRangeExceptionForLength() { throw new ArgumentOutOfRangeException("length"); } private static void ThrowArgumentOutOfRangeExceptionForStep() { throw new ArgumentOutOfRangeException("step"); } private static void ThrowArgumentExceptionForDestinationTooShort() { throw new ArgumentException("The target span is too short to copy all the current items to"); } } [EditorBrowsable(EditorBrowsableState.Never)] public ref struct ReadOnlySpanEnumerable { [EditorBrowsable(EditorBrowsableState.Never)] public readonly ref struct Item { private readonly ReadOnlySpan span; public ref readonly T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref MemoryMarshal.GetReference(span); } } public int Index { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Length; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Item(ref T value, int index) { span = MemoryMarshal.CreateReadOnlySpan(in value, index); } } private readonly ReadOnlySpan span; private int index; public readonly Item Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Item(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)index), index); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpanEnumerable(ReadOnlySpan span) { this.span = span; index = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly ReadOnlySpanEnumerable GetEnumerator() { return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { return ++index < span.Length; } } [EditorBrowsable(EditorBrowsableState.Never)] public ref struct ReadOnlySpanTokenizer where T : IEquatable { private readonly ReadOnlySpan span; private readonly T separator; private int start; private int end; public readonly ReadOnlySpan Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Slice(start, end - start); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpanTokenizer(ReadOnlySpan span, T separator) { this.span = span; this.separator = separator; start = 0; end = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly ReadOnlySpanTokenizer GetEnumerator() { return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int num = end + 1; int length = span.Length; if (num <= length) { start = num; int num2 = System.MemoryExtensions.IndexOf(span.Slice(num), separator); if (num2 >= 0) { end = num + num2; return true; } end = length; return true; } return false; } } public readonly ref struct RefEnumerable { public ref struct Enumerator { private readonly Span span; private readonly int step; private int position; public readonly ref T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { ref T source = ref span.DangerousGetReference(); nint elementOffset = (nint)(uint)position * (nint)(uint)step; return ref Unsafe.Add(ref source, elementOffset); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(Span span, int step) { this.span = span; this.step = step; position = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { return ++position < span.Length; } } internal readonly Span Span; internal readonly int Step; public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return Span.Length; } } public ref T this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { if ((uint)index >= (uint)Length) { ThrowHelper.ThrowIndexOutOfRangeException(); } ref T reference = ref MemoryMarshal.GetReference(Span); nint elementOffset = (nint)(uint)index * (nint)(uint)Step; return ref Unsafe.Add(ref reference, elementOffset); } } public ref T this[Index index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref this[index.GetOffset(Length)]; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal RefEnumerable(ref T reference, int length, int step) { Span = MemoryMarshal.CreateSpan(ref reference, length); Step = step; } public static RefEnumerable DangerousCreate(ref T value, int length, int step) { if (length < 0) { ThrowArgumentOutOfRangeExceptionForLength(); } if (step < 0) { ThrowArgumentOutOfRangeExceptionForStep(); } OverflowHelper.EnsureIsInNativeIntRange(length, 1, step); return new RefEnumerable(ref value, length, step); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Enumerator GetEnumerator() { return new Enumerator(Span, Step); } public void Clear() { if (Step == 1) { Span.Clear(); return; } ref T r = ref Span.DangerousGetReference(); int length = Span.Length; RefEnumerableHelper.Clear(ref r, (nint)(uint)length, (nint)(uint)Step); } public void CopyTo(RefEnumerable destination) { if (Step == 1) { destination.CopyFrom(Span); return; } if (destination.Step == 1) { CopyTo(destination.Span); return; } ref T sourceRef = ref Span.DangerousGetReference(); ref T destinationRef = ref destination.Span.DangerousGetReference(); int length = Span.Length; if ((uint)destination.Span.Length < (uint)length) { ThrowArgumentExceptionForDestinationTooShort(); } RefEnumerableHelper.CopyTo(ref sourceRef, ref destinationRef, (nint)(uint)length, (nint)(uint)Step, (nint)(uint)destination.Step); } public bool TryCopyTo(RefEnumerable destination) { int length = Span.Length; if (destination.Span.Length >= length) { CopyTo(destination); return true; } return false; } public void CopyTo(Span destination) { if (Step == 1) { Span.CopyTo(destination); return; } ref T sourceRef = ref Span.DangerousGetReference(); int length = Span.Length; if ((uint)destination.Length < (uint)length) { ThrowArgumentExceptionForDestinationTooShort(); } RefEnumerableHelper.CopyTo(ref sourceRef, ref destination.DangerousGetReference(), (nint)(uint)length, (nint)(uint)Step); } public bool TryCopyTo(Span destination) { int length = Span.Length; if (destination.Length >= length) { CopyTo(destination); return true; } return false; } internal void CopyFrom(ReadOnlySpan source) { if (Step == 1) { source.CopyTo(Span); return; } ref T destinationRef = ref Span.DangerousGetReference(); int length = Span.Length; ref T sourceRef = ref source.DangerousGetReference(); int length2 = source.Length; if ((uint)length < (uint)length2) { ThrowArgumentExceptionForDestinationTooShort(); } RefEnumerableHelper.CopyFrom(ref sourceRef, ref destinationRef, (nint)(uint)length2, (nint)(uint)Step); } public bool TryCopyFrom(ReadOnlySpan source) { if (Span.Length >= source.Length) { CopyFrom(source); return true; } return false; } public void Fill(T value) { if (Step == 1) { Span.Fill(value); return; } ref T r = ref Span.DangerousGetReference(); int length = Span.Length; RefEnumerableHelper.Fill(ref r, (nint)(uint)length, (nint)(uint)Step, value); } public T[] ToArray() { int length = Span.Length; if (length == 0) { return Array.Empty(); } T[] array = new T[length]; CopyTo(array); return array; } private static void ThrowArgumentOutOfRangeExceptionForLength() { throw new ArgumentOutOfRangeException("length"); } private static void ThrowArgumentOutOfRangeExceptionForStep() { throw new ArgumentOutOfRangeException("step"); } private static void ThrowArgumentExceptionForDestinationTooShort() { throw new ArgumentException("The target span is too short to copy all the current items to"); } } [EditorBrowsable(EditorBrowsableState.Never)] public ref struct SpanEnumerable { [EditorBrowsable(EditorBrowsableState.Never)] public readonly ref struct Item { private readonly Span span; public ref T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return ref MemoryMarshal.GetReference(span); } } public int Index { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Length; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public Item(ref T value, int index) { span = MemoryMarshal.CreateSpan(ref value, index); } } private readonly Span span; private int index; public readonly Item Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Item(ref Unsafe.Add(ref MemoryMarshal.GetReference(span), (nint)(uint)index), index); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanEnumerable(Span span) { this.span = span; index = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly SpanEnumerable GetEnumerator() { return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { return ++index < span.Length; } } [EditorBrowsable(EditorBrowsableState.Never)] public ref struct SpanTokenizer where T : IEquatable { private readonly Span span; private readonly T separator; private int start; private int end; public readonly Span Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return span.Slice(start, end - start); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanTokenizer(Span span, T separator) { this.span = span; this.separator = separator; start = 0; end = -1; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly SpanTokenizer GetEnumerator() { return this; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int num = end + 1; int length = span.Length; if (num <= length) { start = num; int num2 = span.Slice(num).IndexOf(separator); if (num2 >= 0) { end = num + num2; return true; } end = length; return true; } return false; } } } namespace Microsoft.Toolkit.HighPerformance.Buffers { [DebuggerTypeProxy(typeof(MemoryDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public sealed class ArrayPoolBufferWriter : IBuffer, IBufferWriter, IMemoryOwner, IDisposable { private const int DefaultInitialBufferSize = 256; private readonly ArrayPool pool; private T[]? array; private int index; Memory IMemoryOwner.Memory => MemoryMarshal.AsMemory(WrittenMemory); public ReadOnlyMemory WrittenMemory { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return obj.AsMemory(0, index); } } public ReadOnlySpan WrittenSpan { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return obj.AsSpan(0, index); } } public int WrittenCount { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return index; } } public int Capacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return obj.Length; } } public int FreeCapacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return obj.Length - index; } } public ArrayPoolBufferWriter() : this(ArrayPool.Shared, 256) { } public ArrayPoolBufferWriter(ArrayPool pool) : this(pool, 256) { } public ArrayPoolBufferWriter(int initialCapacity) : this(ArrayPool.Shared, initialCapacity) { } public ArrayPoolBufferWriter(ArrayPool pool, int initialCapacity) { this.pool = pool; array = pool.Rent(initialCapacity); index = 0; } ~ArrayPoolBufferWriter() { Dispose(); } public void Clear() { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } obj.AsSpan(0, index).Clear(); index = 0; } public void Advance(int count) { T[] array = this.array; if (array == null) { ThrowObjectDisposedException(); } if (count < 0) { ThrowArgumentOutOfRangeExceptionForNegativeCount(); } if (index > array.Length - count) { ThrowArgumentExceptionForAdvancedTooFar(); } index += count; } public Memory GetMemory(int sizeHint = 0) { CheckBufferAndEnsureCapacity(sizeHint); return array.AsMemory(index); } public Span GetSpan(int sizeHint = 0) { CheckBufferAndEnsureCapacity(sizeHint); return array.AsSpan(index); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void CheckBufferAndEnsureCapacity(int sizeHint) { T[] array = this.array; if (array == null) { ThrowObjectDisposedException(); } if (sizeHint < 0) { ThrowArgumentOutOfRangeExceptionForNegativeSizeHint(); } if (sizeHint == 0) { sizeHint = 1; } if (sizeHint > array.Length - index) { ResizeBuffer(sizeHint); } } [MethodImpl(MethodImplOptions.NoInlining)] private void ResizeBuffer(int sizeHint) { int num = index + sizeHint; if (num > 1048576) { num = Microsoft.Toolkit.HighPerformance.Helpers.Internals.BitOperations.RoundUpPowerOfTwo(num); } pool.Resize(ref array, num); } public void Dispose() { T[] array = this.array; if (array != null) { GC.SuppressFinalize(this); this.array = null; pool.Return(array); } } public override string ToString() { if (typeof(T) == typeof(char) && array is char[] value) { return new string(value, 0, index); } return $"Microsoft.Toolkit.HighPerformance.Buffers.ArrayPoolBufferWriter<{typeof(T)}>[{index}]"; } private static void ThrowArgumentOutOfRangeExceptionForNegativeCount() { throw new ArgumentOutOfRangeException("count", "The count can't be a negative value"); } private static void ThrowArgumentOutOfRangeExceptionForNegativeSizeHint() { throw new ArgumentOutOfRangeException("sizeHint", "The size hint can't be a negative value"); } private static void ThrowArgumentExceptionForAdvancedTooFar() { throw new ArgumentException("The buffer writer has advanced too far"); } private static void ThrowObjectDisposedException() { throw new ObjectDisposedException("The current buffer has already been disposed"); } } public enum AllocationMode { Default, Clear } public interface IBuffer : IBufferWriter { ReadOnlyMemory WrittenMemory { get; } ReadOnlySpan WrittenSpan { get; } int WrittenCount { get; } int Capacity { get; } int FreeCapacity { get; } void Clear(); } [DebuggerTypeProxy(typeof(MemoryDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public sealed class MemoryBufferWriter : IBuffer, IBufferWriter { private readonly Memory memory; private int index; public ReadOnlyMemory WrittenMemory { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return memory.Slice(0, index); } } public ReadOnlySpan WrittenSpan { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return memory.Slice(0, index).Span; } } public int WrittenCount { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return index; } } public int Capacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return memory.Length; } } public int FreeCapacity { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return memory.Length - index; } } public MemoryBufferWriter(Memory memory) { this.memory = memory; } public void Clear() { memory.Slice(0, index).Span.Clear(); index = 0; } public void Advance(int count) { if (count < 0) { ThrowArgumentOutOfRangeExceptionForNegativeCount(); } if (index > memory.Length - count) { ThrowArgumentExceptionForAdvancedTooFar(); } index += count; } public Memory GetMemory(int sizeHint = 0) { ValidateSizeHint(sizeHint); return memory.Slice(index); } public Span GetSpan(int sizeHint = 0) { ValidateSizeHint(sizeHint); return memory.Slice(index).Span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ValidateSizeHint(int sizeHint) { if (sizeHint < 0) { ThrowArgumentOutOfRangeExceptionForNegativeSizeHint(); } if (sizeHint == 0) { sizeHint = 1; } if (sizeHint > FreeCapacity) { ThrowArgumentExceptionForCapacityExceeded(); } } public override string ToString() { if (typeof(T) == typeof(char)) { return memory.Slice(0, index).ToString(); } return $"Microsoft.Toolkit.HighPerformance.Buffers.MemoryBufferWriter<{typeof(T)}>[{index}]"; } private static void ThrowArgumentOutOfRangeExceptionForNegativeCount() { throw new ArgumentOutOfRangeException("count", "The count can't be a negative value"); } private static void ThrowArgumentOutOfRangeExceptionForNegativeSizeHint() { throw new ArgumentOutOfRangeException("sizeHint", "The size hint can't be a negative value"); } private static void ThrowArgumentExceptionForAdvancedTooFar() { throw new ArgumentException("The buffer writer has advanced too far"); } private static void ThrowArgumentExceptionForCapacityExceeded() { throw new ArgumentException("The buffer writer doesn't have enough capacity left"); } } [DebuggerTypeProxy(typeof(MemoryDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public sealed class MemoryOwner : IMemoryOwner, IDisposable { private readonly int start; private readonly int length; private readonly ArrayPool pool; private T[]? array; public static MemoryOwner Empty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new MemoryOwner(0, ArrayPool.Shared, AllocationMode.Default); } } public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return length; } } public Memory Memory { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return new Memory(obj, start, length); } } public Span Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return new Span(obj, start, length); } } private MemoryOwner(int length, ArrayPool pool, AllocationMode mode) { start = 0; this.length = length; this.pool = pool; array = pool.Rent(length); if (mode == AllocationMode.Clear) { array.AsSpan(0, length).Clear(); } } private MemoryOwner(int start, int length, ArrayPool pool, T[] array) { this.start = start; this.length = length; this.pool = pool; this.array = array; } ~MemoryOwner() { Dispose(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MemoryOwner Allocate(int size) { return new MemoryOwner(size, ArrayPool.Shared, AllocationMode.Default); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MemoryOwner Allocate(int size, ArrayPool pool) { return new MemoryOwner(size, pool, AllocationMode.Default); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MemoryOwner Allocate(int size, AllocationMode mode) { return new MemoryOwner(size, ArrayPool.Shared, mode); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static MemoryOwner Allocate(int size, ArrayPool pool, AllocationMode mode) { return new MemoryOwner(size, pool, mode); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T DangerousGetReference() { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return ref obj.DangerousGetReferenceAt(start); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegment DangerousGetArray() { T[]? obj = array; if (obj == null) { ThrowObjectDisposedException(); } return new ArraySegment(obj, start, length); } public MemoryOwner Slice(int start, int length) { T[] array = this.array; if (array == null) { ThrowObjectDisposedException(); } this.array = null; if ((uint)start > this.length) { ThrowInvalidOffsetException(); } if ((uint)length > this.length - start) { ThrowInvalidLengthException(); } GC.SuppressFinalize(this); return new MemoryOwner(start, length, pool, array); } public void Dispose() { T[] array = this.array; if (array != null) { GC.SuppressFinalize(this); this.array = null; pool.Return(array); } } public override string ToString() { if (typeof(T) == typeof(char) && array is char[] value) { return new string(value, start, length); } return $"Microsoft.Toolkit.HighPerformance.Buffers.MemoryOwner<{typeof(T)}>[{length}]"; } private static void ThrowObjectDisposedException() { throw new ObjectDisposedException("MemoryOwner", "The current buffer has already been disposed"); } private static void ThrowInvalidOffsetException() { throw new ArgumentOutOfRangeException("start", "The input start parameter was not valid"); } private static void ThrowInvalidLengthException() { throw new ArgumentOutOfRangeException("length", "The input length parameter was not valid"); } } [DebuggerTypeProxy(typeof(MemoryDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly ref struct SpanOwner { private readonly int length; private readonly ArrayPool pool; private readonly T[] array; public static SpanOwner Empty { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new SpanOwner(0, ArrayPool.Shared, AllocationMode.Default); } } public int Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return length; } } public Span Span { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Span(array, 0, length); } } private SpanOwner(int length, ArrayPool pool, AllocationMode mode) { this.length = length; this.pool = pool; array = pool.Rent(length); if (mode == AllocationMode.Clear) { array.AsSpan(0, length).Clear(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanOwner Allocate(int size) { return new SpanOwner(size, ArrayPool.Shared, AllocationMode.Default); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanOwner Allocate(int size, ArrayPool pool) { return new SpanOwner(size, pool, AllocationMode.Default); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanOwner Allocate(int size, AllocationMode mode) { return new SpanOwner(size, ArrayPool.Shared, mode); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static SpanOwner Allocate(int size, ArrayPool pool, AllocationMode mode) { return new SpanOwner(size, pool, mode); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ref T DangerousGetReference() { return ref array.DangerousGetReference(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ArraySegment DangerousGetArray() { return new ArraySegment(array, 0, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Dispose() { pool.Return(array); } public override string ToString() { if (typeof(T) == typeof(char) && array is char[] value) { return new string(value, 0, length); } return $"Microsoft.Toolkit.HighPerformance.Buffers.SpanOwner<{typeof(T)}>[{length}]"; } } public sealed class StringPool { private struct FixedSizePriorityMap { private struct MapEntry { public int HashCode; public string? Value; public int NextIndex; public int HeapIndex; } private struct HeapEntry { public uint Timestamp; public int MapIndex; } private const int EndOfList = -1; private readonly int[] buckets; private readonly MapEntry[] mapEntries; private readonly HeapEntry[] heapEntries; private int count; private uint timestamp; public object SyncRoot { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return buckets; } } public FixedSizePriorityMap(int capacity) { buckets = new int[capacity]; mapEntries = new MapEntry[capacity]; heapEntries = new HeapEntry[capacity]; count = 0; timestamp = 0u; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Add(string value, int hashcode) { ref string reference = ref TryGet(value.AsSpan(), hashcode); if (Unsafe.IsNullRef(in reference)) { Insert(value, hashcode); } else { reference = value; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetOrAdd(string value, int hashcode) { ref string reference = ref TryGet(value.AsSpan(), hashcode); if (!Unsafe.IsNullRef(in reference)) { return reference; } Insert(value, hashcode); return value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public string GetOrAdd(ReadOnlySpan span, int hashcode) { ref string reference = ref TryGet(span, hashcode); if (!Unsafe.IsNullRef(in reference)) { return reference; } string text = span.ToString(); Insert(text, hashcode); return text; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGet(ReadOnlySpan span, int hashcode, [NotNullWhen(true)] out string? value) { ref string reference = ref TryGet(span, hashcode); if (!Unsafe.IsNullRef(in reference)) { value = reference; return true; } value = null; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Reset() { buckets.AsSpan().Clear(); mapEntries.AsSpan().Clear(); heapEntries.AsSpan().Clear(); count = 0; timestamp = 0u; } [MethodImpl(MethodImplOptions.NoInlining)] private ref string TryGet(ReadOnlySpan span, int hashcode) { ref MapEntry source = ref mapEntries.DangerousGetReference(); ref MapEntry reference = ref Unsafe.NullRef(); int num = buckets.Length; int i = hashcode & (num - 1); int num2 = buckets.DangerousGetReferenceAt(i) - 1; while ((uint)num2 < (uint)num) { reference = ref Unsafe.Add(ref source, (nint)(uint)num2); if (reference.HashCode == hashcode && reference.Value.AsSpan().SequenceEqual(span)) { UpdateTimestamp(ref reference.HeapIndex); return ref reference.Value; } num2 = reference.NextIndex; } return ref Unsafe.NullRef(); } [MethodImpl(MethodImplOptions.NoInlining)] private void Insert(string value, int hashcode) { ref int source = ref buckets.DangerousGetReference(); ref MapEntry source2 = ref mapEntries.DangerousGetReference(); ref HeapEntry reference = ref heapEntries.DangerousGetReference(); int mapIndex; int num; if (count == mapEntries.Length) { mapIndex = reference.MapIndex; num = 0; Remove(Unsafe.Add(ref source2, (nint)(uint)mapIndex).HashCode, mapIndex); } else { mapIndex = count; num = count; } int num2 = hashcode & (buckets.Length - 1); ref int reference2 = ref Unsafe.Add(ref source, (nint)(uint)num2); ref MapEntry reference3 = ref Unsafe.Add(ref source2, (nint)(uint)mapIndex); ref HeapEntry reference4 = ref Unsafe.Add(ref reference, (nint)(uint)num); reference3.HashCode = hashcode; reference3.Value = value; reference3.NextIndex = reference2 - 1; reference3.HeapIndex = num; reference2 = mapIndex + 1; count++; reference4.MapIndex = mapIndex; UpdateTimestamp(ref reference3.HeapIndex); } [MethodImpl(MethodImplOptions.NoInlining)] private void Remove(int hashcode, int mapIndex) { ref MapEntry source = ref mapEntries.DangerousGetReference(); int i = hashcode & (buckets.Length - 1); int num = buckets.DangerousGetReferenceAt(i) - 1; int num2 = -1; ref MapEntry reference; while (true) { reference = ref Unsafe.Add(ref source, (nint)(uint)num); if (num == mapIndex) { break; } num2 = num; num = reference.NextIndex; } if (num2 != -1) { Unsafe.Add(ref source, (nint)(uint)num2).NextIndex = reference.NextIndex; } else { buckets.DangerousGetReferenceAt(i) = reference.NextIndex + 1; } count--; } [MethodImpl(MethodImplOptions.NoInlining)] private void UpdateTimestamp(ref int heapIndex) { int num = heapIndex; int num2 = count; ref MapEntry source = ref mapEntries.DangerousGetReference(); ref HeapEntry source2 = ref heapEntries.DangerousGetReference(); ref HeapEntry reference = ref Unsafe.Add(ref source2, (nint)(uint)num); uint num3 = timestamp; if (num3 == uint.MaxValue) { UpdateAllTimestamps(); num3 = (uint)(num2 - 1); } reference.Timestamp = (timestamp = num3 + 1); int num6; while (true) { ref HeapEntry reference2 = ref reference; int num4 = num * 2 + 1; int num5 = num * 2 + 2; num6 = num; if (num4 < num2) { ref HeapEntry reference3 = ref Unsafe.Add(ref source2, (nint)(uint)num4); if (reference3.Timestamp < reference2.Timestamp) { reference2 = ref reference3; num6 = num4; } } if (num5 < num2) { ref HeapEntry reference4 = ref Unsafe.Add(ref source2, (nint)(uint)num5); if (reference4.Timestamp < reference2.Timestamp) { reference2 = ref reference4; num6 = num5; } } if (Unsafe.AreSame(in reference, in reference2)) { break; } Unsafe.Add(ref source, (nint)(uint)reference.MapIndex).HeapIndex = num6; Unsafe.Add(ref source, (nint)(uint)reference2.MapIndex).HeapIndex = num; num = num6; HeapEntry heapEntry = reference; reference = reference2; reference2 = heapEntry; reference = ref Unsafe.Add(ref source2, (nint)(uint)num); } heapIndex = num6; } [MethodImpl(MethodImplOptions.NoInlining)] private void UpdateAllTimestamps() { int num = count; ref HeapEntry source = ref heapEntries.DangerousGetReference(); for (int i = 0; i < num; i++) { Unsafe.Add(ref source, (nint)(uint)i).Timestamp = (uint)i; } } } private const int DefaultSize = 2048; private const int MinimumSize = 32; private readonly FixedSizePriorityMap[] maps; private readonly int numberOfMaps; public static StringPool Shared { get; } = new StringPool(); public int Size { get; } public StringPool() : this(2048) { } public StringPool(int minimumSize) { if (minimumSize <= 0) { ThrowArgumentOutOfRangeException(); } minimumSize = Math.Max(minimumSize, 32); FindFactors(minimumSize, 2, out var x, out var y); FindFactors(minimumSize, 3, out var x2, out var y2); FindFactors(minimumSize, 4, out var x3, out var y3); int num = x * y; int num2 = x2 * y2; int num3 = x3 * y3; if (num2 < num) { num = num2; x = x2; y = y2; } if (num3 < num) { num = num3; x = x3; y = y3; } Span span = (maps = new FixedSizePriorityMap[x]); for (int i = 0; i < span.Length; i++) { span[i] = new FixedSizePriorityMap(y); } numberOfMaps = x; Size = num; static void FindFactors(int size, int factor, out int reference, out int reference2) { double num4 = Math.Sqrt((double)size / (double)factor); double num5 = (double)factor * num4; reference = Microsoft.Toolkit.HighPerformance.Helpers.Internals.BitOperations.RoundUpPowerOfTwo((int)num4); reference2 = Microsoft.Toolkit.HighPerformance.Helpers.Internals.BitOperations.RoundUpPowerOfTwo((int)num5); } } public void Add(string value) { if (value.Length == 0) { return; } int hashCode = GetHashCode(value.AsSpan()); int i = hashCode & (numberOfMaps - 1); ref FixedSizePriorityMap reference = ref maps.DangerousGetReferenceAt(i); lock (reference.SyncRoot) { reference.Add(value, hashCode); } } public string GetOrAdd(string value) { if (value.Length == 0) { return string.Empty; } int hashCode = GetHashCode(value.AsSpan()); int i = hashCode & (numberOfMaps - 1); ref FixedSizePriorityMap reference = ref maps.DangerousGetReferenceAt(i); lock (reference.SyncRoot) { return reference.GetOrAdd(value, hashCode); } } public string GetOrAdd(ReadOnlySpan span) { if (span.IsEmpty) { return string.Empty; } int hashCode = GetHashCode(span); int i = hashCode & (numberOfMaps - 1); ref FixedSizePriorityMap reference = ref maps.DangerousGetReferenceAt(i); lock (reference.SyncRoot) { return reference.GetOrAdd(span, hashCode); } } public unsafe string GetOrAdd(ReadOnlySpan span, Encoding encoding) { if (span.IsEmpty) { return string.Empty; } int maxCharCount = encoding.GetMaxCharCount(span.Length); SpanOwner spanOwner = SpanOwner.Allocate(maxCharCount); try { fixed (byte* bytes = span) { fixed (char* ptr = &spanOwner.DangerousGetReference()) { int chars = encoding.GetChars(bytes, span.Length, ptr, maxCharCount); return GetOrAdd(new ReadOnlySpan(ptr, chars)); } } } finally { spanOwner.Dispose(); } } public bool TryGet(ReadOnlySpan span, [NotNullWhen(true)] out string? value) { if (span.IsEmpty) { value = string.Empty; return true; } int hashCode = GetHashCode(span); int i = hashCode & (numberOfMaps - 1); ref FixedSizePriorityMap reference = ref maps.DangerousGetReferenceAt(i); lock (reference.SyncRoot) { return reference.TryGet(span, hashCode, out value); } } public void Reset() { Span span = maps.AsSpan(); for (int i = 0; i < span.Length; i++) { ref FixedSizePriorityMap reference = ref span[i]; lock (reference.SyncRoot) { reference.Reset(); } } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static int GetHashCode(ReadOnlySpan span) { return HashCode.Combine(span); } private static void ThrowArgumentOutOfRangeException() { throw new ArgumentOutOfRangeException("minimumSize", "The requested size must be greater than 0"); } } } namespace Microsoft.Toolkit.HighPerformance.Buffers.Views { internal sealed class MemoryDebugView { [DebuggerBrowsable(DebuggerBrowsableState.Collapsed)] public T[]? Items { get; } public MemoryDebugView(ArrayPoolBufferWriter? arrayPoolBufferWriter) { Items = arrayPoolBufferWriter?.WrittenSpan.ToArray(); } public MemoryDebugView(MemoryBufferWriter? memoryBufferWriter) { Items = memoryBufferWriter?.WrittenSpan.ToArray(); } public MemoryDebugView(MemoryOwner? memoryOwner) { Items = memoryOwner?.Span.ToArray(); } public MemoryDebugView(SpanOwner spanOwner) { Items = spanOwner.Span.ToArray(); } } } namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals { internal sealed class ArrayMemoryManager : MemoryManager, IMemoryManager where TFrom : unmanaged where TTo : unmanaged { private readonly TFrom[] array; private readonly int offset; private readonly int length; public ArrayMemoryManager(TFrom[] array, int offset, int length) { this.array = array; this.offset = offset; this.length = length; } public override Span GetSpan() { ref TTo reference = ref Unsafe.As(ref array.DangerousGetReferenceAt(offset)); int num = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(length); return MemoryMarshal.CreateSpan(ref reference, num); } public unsafe override MemoryHandle Pin(int elementIndex = 0) { if ((uint)elementIndex >= (uint)(length * Unsafe.SizeOf() / Unsafe.SizeOf())) { ThrowArgumentOutOfRangeExceptionForInvalidIndex(); } int num = offset * Unsafe.SizeOf(); int num2 = elementIndex * Unsafe.SizeOf(); int elementOffset = num + num2; GCHandle handle = GCHandle.Alloc(array, GCHandleType.Pinned); return new MemoryHandle(Unsafe.AsPointer(ref Unsafe.Add(ref Unsafe.As(ref array.DangerousGetReference()), elementOffset)), handle); } public override void Unpin() { } protected override void Dispose(bool disposing) { } public Memory GetMemory(int offset, int length) where T : unmanaged { int start = this.offset + Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(offset); int num = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(length); if (typeof(T) == typeof(TFrom)) { return (Memory)(object)array.AsMemory(start, num); } return new ArrayMemoryManager(array, start, num).Memory; } private static void ThrowArgumentOutOfRangeExceptionForInvalidIndex() { throw new ArgumentOutOfRangeException("elementIndex", "The input index is not in the valid range"); } } internal sealed class ProxyMemoryManager : MemoryManager, IMemoryManager where TFrom : unmanaged where TTo : unmanaged { private readonly MemoryManager memoryManager; private readonly int offset; private readonly int length; public ProxyMemoryManager(MemoryManager memoryManager, int offset, int length) { this.memoryManager = memoryManager; this.offset = offset; this.length = length; } public override Span GetSpan() { return MemoryMarshal.Cast(memoryManager.GetSpan().Slice(offset, length)); } public override MemoryHandle Pin(int elementIndex = 0) { if ((uint)elementIndex >= (uint)(length * Unsafe.SizeOf() / Unsafe.SizeOf())) { ThrowArgumentExceptionForInvalidIndex(); } int num = offset * Unsafe.SizeOf(); int num2 = elementIndex * Unsafe.SizeOf(); int result; int elementIndex2 = Math.DivRem(num + num2, Unsafe.SizeOf(), out result); if (result != 0) { ThrowArgumentExceptionForInvalidAlignment(); } return memoryManager.Pin(elementIndex2); } public override void Unpin() { memoryManager.Unpin(); } protected override void Dispose(bool disposing) { ((IDisposable)memoryManager).Dispose(); } public Memory GetMemory(int offset, int length) where T : unmanaged { int start = this.offset + Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(offset); int num = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(length); if (typeof(T) == typeof(TFrom)) { return (Memory)(object)memoryManager.Memory.Slice(start, num); } return new ProxyMemoryManager(memoryManager, start, num).Memory; } private static void ThrowArgumentExceptionForInvalidIndex() { throw new ArgumentOutOfRangeException("elementIndex", "The input index is not in the valid range"); } private static void ThrowArgumentExceptionForInvalidAlignment() { throw new ArgumentOutOfRangeException("elementIndex", "The input index doesn't result in an aligned item access"); } } internal sealed class RawObjectMemoryManager : MemoryManager { private readonly object instance; private readonly IntPtr offset; private readonly int length; public RawObjectMemoryManager(object instance, IntPtr offset, int length) { this.instance = instance; this.offset = offset; this.length = length; } public override Span GetSpan() { return MemoryMarshal.CreateSpan(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(instance, offset), length); } public unsafe override MemoryHandle Pin(int elementIndex = 0) { if ((uint)elementIndex >= (uint)length) { ThrowArgumentOutOfRangeExceptionForInvalidElementIndex(); } GCHandle handle = GCHandle.Alloc(instance, GCHandleType.Pinned); return new MemoryHandle(Unsafe.AsPointer(ref Unsafe.Add(ref ObjectMarshal.DangerousGetObjectDataReferenceAt(instance, offset), (nint)(uint)elementIndex)), handle); } public override void Unpin() { } protected override void Dispose(bool disposing) { } private static void ThrowArgumentOutOfRangeExceptionForInvalidElementIndex() { throw new ArgumentOutOfRangeException("elementIndex", "The input element index was not in the valid range"); } } internal sealed class StringMemoryManager : MemoryManager, IMemoryManager where TTo : unmanaged { private readonly string text; private readonly int offset; private readonly int length; public StringMemoryManager(string text, int offset, int length) { this.text = text; this.offset = offset; this.length = length; } public override Span GetSpan() { ref TTo reference = ref Unsafe.As(ref text.DangerousGetReferenceAt(offset)); int num = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(length); return MemoryMarshal.CreateSpan(ref reference, num); } public unsafe override MemoryHandle Pin(int elementIndex = 0) { if ((uint)elementIndex >= (uint)(length * Unsafe.SizeOf() / Unsafe.SizeOf())) { ThrowArgumentOutOfRangeExceptionForInvalidIndex(); } int num = offset * Unsafe.SizeOf(); int num2 = elementIndex * Unsafe.SizeOf(); int elementOffset = num + num2; GCHandle handle = GCHandle.Alloc(text, GCHandleType.Pinned); return new MemoryHandle(Unsafe.AsPointer(ref Unsafe.Add(ref Unsafe.As(ref text.DangerousGetReference()), elementOffset)), handle); } public override void Unpin() { } protected override void Dispose(bool disposing) { } public Memory GetMemory(int offset, int length) where T : unmanaged { int start = this.offset + Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(offset); int num = Microsoft.Toolkit.HighPerformance.Helpers.Internals.RuntimeHelpers.ConvertLength(length); if (typeof(T) == typeof(char)) { return (Memory)(object)MemoryMarshal.AsMemory(text.AsMemory(start, num)); } return new StringMemoryManager(text, start, num).Memory; } private static void ThrowArgumentOutOfRangeExceptionForInvalidIndex() { throw new ArgumentOutOfRangeException("elementIndex", "The input index is not in the valid range"); } } } namespace Microsoft.Toolkit.HighPerformance.Buffers.Internals.Interfaces { internal interface IMemoryManager { Memory GetMemory(int offset, int length) where T : unmanaged; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Module | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event | AttributeTargets.Interface, Inherited = false)] internal sealed class SkipLocalsInitAttribute : Attribute { } }