// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // https://github.com/CommunityToolkit/dotnet/blob/main/CommunityToolkit.HighPerformance/Enumerables/SpanEnumerable%7BT%7D.cs using System.ComponentModel; using System.Runtime.CompilerServices; namespace FisheryLib; /// /// A that enumerates the items in a given instance. /// /// The type of items to enumerate. [EditorBrowsable(EditorBrowsableState.Never)] [PublicAPI] public ref struct SpanEnumerable { /// /// The source instance. /// private readonly Span _span; /// /// The current index within . /// private int _index; /// /// Initializes a new instance of the struct. /// /// The source instance. [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanEnumerable(Span span) { _span = span; _index = -1; } /// /// Implements the duck-typed method. /// /// An instance targeting the current value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly SpanEnumerable GetEnumerator() => this; /// /// Implements the duck-typed method. /// /// whether a new element is available, otherwise [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() => ++_index < _span.Length; /// /// Gets the duck-typed property. /// public readonly Item Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get // On .NET Standard 2.1 and .NET Core (or on any target that offers runtime // support for the Span types), we can save 4 bytes by piggybacking the // current index in the length of the wrapped span. We're going to use the // first item as the target reference, and the length as a host for the // current original offset. This is not possible on eg. .NET Standard 2.0, // as we lack the API to create Span-s from arbitrary references. => new(ref Unsafe.Add(ref _span.DangerousGetPinnableReference(), (nint)(uint)_index), _index); } /// /// An item from a source instance. /// [EditorBrowsable(EditorBrowsableState.Never)] public readonly ref struct Item { /// /// The source instance. /// private readonly Span _span; /// /// Initializes a new instance of the struct. /// /// A reference to the target value. /// The index of the target value. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Item(ref T value, int index) => _span = MemoryMarshal.CreateSpan(ref value, index); /// /// Gets the reference to the current value. /// public ref T Value { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => ref MemoryMarshal.GetReference(_span); } /// /// Gets the current index. /// public int Index { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _span.Length; } } }