using System; using ToolkitPathUtilities = StardewModdingAPI.Toolkit.Utilities.PathUtilities; namespace StardewModdingAPI.Utilities.AssetPathUtilities; /// /// A helper class that yields out each bit of an asset path /// internal ref struct AssetPartYielder { private ReadOnlySpan remainder; /// /// Construct an instance. /// /// The asset name. internal AssetPartYielder(ReadOnlySpan assetName) { this.remainder = AssetPartYielder.TrimLeadingPathSeperators(assetName); } /// /// The remainder of the assetName (that hasn't been yielded out yet.) /// internal ReadOnlySpan Remainder => this.remainder; /// /// The current segment. /// public ReadOnlySpan Current { get; private set; } = default; // this is just so it can be used in a foreach loop. public AssetPartYielder GetEnumerator() => this; /// /// Moves the enumerator to the next element. /// /// True if there is a new public bool MoveNext() { if (this.remainder.Length == 0) { return false; } int index = this.remainder.IndexOfAny(ToolkitPathUtilities.PossiblePathSeparators); // no more seperator characters found, I'm done. if (index < 0) { this.Current = this.remainder; this.remainder = ReadOnlySpan.Empty; return true; } // Yield the next seperate character bit this.Current = this.remainder[..index]; this.remainder = AssetPartYielder.TrimLeadingPathSeperators(this.remainder[(index + 1)..]); return true; } private static ReadOnlySpan TrimLeadingPathSeperators(ReadOnlySpan span) { return span.TrimStart(new ReadOnlySpan(ToolkitPathUtilities.PossiblePathSeparators)); } }