using Misaki.HighPerformance.Unsafe.Collections.Contracts; namespace Misaki.HighPerformance.Unsafe.Helpers; /// /// Provides extension methods for copying elements between unsafe collections and spans, converting collections to /// arrays or lists, and searching for values. /// public unsafe static class UnsafeCollectionExtensions { /// /// Copies elements from a source UnsafeCollection to a destination Span, ensuring both have the same size. /// /// Specifies the type of elements being copied, which must be unmanaged. /// Represents the source collection from which elements are copied. /// Represents the target span where elements are copied to. /// Thrown when the sizes of the source collection and destination span do not match. public static void CopyTo(this IUnsafeCollection source, Span destination) where T : unmanaged { if (source.Count > destination.Length) { throw new ArgumentException("Source collection is larger than the destination span."); } fixed (T* ptr = destination) { SystemUnsfae.CopyBlock(ptr, source.GetUnsafePtr(), (uint)(source.Count * sizeof(T))); } } /// /// Copies a range of elements from a source collection to a destination span, ensuring both are adequately sized. /// /// Specifies the type of elements being copied, which must be a value type. /// The collection from which elements are copied. /// The span where the elements will be copied to. /// The starting index in the source collection for the copy operation. /// The starting index in the destination span where the elements will be placed. /// The number of elements to copy from the source to the destination. /// Thrown when the specified range exceeds the bounds of the source collection or destination span. public static void CopyTo(this IUnsafeCollection source, Span destination, int sourceIndex, int destinationIndex, int length) where T : unmanaged { if (sourceIndex + length > source.Count || destinationIndex + length > destination.Length) { throw new ArgumentException("Source collection or destination span is too small for the specified range."); } fixed (T* ptr = destination) { SystemUnsfae.CopyBlock(ptr + destinationIndex, (byte*)source.GetUnsafePtr() + (sourceIndex * sizeof(T)), (uint)(length * sizeof(T))); } } /// /// Copies elements from a source span to a destination unsafe collection, ensuring both have the same size. /// /// Specifies the type of elements being copied, which must be unmanaged. /// Represents the unsafe collection that will receive the copied elements. /// Represents the span containing the elements to be copied to the unsafe collection. /// Thrown when the source span and destination collection have different sizes. public static void CopyFrom(this IUnsafeCollection destination, Span source) where T : unmanaged { if (destination.Count > source.Length) { throw new ArgumentException("Destination collection is larger than the source span."); } fixed (T* ptr = source) { SystemUnsfae.CopyBlock(destination.GetUnsafePtr(), ptr, (uint)(source.Length * sizeof(T))); } } /// /// Copies a specified range of elements from a source span to a destination collection. /// /// Represents the type of elements being copied, which must be unmanaged. /// The collection where elements will be copied to. /// The span containing the elements to be copied. /// The starting index in the source span from which to begin copying. /// The starting index in the destination collection where the elements will be placed. /// The number of elements to copy from the source span to the destination collection. /// Thrown when the specified range exceeds the bounds of the source span or destination collection. public static void CopyFrom(this IUnsafeCollection destination, Span source, int sourceIndex, int destinationIndex, int length) where T : unmanaged { if (sourceIndex + length > source.Length || destinationIndex + length > destination.Count) { throw new ArgumentException("Source span or destination collection is too small for the specified range."); } fixed (T* ptr = source) { SystemUnsfae.CopyBlock((byte*)destination.GetUnsafePtr() + (destinationIndex * sizeof(T)), ptr + sourceIndex, (uint)(length * sizeof(T))); } } /// /// Converts an UnsafeCollection of unmanaged types into a standard collection. /// /// Represents a type that is unmanaged, allowing for direct memory manipulation. /// The UnsafeCollection instance that contains the data to be converted. /// A new collection containing the elements from the UnsafeCollection. public static T[] ToArray(this IUnsafeCollection source) where T : unmanaged { var array = new T[source.Count]; fixed (T* ptr = array) { SystemUnsfae.CopyBlock(ptr, source.GetUnsafePtr(), (uint)(source.Count * sizeof(T))); } return array; } /// /// Converts an unmanaged collection into a list by copying its elements into a new list. /// /// Represents a type that is unmanaged, allowing for direct memory manipulation. /// The collection from which elements are copied to create the new list. /// A list containing the elements from the specified unmanaged collection. public static List ToList(this IUnsafeCollection source) where T : unmanaged { var list = new List(source.Count); fixed (T* ptr = list.ToArray()) { SystemUnsfae.CopyBlock(ptr, source.GetUnsafePtr(), (uint)(source.Count * sizeof(T))); } return list; } /// /// Converts an UnsafeCollection into a Span for efficient memory access. /// /// Represents a type that can be stored in unmanaged memory. /// The UnsafeCollection instance to be converted into a Span. /// A Span that provides a view over the elements of the UnsafeCollection. public static Span AsSpan(this IUnsafeCollection source) where T : unmanaged { return new(source.GetUnsafePtr(), source.Count); } /// /// Finds the index of a specified value in a collection. Returns -1 if the value is not found. /// /// The type of elements in the collection, which must support equality comparison. /// The collection to search for the specified value. /// The value to locate within the collection. /// Outputs the index of the found value or -1 if not found. public static void IndexOf(this IUnsafeCollection source, T value, out int index) where T : unmanaged, IEquatable { for (var i = 0; i < source.Count; i++) { if (UnsafeUtilities.ReadArrayElement(source.GetUnsafePtr(), i).Equals(value)) { index = i; return; } } index = -1; } /// /// Checks if a specified value exists within an unsafe collection of unmanaged types. /// /// Represents a type that is unmanaged and supports equality comparison. /// The collection being searched for the specified value. /// The value being searched for within the collection. /// Returns true if the value is found; otherwise, returns false. public static bool Conations(this IUnsafeCollection source, T value) where T : unmanaged, IEquatable { source.IndexOf(value, out var index); return index != -1; } }