namespace Parsley;

public static class ReadOnlySpanExtensions
{
    public static ReadOnlySpan<char> Peek(this ref ReadOnlySpan<char> input, int length)
        => length >= input.Length
            ? input.Slice(0)
            : input.Slice(0, length);

    public static void Advance(this ref ReadOnlySpan<char> input, ref Position position, int length)
    {
        int lineDelta = 0;
        int columnDelta = 0;

        var peek = input.Peek(length);

        foreach (var ch in peek)
        {
            if (ch == '\n')
            {
                lineDelta++;
                columnDelta = 0 - position.Column;
            }

            columnDelta++;
        }

        input = input.Slice(peek.Length);
        position = new Position(position.Line + lineDelta, position.Column + columnDelta);
    }

    public static ReadOnlySpan<char> TakeWhile(this ref ReadOnlySpan<char> input, Predicate<char> test)
    {
        int i = 0;

        while (i < input.Length && test(input[i]))
            i++;

        return input.Peek(i);
    }
}

namespace Parsley;

public static class ReadOnlySpanExtensions
{
    public static ReadOnlySpan<char> Peek(this ref ReadOnlySpan<char> input, int length)
        => length >= input.Length
            ? input.Slice(0)
            : input.Slice(0, length);

    public static void Advance(this ref ReadOnlySpan<char> input, ref Position position, int length)
    {
        var peek = input.Peek(length);

        input = input.Slice(peek.Length);

        int lineDelta = 0;
        int columnDelta = 0;

        foreach (var ch in peek)
        {
            if (ch == '\n')
            {
                lineDelta++;
                columnDelta = 0 - position.Column;
            }

            columnDelta++;
        }

        position = new Position(position.Line + lineDelta, position.Column + columnDelta);
    }

    public static ReadOnlySpan<char> TakeWhile(this ref ReadOnlySpan<char> input, Predicate<char> test)
    {
        int i = 0;

        while (i < input.Length && test(input[i]))
            i++;

        return input.Peek(i);
    }
}

Reorder lines within Advance to no longer interleve two distinct operations in play: advancing the input span by `length` items, and then analyzing the items advanced over to update the Position. This is a step towards extracting a method for each of the two distinct operations.
Reorder lines within Advance to no longer interleve two distinct operations in play: advancing the input span by `length` items, and then analyzing the items advanced over to update the Position. This is a step towards extracting a method for each of the two distinct operations.
