< Summary - Combined Code Coverage

Information
Class: NLightning.Bolt11.Models.TaggedFieldList
Assembly: NLightning.Bolt11.Blazor
File(s): /home/runner/work/nlightning/nlightning/src/NLightning.Bolt11/Models/TaggedFieldList.cs
Tag: 49_19945309242
Line coverage
0%
Covered lines: 0
Uncovered lines: 82
Coverable lines: 82
Total lines: 246
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 42
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%210%
Add(...)0%272160%
AddRange(...)0%620%
Remove(...)0%620%
RemoveAt(...)100%210%
RemoveAll(...)0%620%
RemoveRange(...)100%210%
TryGet(...)0%620%
TryGetAll(...)0%620%
FromBitReader(...)0%110100%
WriteToBitWriter(...)0%620%
CalculateSizeInBits()100%210%
Get(...)100%210%
GetAll(...)0%620%
OnChanged()0%620%

File(s)

/home/runner/work/nlightning/nlightning/src/NLightning.Bolt11/Models/TaggedFieldList.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Diagnostics.CodeAnalysis;
 3
 4namespace NLightning.Bolt11.Models;
 5
 6using Domain.Protocol.ValueObjects;
 7using Domain.Utils;
 8using Enums;
 9using Factories;
 10using Interfaces;
 11
 12/// <summary>
 13/// A list of tagged fields
 14/// </summary>
 15internal class TaggedFieldList : List<ITaggedField>
 16{
 017    private bool _shouldInvokeChangedEvent = true;
 18    public event EventHandler? Changed;
 19
 20    /// <summary>
 21    /// Add a tagged field to the list
 22    /// </summary>
 23    /// <param name="taggedField">The tagged field to add</param>
 24    /// <exception cref="ArgumentException">If the tagged field is not unique</exception>
 25    internal new void Add(ITaggedField taggedField)
 26    {
 27        // Individual field validation
 028        if (!taggedField.IsValid())
 029            throw new ArgumentException($"Invalid {taggedField.Type} field: field validation failed");
 30
 31        // Check for uniqueness
 032        if (this.Any(x => x.Type.Equals(taggedField.Type)) && taggedField.Type != TaggedFieldTypes.FallbackAddress)
 033            throw new ArgumentException(
 034                $"TaggedFieldDictionary already contains a tagged field of type {taggedField.Type}");
 35
 36        // Mutual exclusivity validation
 037        if (taggedField.Type == TaggedFieldTypes.Description
 038         && this.Any(x => x.Type.Equals(TaggedFieldTypes.DescriptionHash)))
 039            throw new ArgumentException(
 040                $"TaggedFieldDictionary already contains a tagged field of type {taggedField.Type}");
 41
 042        if (taggedField.Type == TaggedFieldTypes.DescriptionHash
 043         && this.Any(x => x.Type.Equals(TaggedFieldTypes.Description)))
 044            throw new ArgumentException(
 045                $"TaggedFieldDictionary already contains a tagged field of type {taggedField.Type}");
 46
 47        // Add the tagged field
 048        base.Add(taggedField);
 049        if (_shouldInvokeChangedEvent)
 050            OnChanged();
 051    }
 52
 53    /// <summary>
 54    /// Add a range of tagged fields to the list
 55    /// </summary>
 56    /// <param name="taggedFields">The tagged fields to add</param>
 57    internal new void AddRange(IEnumerable<ITaggedField> taggedFields)
 58    {
 059        _shouldInvokeChangedEvent = false;
 60
 061        foreach (var taggedField in taggedFields)
 062            Add(taggedField);
 63
 064        _shouldInvokeChangedEvent = true;
 065        OnChanged();
 066    }
 67
 68    internal new bool Remove(ITaggedField item)
 69    {
 070        if (!base.Remove(item))
 071            return false;
 72
 073        OnChanged();
 074        return true;
 75    }
 76
 77    internal new void RemoveAt(int index)
 78    {
 079        base.RemoveAt(index);
 080        OnChanged();
 081    }
 82
 83    internal new int RemoveAll(Predicate<ITaggedField> match)
 84    {
 085        var removed = base.RemoveAll(match);
 086        if (removed > 0)
 087            OnChanged();
 88
 089        return removed;
 90    }
 91
 92    internal new void RemoveRange(int index, int count)
 93    {
 094        base.RemoveRange(index, count);
 095        OnChanged();
 096    }
 97
 98    /// <summary>
 99    /// Attempts to retrieve a tagged field of the specified type from the list.
 100    /// </summary>
 101    /// <typeparam name="T">The type of the tagged field to retrieve.</typeparam>
 102    /// <param name="taggedFieldType">The type of the tagged field being searched for.</param>
 103    /// <param name="taggedField">The output parameter to hold the retrieved tagged field if found; otherwise, the defau
 104    /// <returns>True if the tagged field of the specified type is found; otherwise, false.</returns>
 105    internal bool TryGet<T>(TaggedFieldTypes taggedFieldType, [MaybeNullWhen(false)] out T taggedField)
 106        where T : ITaggedField
 107    {
 0108        var value = Get<T>(taggedFieldType);
 0109        if (value != null)
 110        {
 0111            taggedField = value;
 0112            return true;
 113        }
 114
 0115        taggedField = default;
 0116        return false;
 117    }
 118
 119    /// <summary>
 120    /// Try to get all tagged fields of a specific type
 121    /// </summary>
 122    /// <param name="taggedFieldType">The type of the tagged field</param>
 123    /// <param name="taggedFieldList">A list containing the tagged fields</param>
 124    /// <typeparam name="T">The type of the tagged field</typeparam>
 125    /// <returns>True if the tagged fields were found, false otherwise</returns>
 126    internal bool TryGetAll<T>(TaggedFieldTypes taggedFieldType, [MaybeNullWhen(false)] out List<T> taggedFieldList)
 127        where T : ITaggedField
 128    {
 0129        var value = GetAll<T>(taggedFieldType);
 0130        if (value != null)
 131        {
 0132            taggedFieldList = value;
 0133            return true;
 134        }
 135
 0136        taggedFieldList = null;
 0137        return false;
 138    }
 139
 140    /// <summary>
 141    /// Get a new TaggedFieldList from a BitReader
 142    /// </summary>
 143    /// <param name="bitReader">The BitReader to read from</param>
 144    /// <param name="bitcoinNetwork">The network type</param>
 145    /// <returns>A new TaggedFieldList</returns>
 146    internal static TaggedFieldList FromBitReader(BitReader bitReader, BitcoinNetwork bitcoinNetwork)
 147    {
 0148        var taggedFields = new TaggedFieldList();
 0149        while (bitReader.HasMoreBits(15))
 150        {
 0151            var type = (TaggedFieldTypes)bitReader.ReadByteFromBits(5);
 0152            var length = bitReader.ReadInt16FromBits(10);
 0153            if (length != 0 && !bitReader.HasMoreBits(length * 5))
 154                continue;
 155
 0156            if (!Enum.IsDefined(type))
 157            {
 0158                bitReader.SkipBits(length * 5);
 159            }
 160            else
 161            {
 162                try
 163                {
 0164                    var taggedField =
 0165                        TaggedFieldFactory.CreateTaggedFieldFromBitReader(type, bitReader, length, bitcoinNetwork);
 0166                    if (taggedField is null)
 0167                        continue;
 168
 169                    try
 170                    {
 0171                        taggedFields.Add(taggedField);
 0172                    }
 0173                    catch (Exception e)
 174                    {
 175                        Debug.WriteLine(e.Message);
 176                        // Skip for now, log latter
 0177                    }
 0178                }
 0179                catch (Exception e)
 180                {
 181                    Debug.WriteLine(e.Message);
 182                    // Skip for now, log latter
 0183                }
 184            }
 185        }
 186
 0187        return taggedFields;
 188    }
 189
 190    /// <summary>
 191    /// Write the TaggedFieldList to a BitWriter
 192    /// </summary>
 193    /// <param name="bitWriter">The BitWriter to write to</param>
 194    internal void WriteToBitWriter(BitWriter bitWriter)
 195    {
 0196        foreach (var taggedField in this)
 197        {
 198            // Write type
 0199            bitWriter.WriteByteAsBits((byte)taggedField.Type, 5);
 200
 201            // Write length
 0202            bitWriter.WriteInt16AsBits(taggedField.Length, 10);
 203
 0204            taggedField.WriteToBitWriter(bitWriter);
 205        }
 0206    }
 207
 208    /// <summary>
 209    /// Calculate the size of the TaggedFieldList in bits
 210    /// </summary>
 211    /// <returns>The size of the TaggedFieldList in bits</returns>
 212    internal int CalculateSizeInBits()
 213    {
 0214        return this.Sum(x => x.Length);
 215    }
 216
 217    /// <summary>
 218    /// Get a tagged field of a specific type
 219    /// </summary>
 220    /// <param name="taggedFieldType">The type of the tagged field</param>
 221    /// <typeparam name="T">The type of the tagged field</typeparam>
 222    /// <returns>The tagged field</returns>
 223    private T? Get<T>(TaggedFieldTypes taggedFieldType) where T : ITaggedField
 224    {
 0225        return (T?)this.FirstOrDefault(x => x.Type.Equals(taggedFieldType));
 226    }
 227
 228    /// <summary>
 229    /// Get all tagged fields of a specific type
 230    /// </summary>
 231    /// <param name="taggedFieldType">The type of the tagged field</param>
 232    /// <typeparam name="T">The type of the tagged field</typeparam>
 233    /// <returns>A list containing the tagged fields</returns>
 234    private List<T>? GetAll<T>(TaggedFieldTypes taggedFieldType) where T : ITaggedField
 235    {
 0236        var taggedFields = this.Where(x => x.Type.Equals(taggedFieldType)).ToList();
 0237        return taggedFields.Count == 0
 0238                   ? null
 0239                   : taggedFields.Cast<T>().ToList();
 240    }
 241
 242    private void OnChanged()
 243    {
 0244        Changed?.Invoke(this, EventArgs.Empty);
 0245    }
 246}