< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 32
Coverable lines: 32
Total lines: 110
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 8
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
GetNextDictionaryKey(...)100%110%
GetValueRefOrAddDefault(...)0%440%
GetOrAdd(...)0%440%
.ctor(...)100%110%
GetEnumerator()100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/BlobDictionary.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Collections.Immutable;
 6using System.Diagnostics;
 7using System.Reflection.Internal;
 8#if NET
 9using System.Runtime.InteropServices;
 10#endif
 11
 12namespace System.Reflection.Metadata.Ecma335
 13{
 14    [DebuggerDisplay("Count = {Count}")]
 15    internal readonly struct BlobDictionary
 16    {
 17        private readonly Dictionary<int, KeyValuePair<ImmutableArray<byte>, BlobHandle>> _dictionary;
 18
 19        // A simple LCG. Constants taken from
 20        // https://github.com/imneme/pcg-c/blob/83252d9c23df9c82ecb42210afed61a7b42402d7/include/pcg_variants.h#L276-L28
 21        private static int GetNextDictionaryKey(int dictionaryKey) =>
 022            (int)((uint)dictionaryKey * 747796405 + 2891336453);
 23
 24#if NET
 25        private unsafe ref KeyValuePair<ImmutableArray<byte>, BlobHandle> GetValueRefOrAddDefault(ReadOnlySpan<byte> key
 026        {
 027            int dictionaryKey = Hash.GetFNVHashCode(key);
 028            while (true)
 029            {
 030                ref var entry = ref CollectionsMarshal.GetValueRefOrAddDefault(_dictionary, dictionaryKey, out exists);
 031                if (!exists || entry.Key.AsSpan().SequenceEqual(key))
 032                {
 33#pragma warning disable CS9082 // Local is returned by reference but was initialized to a value that cannot be returned 
 34                    // In .NET 6 the assembly of GetValueRefOrAddDefault was compiled with earlier ref safety rules
 35                    // and caused an error, which was turned into a warning because of unsafe and was suppressed.
 036                    return ref entry;
 37#pragma warning restore CS9082
 38                }
 039                dictionaryKey = GetNextDictionaryKey(dictionaryKey);
 040            }
 041        }
 42
 43        public BlobHandle GetOrAdd(ReadOnlySpan<byte> key, ImmutableArray<byte> immutableKey, BlobHandle value, out bool
 044        {
 045            ref var entry = ref GetValueRefOrAddDefault(key, out exists);
 046            if (exists)
 047            {
 048                return entry.Value;
 49            }
 50
 51            // If we are given an immutable array, do not allocate a new one.
 052            if (immutableKey.IsDefault)
 053            {
 054                immutableKey = key.ToImmutableArray();
 055            }
 56            else
 057            {
 058                Debug.Assert(immutableKey.AsSpan().SequenceEqual(key));
 059            }
 60
 061            entry = new(immutableKey, value);
 062            return value;
 063        }
 64#else
 65        public BlobHandle GetOrAdd(ReadOnlySpan<byte> key, ImmutableArray<byte> immutableKey, BlobHandle value, out bool
 66        {
 67            int dictionarykey = Hash.GetFNVHashCode(key);
 68            KeyValuePair<ImmutableArray<byte>, BlobHandle> entry;
 69            while (true)
 70            {
 71                if (!(exists = _dictionary.TryGetValue(dictionarykey, out entry))
 72                    || entry.Key.AsSpan().SequenceEqual(key))
 73                {
 74                    break;
 75                }
 76                dictionarykey = GetNextDictionaryKey(dictionarykey);
 77            }
 78
 79            if (exists)
 80            {
 81                return entry.Value;
 82            }
 83
 84            // If we are given an immutable array, do not allocate a new one.
 85            if (immutableKey.IsDefault)
 86            {
 87                immutableKey = key.ToImmutableArray();
 88            }
 89            else
 90            {
 91                Debug.Assert(immutableKey.AsSpan().SequenceEqual(key));
 92            }
 93
 94            _dictionary.Add(dictionarykey, new(immutableKey, value));
 95            return value;
 96        }
 97#endif
 98
 99        public BlobDictionary(int capacity = 0)
 0100        {
 0101            _dictionary = new(capacity);
 0102        }
 103
 0104        public int Count => _dictionary.Count;
 105
 106        public Dictionary<int, KeyValuePair<ImmutableArray<byte>, BlobHandle>>.Enumerator GetEnumerator() =>
 0107            _dictionary.GetEnumerator();
 108    }
 109}
 110