using System;
using ToolkitPathUtilities = StardewModdingAPI.Toolkit.Utilities.PathUtilities;
namespace StardewModdingAPI.Utilities.AssetPathUtilities
{
/// Handles enumerating the normalized segments in an asset name.
internal ref struct AssetNamePartEnumerator
{
/*********
** Fields
*********/
/// The backing field for .
private ReadOnlySpan RemainderImpl;
/*********
** Properties
*********/
/// The remainder of the asset name being enumerated, ignoring segments which have already been yielded.
public ReadOnlySpan Remainder => this.RemainderImpl;
/// Get the current segment.
public ReadOnlySpan Current { get; private set; } = default;
/*********
** Public methods
*********/
/// Construct an instance.
/// The asset name to enumerate.
public AssetNamePartEnumerator(ReadOnlySpan assetName)
{
this.RemainderImpl = AssetNamePartEnumerator.TrimLeadingPathSeparators(assetName);
}
/// Move the enumerator to the next segment.
/// Returns true if a new value was found (accessible via ).
public bool MoveNext()
{
if (this.RemainderImpl.Length == 0)
return false;
int index = this.RemainderImpl.IndexOfAny(ToolkitPathUtilities.PossiblePathSeparators);
// no more separator characters found, I'm done.
if (index < 0)
{
this.Current = this.RemainderImpl;
this.RemainderImpl = ReadOnlySpan.Empty;
return true;
}
// Yield the next separate character bit
this.Current = this.RemainderImpl[..index];
this.RemainderImpl = AssetNamePartEnumerator.TrimLeadingPathSeparators(this.RemainderImpl[(index + 1)..]);
return true;
}
/*********
** Private methods
*********/
/// Trim path separators at the start of the given path or segment.
/// The path or segment to trim.
private static ReadOnlySpan TrimLeadingPathSeparators(ReadOnlySpan span)
{
return span.TrimStart(new ReadOnlySpan(ToolkitPathUtilities.PossiblePathSeparators));
}
}
}