<commit_before>using System.Diagnostics.CodeAnalysis;

namespace Parsley;

partial class Grammar
{
    public static Parser<TItem, TItem> Single<TItem>(TItem expected)
    {
        return Single<TItem>(x => EqualityComparer<TItem>.Default.Equals(x, expected), $"{expected}");
    }

    public static Parser<TItem, TItem> Single<TItem>(Predicate<TItem> test, string name)
    {
        return (ReadOnlySpan<TItem> input, ref int index, [NotNullWhen(true)] out TItem? value, [NotNullWhen(false)] out string? expectation) =>
        {
            var next = input.Peek(index, 1);

            if (next.Length == 1)
            {
                var c = next[0]!;
                if (test(c))
                {
                    index += 1;

                    expectation = null;
                    value = c;
                    return true;
                }
            }

            expectation = name;
            value = default;
            return false;
        };
    }
}

<commit_msg>Optimize Single to avoid excessive slice operations when we simply need to inspect a single item at a known index.<commit_after>using System.Diagnostics.CodeAnalysis;

namespace Parsley;

partial class Grammar
{
    public static Parser<TItem, TItem> Single<TItem>(TItem expected)
    {
        return Single<TItem>(x => EqualityComparer<TItem>.Default.Equals(x, expected), $"{expected}");
    }

    public static Parser<TItem, TItem> Single<TItem>(Predicate<TItem> test, string name)
    {
        return (ReadOnlySpan<TItem> input, ref int index, [NotNullWhen(true)] out TItem? value, [NotNullWhen(false)] out string? expectation) =>
        {
            if (index + 1 <= input.Length)
            {
                var c = input[index]!;
                if (test(c))
                {
                    index += 1;

                    expectation = null;
                    value = c;
                    return true;
                }
            }

            expectation = name;
            value = default;
            return false;
        };
    }
}


{'fraction_non_alphanumeric': 0.1036319612590799, 'fraction_numerical': 0.0029055690072639223, 'mean_word_length': 1.669250645994832, 'pattern_counts': {'":': 0, '<': 20, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6789335', 'n_tokens_mistral': 578, 'n_tokens_neox': 555, 'n_words': 148}