DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="5.1.0" />

.NET API 495,000 bytes

 SpanReader<T>

public struct SpanReader<T>
Represents simple memory reader backed by ReadOnlySpan<T>.
using System; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace DotNext.Buffers { [StructLayout(LayoutKind.Auto)] [NullableContext(1)] [Nullable(0)] [CompilerFeatureRequired("RefStructs")] public ref struct SpanReader<[Nullable(2)] T> { private readonly ref T reference; private readonly int length; private int position; [IsReadOnly] public unsafe ref T Current { [IsReadOnly] [return: IsReadOnly] get { if ((uint)position >= (uint)length) <get_Current>g__ThrowInvalidOperationException|6_0(); return ref Unsafe.Add<T>(*(ref T*)(&reference), position); } } public int ConsumedCount { [IsReadOnly] get { return position; } set { ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)value, (uint)length, "value"); position = value; } } public int RemainingCount { [IsReadOnly] get { return length - position; } } [Nullable(new byte[] { 0, 1 })] public unsafe ReadOnlySpan<T> Span { [IsReadOnly] [return: Nullable(new byte[] { 0, 1 })] get { return MemoryMarshal.CreateReadOnlySpan<T>(*(ref T*)(&reference), length); } } [Nullable(new byte[] { 0, 1 })] public unsafe ReadOnlySpan<T> ConsumedSpan { [IsReadOnly] [return: Nullable(new byte[] { 0, 1 })] get { return MemoryMarshal.CreateReadOnlySpan<T>(*(ref T*)(&reference), position); } } [Nullable(new byte[] { 0, 1 })] public unsafe ReadOnlySpan<T> RemainingSpan { [IsReadOnly] [return: Nullable(new byte[] { 0, 1 })] get { return MemoryMarshal.CreateReadOnlySpan<T>(ref Unsafe.Add<T>(*(ref T*)(&reference), position), RemainingCount); } } public unsafe SpanReader([Nullable(new byte[] { 0, 1 })] ReadOnlySpan<T> span) { position = 0; *(ref T*)(&reference) = ref MemoryMarshal.GetReference<T>(span); length = span.Length; } public unsafe SpanReader(ref T reference, int length) { position = 0; if (length < 0) throw new ArgumentOutOfRangeException("length"); if (length > 0 && Unsafe.IsNullRef<T>(ref reference)) throw new ArgumentNullException("reference"); *(ref T*)(&this.reference) = ref reference; this.length = length; } public void Advance(int count) { ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)count, (uint)RemainingCount, "count"); position += count; } public void Rewind(int count) { ArgumentOutOfRangeException.ThrowIfGreaterThan<uint>((uint)count, (uint)position, "count"); position -= count; } public void Reset() { position = 0; } public bool TryRead([ScopedRef] [Nullable(new byte[] { 0, 1 })] Span<T> output) { if (TryRead(output.Length, out ReadOnlySpan<T> result)) return result.TryCopyTo(output); return false; } public unsafe bool TryRead(int count, [Nullable(new byte[] { 0, 1 })] out ReadOnlySpan<T> result) { ArgumentOutOfRangeException.ThrowIfNegative<int>(count, "count"); int num = position + count; if ((uint)num <= (uint)length) { result = MemoryMarshal.CreateReadOnlySpan<T>(ref Unsafe.Add<T>(*(ref T*)(&reference), position), count); position = num; return true; } result = default(ReadOnlySpan<T>); return false; } public unsafe bool TryRead([MaybeNullWhen(false)] out T result) { if ((uint)position < (uint)length) { result = Unsafe.Add<T>(*(ref T*)(&reference), position++); return true; } result = default(T); return false; } public int Read([ScopedRef] [Nullable(new byte[] { 0, 1 })] Span<T> output) { DotNext.Span.CopyTo<T>(RemainingSpan, output, out int writtenCount); position += writtenCount; return writtenCount; } [return: IsReadOnly] public unsafe ref T Read() { if ((uint)position >= (uint)length) ThrowInternalBufferOverflowException(); return ref Unsafe.Add<T>(*(ref T*)(&reference), position++); } [return: Nullable(new byte[] { 0, 1 })] public ReadOnlySpan<T> Read(int count) { if (!TryRead(count, out ReadOnlySpan<T> result)) ThrowInternalBufferOverflowException(); return result; } [DoesNotReturn] [StackTraceHidden] private static void ThrowInternalBufferOverflowException() { throw new InternalBufferOverflowException(); } [CLSCompliant(false)] public unsafe TResult Read<[Nullable(2)] TResult>([Nullable(new byte[] { 0, 1, 0, 1 })] IntPtr reader, int count) { ArgumentNullException.ThrowIfNull((void*)(long)reader, "reader"); if (!this.TryRead(count, out ReadOnlySpan<T> result)) SpanReader<T>.ThrowInternalBufferOverflowException(); return (TResult); } [CLSCompliant(false)] public unsafe bool TryRead<[Nullable(2)] TResult>([Nullable(new byte[] { 0, 1, 0, 1 })] IntPtr reader, int count, [MaybeNullWhen(false)] out TResult result) { ArgumentNullException.ThrowIfNull((void*)(long)reader, "reader"); if (this.TryRead(count, out ReadOnlySpan<T> result2)) { result = (TResult); return true; } result = default(TResult); return false; } [return: Nullable(new byte[] { 0, 1 })] public ReadOnlySpan<T> ReadToEnd() { ReadOnlySpan<T> remainingSpan = RemainingSpan; position = length; return remainingSpan; } [IsReadOnly] public override string ToString() { return ConsumedSpan.ToString(); } } }