// 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. using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.Contracts; using System.Runtime.CompilerServices; namespace CommunityToolkit.HighPerformance.Enumerables; /// /// A that tokenizes a given instance. /// /// The type of items to enumerate. [EditorBrowsable(EditorBrowsableState.Never)] public ref struct SpanTokenizer where T : IEquatable { /// /// The source instance. /// private readonly Span span; /// /// The separator item to use. /// private readonly T separator; /// /// The current initial offset. /// private int start; /// /// The current final offset. /// private int end; /// /// Initializes a new instance of the struct. /// /// The source instance. /// The separator item to use. [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanTokenizer(Span span, T separator) { this.span = span; this.separator = separator; this.start = 0; this.end = -1; } /// /// Implements the duck-typed method. /// /// An instance targeting the current value. [Pure] [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly SpanTokenizer GetEnumerator() => this; /// /// Implements the duck-typed method. /// /// whether a new element is available, otherwise [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int newEnd = this.end + 1; int length = this.span.Length; // Additional check if the separator is not the last character if (newEnd <= length) { this.start = newEnd; int index = this.span.Slice(newEnd).IndexOf(this.separator); // Extract the current subsequence if (index >= 0) { this.end = newEnd + index; return true; } this.end = length; return true; } return false; } /// /// Gets the duck-typed property. /// public readonly Span Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => this.span.Slice(this.start, this.end - this.start); } }