< Summary

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

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
KeyValueSetTriplet(...)0%110100%

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    {
 29513        this.key1 = key1;
 29514        this.key2 = key2;
 29515        this.value = value;
 29516    }
 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        {
 37            this.key1 = key1;
 38            this.key2 = key2;
 39        }
 40    }
 41
 42    private readonly Dictionary<KeyPair, int> indexer;
 43    private readonly List<KeyValueSetTriplet<TKey1, TKey2, TValue>> pairs;
 44
 45    public IReadOnlyList<KeyValueSetTriplet<TKey1, TKey2, TValue>> Pairs => pairs;
 46
 47    public int Count => pairs.Count;
 48
 49    public TValue this[TKey1 key1, TKey2 key2]
 50    {
 51        set => AddInternal(key1, key2, value, false);
 52        get
 53        {
 54            TryGetValue(key1, key2, out TValue value);
 55            return value;
 56        }
 57    }
 58
 59    public DualKeyValueSet() : this(0) { }
 60
 61    public DualKeyValueSet(int capacity)
 62    {
 63        indexer = new Dictionary<KeyPair, int>(capacity);
 64        pairs = new List<KeyValueSetTriplet<TKey1, TKey2, TValue>>(capacity);
 65    }
 66
 67    public bool ContainsKey(TKey1 key1, TKey2 key2)
 68    {
 69        KeyPair keyPair = new KeyPair(key1, key2);
 70        return indexer.ContainsKey(keyPair);
 71    }
 72
 73    public bool TryGetValue(TKey1 key1, TKey2 key2, out TValue value)
 74    {
 75        KeyPair keyPair = new KeyPair(key1, key2);
 76        if (!indexer.TryGetValue(keyPair, out int index))
 77        {
 78            value = default;
 79            return false;
 80        }
 81        value = pairs[index].value;
 82        return true;
 83    }
 84
 85    public void Add(TKey1 key1, TKey2 key2, TValue value)
 86    {
 87        AddInternal(key1, key2, value, true);
 88    }
 89
 90    public void RemoveAt(int index)
 91    {
 92        int count = Count;
 93        if (index >= count || index < 0)
 94        {
 95            throw new IndexOutOfRangeException();
 96        }
 97
 98        TKey1 key1 = pairs[index].key1;
 99        TKey2 key2 = pairs[index].key2;
 100
 101        if (count > 1 && index < count - 1)
 102        {
 103            int lastValueIndex = count - 1;
 104            pairs[index] = pairs[lastValueIndex];
 105            KeyPair newKeyPair = new KeyPair(pairs[lastValueIndex].key1, pairs[lastValueIndex].key2);
 106            indexer[newKeyPair] = index;
 107            pairs.RemoveAt(lastValueIndex);
 108        }
 109        else
 110        {
 111            pairs.RemoveAt(index);
 112        }
 113
 114        KeyPair removeKeyPair = new KeyPair(key1, key2);
 115        indexer.Remove(removeKeyPair);
 116    }
 117
 118    public bool Remove(TKey1 key1, TKey2 key2)
 119    {
 120        KeyPair keyPair = new KeyPair(key1, key2);
 121
 122        if (!indexer.TryGetValue(keyPair, out int index))
 123        {
 124            return false;
 125        }
 126
 127        RemoveAt(index);
 128        return true;
 129    }
 130
 131    public void Clear()
 132    {
 133        indexer.Clear();
 134        pairs.Clear();
 135    }
 136
 137    public IEnumerator<KeyValueSetTriplet<TKey1, TKey2, TValue>> GetEnumerator()
 138    {
 139        for (int i = 0; i < Count; i++)
 140        {
 141            yield return pairs[i];
 142        }
 143    }
 144
 145    IEnumerator IEnumerable.GetEnumerator()
 146    {
 147        return GetEnumerator();
 148    }
 149
 150    private void AddInternal(TKey1 key1, TKey2 key2, TValue value, bool add)
 151    {
 152        KeyPair keyPair = new KeyPair(key1, key2);
 153        if (!add && indexer.TryGetValue(keyPair, out int index))
 154        {
 155            pairs[index] = new KeyValueSetTriplet<TKey1, TKey2, TValue>(keyPair.key1, keyPair.key2, value);
 156            return;
 157        }
 158        indexer.Add(keyPair, pairs.Count);
 159        pairs.Add(new KeyValueSetTriplet<TKey1, TKey2, TValue>(keyPair.key1, keyPair.key2, value));
 160    }
 161}