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