Files
2026-08-27 10:56:38 -06:00

117 lines
2.8 KiB
C#

using System.Runtime.CompilerServices;
namespace System.Buffers;
public static class BuffersExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SequencePosition? PositionOf<T>(this in ReadOnlySequence<T> source, T value) where T : IEquatable<T>
{
if (source.IsSingleSegment)
{
int num = source.First.Span.IndexOf(value);
if (num != -1)
{
return source.GetPosition(num);
}
return null;
}
return PositionOfMultiSegment(in source, value);
}
private static SequencePosition? PositionOfMultiSegment<T>(in ReadOnlySequence<T> source, T value) where T : IEquatable<T>
{
SequencePosition position = source.Start;
SequencePosition origin = position;
ReadOnlyMemory<T> memory;
while (source.TryGet(ref position, out memory))
{
int num = memory.Span.IndexOf(value);
if (num != -1)
{
return source.GetPosition(num, origin);
}
if (position.GetObject() == null)
{
break;
}
origin = position;
}
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo<T>(this in ReadOnlySequence<T> source, Span<T> destination)
{
if (source.Length > destination.Length)
{
System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.destination);
}
if (source.IsSingleSegment)
{
source.First.Span.CopyTo(destination);
}
else
{
CopyToMultiSegment(in source, destination);
}
}
private static void CopyToMultiSegment<T>(in ReadOnlySequence<T> sequence, Span<T> destination)
{
SequencePosition position = sequence.Start;
ReadOnlyMemory<T> memory;
while (sequence.TryGet(ref position, out memory))
{
ReadOnlySpan<T> span = memory.Span;
span.CopyTo(destination);
if (position.GetObject() != null)
{
destination = destination.Slice(span.Length);
continue;
}
break;
}
}
public static T[] ToArray<T>(this in ReadOnlySequence<T> sequence)
{
T[] array = new T[sequence.Length];
sequence.CopyTo(array);
return array;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write<T>(this IBufferWriter<T> writer, ReadOnlySpan<T> value)
{
Span<T> span = writer.GetSpan();
if (value.Length <= span.Length)
{
value.CopyTo(span);
writer.Advance(value.Length);
}
else
{
WriteMultiSegment(writer, in value, span);
}
}
private static void WriteMultiSegment<T>(IBufferWriter<T> writer, in ReadOnlySpan<T> source, Span<T> destination)
{
ReadOnlySpan<T> readOnlySpan = source;
while (true)
{
int num = Math.Min(destination.Length, readOnlySpan.Length);
readOnlySpan.Slice(0, num).CopyTo(destination);
writer.Advance(num);
readOnlySpan = readOnlySpan.Slice(num);
if (readOnlySpan.Length > 0)
{
destination = writer.GetSpan(readOnlySpan.Length);
continue;
}
break;
}
}
}