< Summary

Information
Class: NGql.Core.Features.KeyGenerator
Assembly: NGql.Core
File(s): /home/runner/work/NGql/NGql/src/Core/Features/KeyGenerator.cs
Line coverage
100%
Covered lines: 22
Uncovered lines: 0
Coverable lines: 22
Total lines: 73
Line coverage: 100%
Branch coverage
100%
Covered branches: 8
Total branches: 8
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GenerateUniqueKey(...)100%22100%
GenerateUniqueKey(...)100%44100%
GenerateUniqueKeyCore(...)100%22100%

File(s)

/home/runner/work/NGql/NGql/src/Core/Features/KeyGenerator.cs

#LineLine coverage
 1using NGql.Core.Abstractions;
 2using NGql.Core.Pooling;
 3
 4namespace NGql.Core.Features;
 5
 6/// <summary>
 7/// Utility class for generating unique keys.
 8/// </summary>
 9internal static class KeyGenerator
 10{
 11    /// <summary>
 12    /// Generates a unique key by appending a counter suffix if the base key already exists.
 13    /// </summary>
 14    /// <param name="baseKey">The base key to make unique</param>
 15    /// <param name="existingKeys">Collection of existing keys to check against</param>
 16    /// <returns>A unique key that doesn't exist in the collection</returns>
 17    internal static string GenerateUniqueKey(string baseKey, IEnumerable<string> existingKeys)
 18    {
 16519        using var pooledSet = LockFreeHashSetPool.GetPooled(existingKeys);
 16520        var existingKeySet = pooledSet.Set;
 21
 16522        if (!existingKeySet.Contains(baseKey))
 23        {
 9924            return baseKey;
 25        }
 26
 6627        return GenerateUniqueKeyCore(baseKey, existingKeySet);
 16528    }
 29
 30    /// <summary>
 31    /// Generates a unique key from field definitions' effective names (zero-alloc for span iteration).
 32    /// </summary>
 33    internal static string GenerateUniqueKey(string baseKey, ReadOnlySpan<FieldDefinition> fields)
 34    {
 935        using var pooledSet = LockFreeHashSetPool.GetPooled();
 936        var existingKeySet = pooledSet.Set;
 37
 38        // Populate set with effective names from span — zero-alloc iteration
 4839        for (int i = 0; i < fields.Length; i++)
 1540            existingKeySet.Add(fields[i]._effectiveName);
 41
 942        if (!existingKeySet.Contains(baseKey))
 43        {
 344            return baseKey;
 45        }
 46
 647        return GenerateUniqueKeyCore(baseKey, existingKeySet);
 948    }
 49
 50    private static string GenerateUniqueKeyCore(string baseKey, HashSet<string> existingKeySet)
 51    {
 52        // 16 chars holds "_" plus a 15-digit counter — counter is int, max ~10 digits.
 7253        Span<char> buffer = stackalloc char[baseKey.Length + 16];
 7254        baseKey.AsSpan().CopyTo(buffer);
 7255        buffer[baseKey.Length] = '_';
 56
 57        // Loop terminates as soon as the formatted candidate isn't in the existingKeySet.
 58        // existingKeySet has finite capacity bounded by the number of fields in the merged tree,
 59        // so a not-present key is always reachable; counter is int, more than enough headroom.
 60#pragma warning disable S1994
 8461        for (int counter = 1; ; counter++)
 62#pragma warning restore S1994
 63        {
 8464            counter.TryFormat(buffer[(baseKey.Length + 1)..], out var charsWritten);
 8465            var uniqueKey = new string(buffer[..(baseKey.Length + 1 + charsWritten)]);
 66
 8467            if (!existingKeySet.Contains(uniqueKey))
 68            {
 7269                return uniqueKey;
 70            }
 71        }
 72    }
 73}