<PackageReference Include="System.Drawing.Common" Version="10.0.0-preview.1.25080.3" />

SpanReader<T>

Fast stack based ReadOnlySpan<T> reader.
using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace System { [CompilerFeatureRequired("RefStructs")] internal ref struct SpanReader<[IsUnmanaged] T> where T : struct, IEquatable<T> { private ReadOnlySpan<T> _unread; public ReadOnlySpan<T> Span { [IsReadOnly] get; } public int Position { [IsReadOnly] get { return Span.Length - _unread.Length; } set { ReadOnlySpan<T> span = Span; _unread = span.Slice(value, span.Length - value); } } public SpanReader(ReadOnlySpan<T> span) { _unread = span; Span = span; } public bool TryReadTo(T delimiter, out ReadOnlySpan<T> span) { return TryReadTo(delimiter, true, out span); } public bool TryReadTo(T delimiter, bool advancePastDelimiter, out ReadOnlySpan<T> span) { bool result = false; int num = MemoryExtensions.IndexOf<T>(_unread, delimiter); span = default(ReadOnlySpan<T>); if (num != -1) { result = true; if (num > 0) { span = _unread; UncheckedSliceTo(ref span, num); if (advancePastDelimiter) num++; UnsafeAdvance(num); } } return result; } public bool TryRead(out T value) { bool result; if (_unread.IsEmpty) { value = default(T); result = false; } else { result = true; value = _unread[0]; UnsafeAdvance(1); } return result; } public bool TryRead(int count, out ReadOnlySpan<T> span) { bool result; if (count > _unread.Length) { span = default(ReadOnlySpan<T>); result = false; } else { result = true; span = _unread.Slice(0, count); UnsafeAdvance(count); } return result; } public unsafe bool TryRead<[IsUnmanaged] TValue>(out TValue value) where TValue : struct { if (sizeof(TValue) < sizeof(T) || sizeof(TValue) % sizeof(T) != 0) throw new ArgumentException("The size of TValue must be evenly divisible by the size of T."); bool result; if (sizeof(TValue) > this._unread.Length * sizeof(T)) { value = default(TValue); result = false; } else { result = true; value = Unsafe.ReadUnaligned<TValue>(ref Unsafe.As<T, byte>(ref MemoryMarshal.GetReference<T>(this._unread))); this.UnsafeAdvance(sizeof(TValue) / sizeof(T)); } return result; } public unsafe bool TryRead<[IsUnmanaged] TValue>(int count, out ReadOnlySpan<TValue> value) where TValue : struct { if (sizeof(TValue) < sizeof(T) || sizeof(TValue) % sizeof(T) != 0) throw new ArgumentException("The size of TValue must be evenly divisible by the size of T."); bool result; if (sizeof(TValue) * count > this._unread.Length * sizeof(T)) { value = default(ReadOnlySpan<TValue>); result = false; } else { result = true; value = MemoryMarshal.CreateReadOnlySpan<TValue>(ref Unsafe.As<T, TValue>(ref MemoryMarshal.GetReference<T>(this._unread)), count); this.UnsafeAdvance(sizeof(TValue) / sizeof(T) * count); } return result; } [IsReadOnly] public bool IsNext([ParamCollection] [ScopedRef] ReadOnlySpan<T> next) { return MemoryExtensions.StartsWith<T>(_unread, next); } public bool TryAdvancePast([ParamCollection] [ScopedRef] ReadOnlySpan<T> next) { bool result = false; if (MemoryExtensions.StartsWith<T>(_unread, next)) { UnsafeAdvance(next.Length); result = true; } return result; } public int AdvancePast(T value) { int result = 0; int num = MemoryExtensions.IndexOfAnyExcept<T>(_unread, value); switch (num) { case -1: result = _unread.Length; _unread = default(ReadOnlySpan<T>); break; default: result = num; UnsafeAdvance(num); break; case 0: break; } return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Advance(int count) { ref ReadOnlySpan<T> unread = ref _unread; _unread = unread.Slice(count, unread.Length - count); } public void Rewind(int count) { ReadOnlySpan<T> span = Span; int num = Span.Length - _unread.Length - count; _unread = span.Slice(num, span.Length - num); } public void Reset() { _unread = Span; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private void UnsafeAdvance(int count) { UncheckedSlice(ref _unread, count, _unread.Length - count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void UncheckedSliceTo(ref ReadOnlySpan<T> span, int length) { span = MemoryMarshal.CreateReadOnlySpan<T>(ref MemoryMarshal.GetReference<T>(span), length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private unsafe static void UncheckedSlice(ref ReadOnlySpan<T> span, int start, int length) { span = MemoryMarshal.CreateReadOnlySpan<T>(ref Unsafe.Add<T>(ref MemoryMarshal.GetReference<T>(span), (IntPtr)(void*)(uint)start), length); } } }