< Summary

Information
Class: ZeroC.Slice.SliceDecoderExtensions
Assembly: ZeroC.Slice
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/ZeroC.Slice/SliceDecoderExtensions.cs
Tag: 275_13775359185
Line coverage
77%
Covered lines: 91
Uncovered lines: 26
Coverable lines: 117
Total lines: 249
Line coverage: 77.7%
Branch coverage
70%
Covered branches: 34
Total branches: 48
Branch coverage: 70.8%
Method coverage
87%
Covered methods: 7
Total methods: 8
Method coverage: 87.5%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
DecodeDictionary(...)100%66100%
DecodeDictionaryWithOptionalValueType(...)87.5%8.1888.23%
DecodeResult(...)75%4.07483.33%
DecodeSequence(...)83.33%6.04690%
DecodeSequence(...)75%4.05485.71%
DecodeSequence(...)83.33%6.11685.71%
DecodeSequenceOfOptionals(...)83.33%6.09686.66%
DecodeSequenceOfOptionals(...)0%7280%

File(s)

/home/runner/work/icerpc-csharp/icerpc-csharp/src/ZeroC.Slice/SliceDecoderExtensions.cs

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Runtime.CompilerServices;
 4using System.Runtime.InteropServices;
 5
 6namespace ZeroC.Slice;
 7
 8/// <summary>Provides extension methods for <see cref="SliceDecoder" /> to decode sequences or dictionaries.</summary>
 9public static class SliceDecoderExtensions
 10{
 11    /// <summary>Decodes a dictionary.</summary>
 12    /// <typeparam name="TDictionary">The type of the returned dictionary.</typeparam>
 13    /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
 14    /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
 15    /// <param name="decoder">The Slice decoder.</param>
 16    /// <param name="dictionaryFactory">The factory for creating the dictionary instance.</param>
 17    /// <param name="keyDecodeFunc">The decode function for each key of the dictionary.</param>
 18    /// <param name="valueDecodeFunc">The decode function for each value of the dictionary.</param>
 19    /// <returns>The dictionary decoded by this decoder.</returns>
 20    public static TDictionary DecodeDictionary<TDictionary, TKey, TValue>(
 21        this ref SliceDecoder decoder,
 22        Func<int, TDictionary> dictionaryFactory,
 23        DecodeFunc<TKey> keyDecodeFunc,
 24        DecodeFunc<TValue> valueDecodeFunc)
 25        where TKey : notnull
 26        where TDictionary : ICollection<KeyValuePair<TKey, TValue>>
 184427    {
 184428        int count = decoder.DecodeSize();
 184029        if (count == 0)
 56530        {
 56531            return dictionaryFactory(0);
 32        }
 33        else
 127534        {
 127535            decoder.IncreaseCollectionAllocation(count * (Unsafe.SizeOf<TKey>() + Unsafe.SizeOf<TValue>()));
 127336            TDictionary dictionary = dictionaryFactory(count);
 1864637            for (int i = 0; i < count; ++i)
 805038            {
 805039                TKey key = keyDecodeFunc(ref decoder);
 805040                TValue value = valueDecodeFunc(ref decoder);
 805041                dictionary.Add(new KeyValuePair<TKey, TValue>(key, value));
 805042            }
 127343            return dictionary;
 44        }
 183845    }
 46
 47    /// <summary>Decodes a dictionary with an optional value type (T? in Slice).</summary>
 48    /// <typeparam name="TDictionary">The type of the returned dictionary.</typeparam>
 49    /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
 50    /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
 51    /// <param name="decoder">The Slice decoder.</param>
 52    /// <param name="dictionaryFactory">The factory for creating the dictionary instance.</param>
 53    /// <param name="keyDecodeFunc">The decode function for each key of the dictionary.</param>
 54    /// <param name="valueDecodeFunc">The decode function for each non-null value of the dictionary.</param>
 55    /// <returns>The dictionary decoded by this decoder.</returns>
 56    public static TDictionary DecodeDictionaryWithOptionalValueType<TDictionary, TKey, TValue>(
 57        this ref SliceDecoder decoder,
 58        Func<int, TDictionary> dictionaryFactory,
 59        DecodeFunc<TKey> keyDecodeFunc,
 60        DecodeFunc<TValue?> valueDecodeFunc)
 61        where TKey : notnull
 62        where TDictionary : ICollection<KeyValuePair<TKey, TValue?>>
 1763    {
 1764        int count = decoder.DecodeSize();
 1765        if (count == 0)
 066        {
 067            return dictionaryFactory(0);
 68        }
 69        else
 1770        {
 1771            decoder.IncreaseCollectionAllocation(count * (Unsafe.SizeOf<TKey>() + Unsafe.SizeOf<TValue?>()));
 1672            TDictionary dictionary = dictionaryFactory(count);
 420873            for (int i = 0; i < count; ++i)
 208874            {
 75                // Each entry is encoded like a:
 76                // compact struct Pair
 77                // {
 78                //     key: Key,
 79                //     value: Value?
 80                // }
 208881                bool hasValue = decoder.DecodeBool(); // simplified bit sequence
 208882                TKey key = keyDecodeFunc(ref decoder);
 208883                TValue? value = hasValue ? valueDecodeFunc(ref decoder) : default;
 208884                dictionary.Add(new KeyValuePair<TKey, TValue?>(key, value));
 208885            }
 1686            return dictionary;
 87        }
 1688    }
 89
 90    /// <summary>Decodes a result.</summary>
 91    /// <typeparam name="TSuccess">The type of the success value.</typeparam>
 92    /// <typeparam name="TFailure">The type of the failure value.</typeparam>
 93    /// <param name="decoder">The Slice decoder.</param>
 94    /// <param name="successDecodeFunc">The decode function for the success type.</param>
 95    /// <param name="failureDecodeFunc">The decode function for the failure type.</param>
 96    /// <returns>The decoded result.</returns>
 97    public static Result<TSuccess, TFailure> DecodeResult<TSuccess, TFailure>(
 98        this ref SliceDecoder decoder,
 99        DecodeFunc<TSuccess> successDecodeFunc,
 100        DecodeFunc<TFailure> failureDecodeFunc) =>
 8101        decoder.DecodeVarInt32() switch
 8102        {
 3103            0 => new Result<TSuccess, TFailure>.Success(successDecodeFunc(ref decoder)),
 5104            1 => new Result<TSuccess, TFailure>.Failure(failureDecodeFunc(ref decoder)),
 0105            int value => throw new InvalidDataException($"Received invalid discriminant value '{value}' for Result.")
 8106        };
 107
 108    /// <summary>Decodes a sequence of fixed-size numeric values.</summary>
 109    /// <typeparam name="T">The sequence element type.</typeparam>
 110    /// <param name="decoder">The Slice decoder.</param>
 111    /// <param name="checkElement">A delegate used to check each element of the array (optional).</param>
 112    /// <returns>An array of T.</returns>
 113    public static T[] DecodeSequence<T>(this ref SliceDecoder decoder, Action<T>? checkElement = null)
 114        where T : struct
 5954115    {
 5954116        int count = decoder.DecodeSize();
 5954117        if (count == 0)
 0118        {
 0119            return Array.Empty<T>();
 120        }
 121        else
 5954122        {
 5954123            int elementSize = Unsafe.SizeOf<T>();
 5954124            decoder.IncreaseCollectionAllocation(count * elementSize);
 5954125            var value = new T[count];
 5954126            Span<byte> destination = MemoryMarshal.Cast<T, byte>(value);
 5954127            decoder.CopyTo(destination);
 128
 5954129            if (checkElement is not null)
 9130            {
 81131                foreach (T e in value)
 28132                {
 28133                    checkElement(e);
 26134                }
 7135            }
 5952136            return value;
 137        }
 5952138    }
 139
 140    /// <summary>Decodes a sequence.</summary>
 141    /// <typeparam name="T">The type of the elements in the array.</typeparam>
 142    /// <param name="decoder">The Slice decoder.</param>
 143    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 144    /// <returns>An array of T.</returns>
 145    public static T[] DecodeSequence<T>(this ref SliceDecoder decoder, DecodeFunc<T> decodeFunc)
 39146    {
 39147        int count = decoder.DecodeSize();
 37148        if (count == 0)
 0149        {
 0150            return Array.Empty<T>();
 151        }
 152        else
 37153        {
 37154            decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<T>());
 37155            var array = new T[count];
 2268156            for (int i = 0; i < count; ++i)
 1097157            {
 1097158                array[i] = decodeFunc(ref decoder);
 1097159            }
 37160            return array;
 161        }
 37162    }
 163
 164    /// <summary>Decodes a sequence.</summary>
 165    /// <typeparam name="TSequence">The type of the returned sequence.</typeparam>
 166    /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
 167    /// <param name="decoder">The Slice decoder.</param>
 168    /// <param name="sequenceFactory">The factory for creating the sequence instance.</param>
 169    /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
 170    /// <returns>A TSequence.</returns>
 171    public static TSequence DecodeSequence<TSequence, TElement>(
 172        this ref SliceDecoder decoder,
 173        Func<int, TSequence> sequenceFactory,
 174        DecodeFunc<TElement> decodeFunc) where TSequence : ICollection<TElement>
 4175    {
 4176        int count = decoder.DecodeSize();
 4177        if (count == 0)
 0178        {
 0179            return sequenceFactory(0);
 180        }
 181        else
 4182        {
 4183            decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<TElement>());
 4184            TSequence sequence = sequenceFactory(count);
 32185            for (int i = 0; i < count; ++i)
 12186            {
 12187                sequence.Add(decodeFunc(ref decoder));
 12188            }
 4189            return sequence;
 190        }
 4191    }
 192
 193    /// <summary>Decodes a sequence where the element type is an optional Slice type (T?).</summary>
 194    /// <typeparam name="T">The type of the elements in the array.</typeparam>
 195    /// <param name="decoder">The Slice decoder.</param>
 196    /// <param name="decodeFunc">The decode function for each non-null element of the sequence.</param>
 197    /// <returns>An array of T.</returns>
 198    /// <remarks>We return a T? and not a T to avoid ambiguities in the generated code with nullable reference
 199    /// types such as string?.</remarks>
 200    public static T?[] DecodeSequenceOfOptionals<T>(this ref SliceDecoder decoder, DecodeFunc<T> decodeFunc)
 17201    {
 17202        int count = decoder.DecodeSize();
 17203        if (count == 0)
 0204        {
 0205            return Array.Empty<T>();
 206        }
 207        else
 17208        {
 17209            BitSequenceReader bitSequenceReader = decoder.GetBitSequenceReader(count);
 17210            decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<T>());
 16211            var array = new T?[count];
 2364212            for (int i = 0; i < count; ++i)
 1166213            {
 1166214                array[i] = bitSequenceReader.Read() ? decodeFunc(ref decoder) : default;
 1166215            }
 16216            return array;
 217        }
 16218    }
 219
 220    /// <summary>Decodes a sequence where the element type is an optional Slice type (T?).</summary>
 221    /// <typeparam name="TSequence">The type of the returned sequence.</typeparam>
 222    /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
 223    /// <param name="decoder">The Slice decoder.</param>
 224    /// <param name="sequenceFactory">The factory for creating the sequence instance.</param>
 225    /// <param name="decodeFunc">The decode function for each non-null element of the sequence.</param>
 226    /// <returns>A TSequence.</returns>
 227    public static TSequence DecodeSequenceOfOptionals<TSequence, TElement>(
 228        this ref SliceDecoder decoder,
 229        Func<int, TSequence> sequenceFactory,
 230        DecodeFunc<TElement> decodeFunc) where TSequence : ICollection<TElement>
 0231    {
 0232        int count = decoder.DecodeSize();
 0233        if (count == 0)
 0234        {
 0235            return sequenceFactory(0);
 236        }
 237        else
 0238        {
 0239            BitSequenceReader bitSequenceReader = decoder.GetBitSequenceReader(count);
 0240            decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<TElement>());
 0241            TSequence sequence = sequenceFactory(count);
 0242            for (int i = 0; i < count; ++i)
 0243            {
 0244                sequence.Add(bitSequenceReader.Read() ? decodeFunc(ref decoder) : default!);
 0245            }
 0246            return sequence;
 247        }
 0248    }
 249}