< Summary

Information
Class: IceRpc.Ice.Codec.IceDecoderExtensions
Assembly: IceRpc
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Ice/Codec/IceDecoderExtensions.cs
Tag: 1321_24790053727
Line coverage
93%
Covered lines: 85
Uncovered lines: 6
Coverable lines: 91
Total lines: 199
Line coverage: 93.4%
Branch coverage
87%
Covered branches: 28
Total branches: 32
Branch coverage: 87.5%
Method coverage
100%
Covered methods: 9
Fully covered methods: 6
Total methods: 9
Method coverage: 100%
Full method coverage: 66.6%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
CheckEndOfBuffer(...)50%2280%
DecodeDictionary(...)75%4490.47%
DecodeSequence(...)83.33%6690%
DecodeSequence(...)100%44100%
DecodeCollection(...)75%4485.71%
DecodeLinkedList(...)100%44100%
DecodeList(...)100%44100%
DecodeQueue(...)100%44100%
DecodeStack(...)100%11100%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/IceRpc/Ice/Codec/IceDecoderExtensions.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Runtime.CompilerServices;
 4using System.Runtime.InteropServices;
 5
 6namespace IceRpc.Ice.Codec;
 7
 8/// <summary>Provides extension methods for <see cref="IceDecoder" /> to decode sequences or dictionaries.</summary>
 9public static class IceDecoderExtensions
 10{
 11    /// <summary>Verifies the Ice decoder has reached the end of its underlying buffer.</summary>
 12    /// <param name="decoder">The Ice decoder.</param>
 13    public static void CheckEndOfBuffer(this ref IceDecoder decoder)
 467214    {
 467215        if (!decoder.End)
 116        {
 117            throw new InvalidDataException($"There are {decoder.Remaining} bytes remaining in the buffer.");
 18        }
 467119    }
 20
 21    /// <summary>Decodes a dictionary.</summary>
 22    /// <typeparam name="TDictionary">The type of the returned dictionary.</typeparam>
 23    /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
 24    /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
 25    /// <param name="decoder">The Ice decoder.</param>
 26    /// <param name="dictionaryFactory">The factory for creating the dictionary instance.</param>
 27    /// <param name="keyDecodeFunc">The decode function for each key of the dictionary.</param>
 28    /// <param name="valueDecodeFunc">The decode function for each value of the dictionary.</param>
 29    /// <returns>The dictionary decoded by this decoder.</returns>
 30    public static TDictionary DecodeDictionary<TDictionary, TKey, TValue>(
 31        this ref IceDecoder decoder,
 32        Func<int, TDictionary> dictionaryFactory,
 33        DecodeFunc<TKey> keyDecodeFunc,
 34        DecodeFunc<TValue> valueDecodeFunc)
 35        where TKey : notnull
 36        where TDictionary : IDictionary<TKey, TValue>
 3437    {
 3438        int count = decoder.DecodeSize();
 3439        if (count == 0)
 040        {
 041            return dictionaryFactory(0);
 42        }
 43        else
 3444        {
 3445            decoder.IncreaseCollectionAllocation(count, Unsafe.SizeOf<TKey>() + Unsafe.SizeOf<TValue>());
 3046            TDictionary dictionary = dictionaryFactory(count);
 254847            for (int i = 0; i < count; ++i)
 124548            {
 124549                TKey key = keyDecodeFunc(ref decoder);
 124550                TValue value = valueDecodeFunc(ref decoder);
 51                try
 124552                {
 124553                    dictionary.Add(key, value);
 124454                }
 155                catch (ArgumentException exception)
 156                {
 157                    throw new InvalidDataException($"Received dictionary with duplicate key '{key}'.", exception);
 58                }
 124459            }
 2960            return dictionary;
 61        }
 2962    }
 63
 64    /// <summary>Decodes a sequence of fixed-size numeric values.</summary>
 65    /// <typeparam name="T">The sequence element type.</typeparam>
 66    /// <param name="decoder">The Ice decoder.</param>
 67    /// <param name="checkElement">A delegate used to check each element of the array (optional).</param>
 68    /// <returns>An array of T.</returns>
 69    public static T[] DecodeSequence<T>(this ref IceDecoder decoder, Action<T>? checkElement = null)
 70        where T : struct
 2171    {
 2172        int count = decoder.DecodeSize();
 2173        if (count == 0)
 074        {
 075            return [];
 76        }
 77        else
 2178        {
 2179            int elementSize = Unsafe.SizeOf<T>();
 2180            decoder.IncreaseCollectionAllocation(count, elementSize);
 2181            var value = new T[count];
 2182            Span<byte> destination = MemoryMarshal.Cast<T, byte>(value.AsSpan());
 2183            decoder.CopyTo(destination);
 84
 2185            if (checkElement is not null)
 386            {
 3687                foreach (T e in value)
 1488                {
 1489                    checkElement(e);
 1390                }
 291            }
 2092            return value;
 93        }
 2094    }
 95
 96    /// <summary>Decodes a sequence.</summary>
 97    /// <typeparam name="T">The type of the elements in the array.</typeparam>
 98    /// <param name="decoder">The Ice decoder.</param>
 99    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 100    /// <returns>An array of T.</returns>
 101    public static T[] DecodeSequence<T>(this ref IceDecoder decoder, DecodeFunc<T> decodeFunc)
 1485102    {
 1485103        int count = decoder.DecodeSize();
 1485104        if (count == 0)
 1448105        {
 1448106            return [];
 107        }
 108        else
 37109        {
 37110            decoder.IncreaseCollectionAllocation(count, Unsafe.SizeOf<T>());
 33111            var array = new T[count];
 1526112            for (int i = 0; i < count; ++i)
 730113            {
 730114                array[i] = decodeFunc(ref decoder);
 730115            }
 33116            return array;
 117        }
 1481118    }
 119
 120    /// <summary>Decodes an Ice sequence mapped to a custom collection.</summary>
 121    /// <typeparam name="TCollection">The type of the returned collection.</typeparam>
 122    /// <typeparam name="TElement">The type of the elements in the collection.</typeparam>
 123    /// <param name="decoder">The Ice decoder.</param>
 124    /// <param name="collectionFactory">A delegate used to create the collection with the specified capacity.</param>
 125    /// <param name="addElement">A delegate used to add each decoded element to the collection.</param>
 126    /// <param name="decodeFunc">The decode function for each element of the collection.</param>
 127    /// <returns>The decoded collection.</returns>
 128    public static TCollection DecodeCollection<TCollection, TElement>(
 129        this ref IceDecoder decoder,
 130        Func<int, TCollection> collectionFactory,
 131        Action<TCollection, TElement> addElement,
 132        DecodeFunc<TElement> decodeFunc)
 26133    {
 26134        int count = decoder.DecodeSize();
 26135        if (count == 0)
 0136        {
 0137            return collectionFactory(0);
 138        }
 139        else
 26140        {
 26141            decoder.IncreaseCollectionAllocation(count, Unsafe.SizeOf<TElement>());
 26142            TCollection collection = collectionFactory(count);
 168143            for (int i = 0; i < count; ++i)
 58144            {
 58145                addElement(collection, decodeFunc(ref decoder));
 58146            }
 26147            return collection;
 148        }
 26149    }
 150
 151    /// <summary>Decodes an Ice sequence mapped to a <see cref="LinkedList{T}" />.</summary>
 152    /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
 153    /// <param name="decoder">The Ice decoder.</param>
 154    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 155    /// <returns>A <see cref="LinkedList{T}" />.</returns>
 156    public static LinkedList<TElement> DecodeLinkedList<TElement>(
 157        this ref IceDecoder decoder,
 158        DecodeFunc<TElement> decodeFunc) =>
 4159        decoder.DecodeCollection<LinkedList<TElement>, TElement>(
 4160            collectionFactory: _ => new LinkedList<TElement>(),
 7161            (list, element) => list.AddLast(element),
 4162            decodeFunc);
 163
 164    /// <summary>Decodes an Ice sequence mapped to a <see cref="List{T}" />.</summary>
 165    /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
 166    /// <param name="decoder">The Ice decoder.</param>
 167    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 168    /// <returns>A <see cref="List{T}" />.</returns>
 169    public static List<TElement> DecodeList<TElement>(
 170        this ref IceDecoder decoder,
 171        DecodeFunc<TElement> decodeFunc) =>
 4172        decoder.DecodeCollection<List<TElement>, TElement>(
 4173            collectionFactory: count => new List<TElement>(count),
 7174            (list, element) => list.Add(element),
 4175            decodeFunc);
 176
 177    /// <summary>Decodes an Ice sequence mapped to a <see cref="Queue{T}" />.</summary>
 178    /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
 179    /// <param name="decoder">The Ice decoder.</param>
 180    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 181    /// <returns>A <see cref="Queue{T}" />.</returns>
 182    public static Queue<TElement> DecodeQueue<TElement>(this ref IceDecoder decoder, DecodeFunc<TElement> decodeFunc) =>
 4183        decoder.DecodeCollection<Queue<TElement>, TElement>(
 4184            collectionFactory: count => new Queue<TElement>(count),
 7185            (queue, element) => queue.Enqueue(element),
 4186            decodeFunc);
 187
 188    /// <summary>Decodes an Ice sequence mapped to a <see cref="Stack{T}" />.</summary>
 189    /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
 190    /// <param name="decoder">The Ice decoder.</param>
 191    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 192    /// <returns>A <see cref="Stack{T}" />.</returns>
 193    public static Stack<TElement> DecodeStack<TElement>(this ref IceDecoder decoder, DecodeFunc<TElement> decodeFunc)
 6194    {
 6195        var array = decoder.DecodeSequence(decodeFunc);
 6196        Array.Reverse(array);
 6197        return new Stack<TElement>(array);
 6198    }
 199}