< Summary

Class:DualKeyValueSet[TKey1,TKey2,TValue]
Assembly:KeyValueSet
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Utils/KeyValueSet/DualKeyValueSet.cs
Covered lines:46
Uncovered lines:11
Coverable lines:57
Total lines:161
Line coverage:80.7% (46 of 57)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
KeyPair(...)0%110100%
DualKeyValueSet()0%110100%
DualKeyValueSet(...)0%110100%
ContainsKey(...)0%110100%
TryGetValue(...)0%220100%
Add(...)0%110100%
RemoveAt(...)0%5.015093.33%
Remove(...)0%2.032080%
Clear()0%2100%
GetEnumerator()0%440100%
GetEnumerator()0%2100%
AddInternal(...)0%3.213071.43%

File(s)

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

#LineLine coverage
 1using System;
 2using System.Collections;
 3using System.Collections.Generic;
 4
 5public readonly struct KeyValueSetTriplet<TKey1, TKey2, TValue>
 6{
 7    public readonly TKey1 key1;
 8    public readonly TKey2 key2;
 9    public readonly TValue value;
 10
 11    public KeyValueSetTriplet(TKey1 key1, TKey2 key2, TValue value)
 12    {
 13        this.key1 = key1;
 14        this.key2 = key2;
 15        this.value = value;
 16    }
 17}
 18
 19public interface IReadOnlyDualKeyValueSet<TKey1, TKey2, TValue> : IEnumerable<KeyValueSetTriplet<TKey1, TKey2, TValue>>
 20{
 21    TValue this[TKey1 key1, TKey2 key2] { get; }
 22    int Count { get; }
 23    IReadOnlyList<KeyValueSetTriplet<TKey1, TKey2, TValue>> Pairs { get; }
 24    bool ContainsKey(TKey1 key1, TKey2 key2);
 25    bool TryGetValue(TKey1 key1, TKey2 key2, out TValue value);
 26}
 27
 28public class DualKeyValueSet<TKey1, TKey2, TValue> : IReadOnlyDualKeyValueSet<TKey1, TKey2, TValue>
 29{
 30    private readonly struct KeyPair
 31    {
 32        public readonly TKey1 key1;
 33        public readonly TKey2 key2;
 34
 35        public KeyPair(TKey1 key1, TKey2 key2)
 36        {
 287837            this.key1 = key1;
 287838            this.key2 = key2;
 287839        }
 40    }
 41
 42    private readonly Dictionary<KeyPair, int> indexer;
 43    private readonly List<KeyValueSetTriplet<TKey1, TKey2, TValue>> pairs;
 44
 15445    public IReadOnlyList<KeyValueSetTriplet<TKey1, TKey2, TValue>> Pairs => pairs;
 46
 13447    public int Count => pairs.Count;
 48
 49    public TValue this[TKey1 key1, TKey2 key2]
 50    {
 051        set => AddInternal(key1, key2, value, false);
 52        get
 53        {
 054            TryGetValue(key1, key2, out TValue value);
 055            return value;
 56        }
 57    }
 58
 459    public DualKeyValueSet() : this(0) { }
 60
 91261    public DualKeyValueSet(int capacity)
 62    {
 91263        indexer = new Dictionary<KeyPair, int>(capacity);
 91264        pairs = new List<KeyValueSetTriplet<TKey1, TKey2, TValue>>(capacity);
 91265    }
 66
 67    public bool ContainsKey(TKey1 key1, TKey2 key2)
 68    {
 121869        KeyPair keyPair = new KeyPair(key1, key2);
 121870        return indexer.ContainsKey(keyPair);
 71    }
 72
 73    public bool TryGetValue(TKey1 key1, TKey2 key2, out TValue value)
 74    {
 109075        KeyPair keyPair = new KeyPair(key1, key2);
 109076        if (!indexer.TryGetValue(keyPair, out int index))
 77        {
 27278            value = default;
 27279            return false;
 80        }
 81881        value = pairs[index].value;
 81882        return true;
 83    }
 84
 85    public void Add(TKey1 key1, TKey2 key2, TValue value)
 86    {
 29587        AddInternal(key1, key2, value, true);
 29588    }
 89
 90    public void RemoveAt(int index)
 91    {
 12192        int count = Count;
 12193        if (index >= count || index < 0)
 94        {
 095            throw new IndexOutOfRangeException();
 96        }
 97
 12198        TKey1 key1 = pairs[index].key1;
 12199        TKey2 key2 = pairs[index].key2;
 100
 121101        if (count > 1 && index < count - 1)
 102        {
 33103            int lastValueIndex = count - 1;
 33104            pairs[index] = pairs[lastValueIndex];
 33105            KeyPair newKeyPair = new KeyPair(pairs[lastValueIndex].key1, pairs[lastValueIndex].key2);
 33106            indexer[newKeyPair] = index;
 33107            pairs.RemoveAt(lastValueIndex);
 108        }
 109        else
 110        {
 88111            pairs.RemoveAt(index);
 112        }
 113
 121114        KeyPair removeKeyPair = new KeyPair(key1, key2);
 121115        indexer.Remove(removeKeyPair);
 121116    }
 117
 118    public bool Remove(TKey1 key1, TKey2 key2)
 119    {
 121120        KeyPair keyPair = new KeyPair(key1, key2);
 121
 121122        if (!indexer.TryGetValue(keyPair, out int index))
 123        {
 0124            return false;
 125        }
 126
 121127        RemoveAt(index);
 121128        return true;
 129    }
 130
 131    public void Clear()
 132    {
 0133        indexer.Clear();
 0134        pairs.Clear();
 0135    }
 136
 137    public IEnumerator<KeyValueSetTriplet<TKey1, TKey2, TValue>> GetEnumerator()
 138    {
 12139        for (int i = 0; i < Count; i++)
 140        {
 5141            yield return pairs[i];
 142        }
 1143    }
 144
 145    IEnumerator IEnumerable.GetEnumerator()
 146    {
 0147        return GetEnumerator();
 148    }
 149
 150    private void AddInternal(TKey1 key1, TKey2 key2, TValue value, bool add)
 151    {
 295152        KeyPair keyPair = new KeyPair(key1, key2);
 295153        if (!add && indexer.TryGetValue(keyPair, out int index))
 154        {
 0155            pairs[index] = new KeyValueSetTriplet<TKey1, TKey2, TValue>(keyPair.key1, keyPair.key2, value);
 0156            return;
 157        }
 295158        indexer.Add(keyPair, pairs.Count);
 295159        pairs.Add(new KeyValueSetTriplet<TKey1, TKey2, TValue>(keyPair.key1, keyPair.key2, value));
 295160    }
 161}