BuffersExtensions
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace System.Buffers
{
public static class BuffersExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SequencePosition? PositionOf<T>([In] [System.Runtime.CompilerServices.IsReadOnly] ref 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((long)num);
return null;
}
return PositionOfMultiSegment(ref source, value);
}
private static SequencePosition? PositionOfMultiSegment<T>([In] [System.Runtime.CompilerServices.IsReadOnly] ref 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, true)) {
int num = memory.Span.IndexOf(value);
if (num != -1)
return source.GetPosition((long)num, origin);
if (position.GetObject() == null)
break;
origin = position;
}
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo<T>([In] [System.Runtime.CompilerServices.IsReadOnly] ref 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(ref source, destination);
}
private static void CopyToMultiSegment<T>([In] [System.Runtime.CompilerServices.IsReadOnly] ref ReadOnlySequence<T> sequence, Span<T> destination)
{
SequencePosition position = sequence.Start;
ReadOnlyMemory<T> memory;
while (sequence.TryGet(ref position, out memory, true)) {
ReadOnlySpan<T> span = memory.Span;
span.CopyTo(destination);
if (position.GetObject() == null)
break;
destination = destination.Slice(span.Length);
}
}
public static T[] ToArray<T>([In] [System.Runtime.CompilerServices.IsReadOnly] ref ReadOnlySequence<T> sequence)
{
T[] array = new T[sequence.Length];
ref 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(0);
if (value.Length <= span.Length) {
value.CopyTo(span);
writer.Advance(value.Length);
} else
WriteMultiSegment(writer, ref value, span);
}
private static void WriteMultiSegment<T>(IBufferWriter<T> writer, [In] [System.Runtime.CompilerServices.IsReadOnly] ref 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)
break;
destination = writer.GetSpan(readOnlySpan.Length);
}
}
}
}