< Summary

Class:KeyValueSet[TKey,TValue]
Assembly:KeyValueSet
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/KeyValueSet/KeyValueSet.cs
Covered lines:35
Uncovered lines:12
Coverable lines:47
Total lines:150
Line coverage:74.4% (35 of 47)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
KeyValueSet()0%110100%
KeyValueSet(...)0%110100%
ContainsKey(...)0%110100%
TryGetValue(...)0%220100%
Add(...)0%110100%
RemoveAt(...)0%6.815058.33%
Remove(...)0%220100%
Clear()0%2100%
GetEnumerator()0%20400%
GetEnumerator()0%2100%
AddInternal(...)0%330100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/KeyValueSet/KeyValueSet.cs

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4
 5/*
 6 * `KeyValueSet` works as an alternative of `Dictionary` when a iteration through all it values is performed frequently.
 7 * CONS: It's much slower to modify the data compared to a `Dictionary`
 8 * PRO: It's much faster to iterate through all the data compared to a `Dictionary` and
 9 *      it doesn't alloc extra memory while doing so.
 10 * Benchmark against a `Dictionary`:
 11 * Adding element: ~32% slower
 12 * Removing element: ~164% slower
 13 * Iterating through all elements: ~34% faster
 14 */
 15
 16public readonly struct KeyValueSetPair<TKey, TValue>
 17{
 18    public readonly TKey key;
 19    public readonly TValue value;
 20
 21    public KeyValueSetPair(TKey key, TValue value)
 22    {
 23        this.key = key;
 24        this.value = value;
 25    }
 26}
 27
 28public interface IReadOnlyKeyValueSet<TKey, TValue> : IEnumerable<KeyValueSetPair<TKey, TValue>>
 29{
 30    TValue this[TKey key] { get; }
 31    int Count { get; }
 32    IReadOnlyList<KeyValueSetPair<TKey, TValue>> Pairs { get; }
 33    bool ContainsKey(TKey key);
 34    bool TryGetValue(TKey key, out TValue value);
 35}
 36
 37public class KeyValueSet<TKey, TValue> : IReadOnlyKeyValueSet<TKey, TValue>
 38{
 39    private readonly Dictionary<TKey, int> indexer;
 40    private readonly List<KeyValueSetPair<TKey, TValue>> pairs;
 41
 56942    public IReadOnlyList<KeyValueSetPair<TKey, TValue>> Pairs => pairs;
 43
 11444    public int Count => pairs.Count;
 45
 46    public TValue this[TKey key]
 47    {
 1148        set => AddInternal(key, value, false);
 49        get
 50        {
 851            TryGetValue(key, out TValue value);
 852            return value;
 53        }
 54    }
 55
 32656    public KeyValueSet() : this(0) { }
 57
 20158    public KeyValueSet(int capacity)
 59    {
 20160        indexer = new Dictionary<TKey, int>(capacity);
 20161        pairs = new List<KeyValueSetPair<TKey, TValue>>(capacity);
 20162    }
 63
 64    public bool ContainsKey(TKey key)
 65    {
 966        return indexer.ContainsKey(key);
 67    }
 68
 69    public bool TryGetValue(TKey key, out TValue value)
 70    {
 138571        if (!indexer.TryGetValue(key, out int index))
 72        {
 91073            value = default;
 91074            return false;
 75        }
 47576        value = pairs[index].value;
 47577        return true;
 78    }
 79
 80    public void Add(TKey key, TValue value)
 81    {
 90782        AddInternal(key, value, true);
 90783    }
 84
 85    public void RemoveAt(int index)
 86    {
 687        int count = Count;
 688        if (index >= count || index < 0)
 89        {
 090            throw new IndexOutOfRangeException();
 91        }
 92
 693        TKey key = pairs[index].key;
 94
 695        if (count > 1 && index < count - 1)
 96        {
 097            int lastValueIndex = count - 1;
 098            pairs[index] = pairs[lastValueIndex];
 099            indexer[pairs[lastValueIndex].key] = index;
 0100            pairs.RemoveAt(lastValueIndex);
 101        }
 102        else
 103        {
 6104            pairs.RemoveAt(index);
 105        }
 106
 6107        indexer.Remove(key);
 6108    }
 109
 110    public bool Remove(TKey key)
 111    {
 7112        if (!indexer.TryGetValue(key, out int index))
 113        {
 6114            return false;
 115        }
 116
 1117        RemoveAt(index);
 1118        return true;
 119    }
 120
 121    public void Clear()
 122    {
 0123        indexer.Clear();
 0124        pairs.Clear();
 0125    }
 126
 127    public IEnumerator<KeyValueSetPair<TKey, TValue>> GetEnumerator()
 128    {
 0129        for (int i = 0; i < Count; i++)
 130        {
 0131            yield return pairs[i];
 132        }
 0133    }
 134
 135    IEnumerator IEnumerable.GetEnumerator()
 136    {
 0137        return GetEnumerator();
 138    }
 139
 140    private void AddInternal(TKey key, TValue value, bool add)
 141    {
 918142        if (!add && indexer.TryGetValue(key, out int index))
 143        {
 2144            pairs[index] = new KeyValueSetPair<TKey, TValue>(key, value);
 2145            return;
 146        }
 916147        indexer.Add(key, pairs.Count);
 916148        pairs.Add(new KeyValueSetPair<TKey, TValue>(key, value));
 916149    }
 150}