< Summary

Information
Class: ZeroC.Slice.Codec.SliceEncoderExtensions
Assembly: ZeroC.Slice.Codec
File(s): /home/runner/work/icerpc-csharp/icerpc-csharp/src/ZeroC.Slice.Codec/SliceEncoderExtensions.cs
Tag: 1321_24790053727
Line coverage
76%
Covered lines: 89
Uncovered lines: 28
Coverable lines: 117
Total lines: 237
Line coverage: 76%
Branch coverage
80%
Covered branches: 37
Total branches: 46
Branch coverage: 80.4%
Method coverage
100%
Covered methods: 8
Fully covered methods: 2
Total methods: 8
Method coverage: 100%
Full method coverage: 25%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
EncodeDictionary(...)75%5464.28%
EncodeDictionaryWithOptionalValueType(...)87.5%9876.19%
EncodeResult(...)75%4481.81%
EncodeSequence(...)90%101086.66%
EncodeSequence(...)75%5461.53%
EncodeSequenceOfOptionals(...)87.5%9876.19%
EncodeSpan(...)100%22100%
WriteByteSequence(...)50%8660%

File(s)

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

#LineLine coverage
 1// Copyright (c) ZeroC, Inc.
 2
 3using System.Buffers;
 4using System.Collections.Immutable;
 5using System.Diagnostics;
 6using System.Runtime.InteropServices;
 7
 8namespace ZeroC.Slice.Codec;
 9
 10/// <summary>Provides extension methods for <see cref="SliceEncoder" /> to encode dictionaries, results, and sequences.
 11/// </summary>
 12public static class SliceEncoderExtensions
 13{
 14    /// <summary>Encodes a dictionary.</summary>
 15    /// <typeparam name="TKey">The dictionary key type.</typeparam>
 16    /// <typeparam name="TValue">The dictionary value type.</typeparam>
 17    /// <param name="encoder">The Slice encoder.</param>
 18    /// <param name="v">The dictionary to encode.</param>
 19    /// <param name="keyEncodeAction">The encode action for the keys.</param>
 20    /// <param name="valueEncodeAction">The encode action for the values.</param>
 21    public static void EncodeDictionary<TKey, TValue>(
 22        this ref SliceEncoder encoder,
 23        IEnumerable<KeyValuePair<TKey, TValue>> v,
 24        EncodeAction<TKey> keyEncodeAction,
 25        EncodeAction<TValue> valueEncodeAction)
 26        where TKey : notnull
 288427    {
 288428        if (!v.TryGetNonEnumeratedCount(out int count))
 029        {
 030            KeyValuePair<TKey, TValue>[] array = v.ToArray();
 031            count = array.Length;
 032            v = array;
 033        }
 288434        encoder.EncodeSize(count);
 1803335        foreach ((TKey key, TValue value) in v)
 469136        {
 469137            keyEncodeAction(ref encoder, key);
 469138            valueEncodeAction(ref encoder, value);
 469039        }
 288340    }
 41
 42    /// <summary>Encodes a dictionary with an optional value type (T? in Slice).</summary>
 43    /// <typeparam name="TKey">The dictionary key type.</typeparam>
 44    /// <typeparam name="TValue">The dictionary value type.</typeparam>
 45    /// <param name="encoder">The Slice encoder.</param>
 46    /// <param name="v">The dictionary to encode.</param>
 47    /// <param name="keyEncodeAction">The encode action for the keys.</param>
 48    /// <param name="valueEncodeAction">The encode action for the non-null values.</param>
 49    public static void EncodeDictionaryWithOptionalValueType<TKey, TValue>(
 50        this ref SliceEncoder encoder,
 51        IEnumerable<KeyValuePair<TKey, TValue>> v,
 52        EncodeAction<TKey> keyEncodeAction,
 53        EncodeAction<TValue> valueEncodeAction)
 54        where TKey : notnull
 1755    {
 1756        if (!v.TryGetNonEnumeratedCount(out int count))
 057        {
 058            KeyValuePair<TKey, TValue>[] array = v.ToArray();
 059            count = array.Length;
 060            v = array;
 061        }
 1762        encoder.EncodeSize(count);
 1763        if (count > 0)
 1764        {
 627565            foreach ((TKey key, TValue value) in v)
 311266            {
 67                // Each entry is encoded like a:
 68                // compact struct Pair
 69                // {
 70                //     key: Key,
 71                //     value: Value?
 72                // }
 311273                encoder.EncodeBool(value is not null); // simplified bit sequence
 74
 311275                keyEncodeAction(ref encoder, key);
 311276                if (value is not null)
 53877                {
 53878                    valueEncodeAction(ref encoder, value);
 53879                }
 311280            }
 1781        }
 1782    }
 83
 84    /// <summary>Encodes a result.</summary>
 85    /// <typeparam name="TSuccess">The type of the success value.</typeparam>
 86    /// <typeparam name="TFailure">The type of the failure value.</typeparam>
 87    /// <param name="encoder">The Slice encoder.</param>
 88    /// <param name="v">The result to encode.</param>
 89    /// <param name="successEncodeAction">The encode action for the success type.</param>
 90    /// <param name="failureEncodeAction">The encode action for the failure type.</param>
 91    public static void EncodeResult<TSuccess, TFailure>(
 92        this ref SliceEncoder encoder,
 93        Result<TSuccess, TFailure> v,
 94        EncodeAction<TSuccess> successEncodeAction,
 95        EncodeAction<TFailure> failureEncodeAction)
 496    {
 497        switch (v)
 98        {
 99            case Result<TSuccess, TFailure>.Success success:
 2100                encoder.EncodeVarInt32(0);
 2101                successEncodeAction(ref encoder, success.Value);
 2102                break;
 103
 104            case Result<TSuccess, TFailure>.Failure failure:
 2105                encoder.EncodeVarInt32(1);
 2106                failureEncodeAction(ref encoder, failure.Value);
 2107                break;
 108
 109            default:
 110                // Our result type somehow got extended with an additional enumerator.
 0111                Debug.Fail("Unexpected result type");
 0112                break;
 113        }
 4114    }
 115
 116    /// <summary>Encodes a sequence of fixed-size numeric values, such as int or ulong.</summary>
 117    /// <typeparam name="T">The sequence element type.</typeparam>
 118    /// <param name="encoder">The Slice encoder.</param>
 119    /// <param name="v">The sequence of numeric values.</param>
 120    public static void EncodeSequence<T>(this ref SliceEncoder encoder, IEnumerable<T> v)
 121        where T : struct
 3278122    {
 3278123        switch (v)
 124        {
 125            case T[] vArray:
 3269126                encoder.EncodeSpan(new ReadOnlySpan<T>(vArray));
 3269127                break;
 128
 129            case ImmutableArray<T> vImmutableArray:
 2130                encoder.EncodeSpan(vImmutableArray.AsSpan());
 2131                break;
 132
 133            case ArraySegment<T> vArraySegment:
 2134                encoder.EncodeSpan((ReadOnlySpan<T>)vArraySegment.AsSpan());
 2135                break;
 136
 137            case List<T> list:
 1138                encoder.EncodeSpan((ReadOnlySpan<T>)CollectionsMarshal.AsSpan(list));
 1139                break;
 140
 141            default:
 4142                encoder.EncodeSequence(
 4143                    v,
 269144                    (ref SliceEncoder encoder, T element) => encoder.EncodeFixedSizeNumeric(element));
 4145                break;
 146        }
 3278147    }
 148
 149    /// <summary>Encodes a sequence.</summary>
 150    /// <typeparam name="T">The type of the sequence elements.</typeparam>
 151    /// <param name="encoder">The Slice encoder.</param>
 152    /// <param name="v">The sequence to encode.</param>
 153    /// <param name="encodeAction">The encode action for an element.</param>
 154    public static void EncodeSequence<T>(this ref SliceEncoder encoder, IEnumerable<T> v, EncodeAction<T> encodeAction)
 155        where T : notnull
 45156    {
 45157        if (!v.TryGetNonEnumeratedCount(out int count))
 0158        {
 0159            T[] array = v.ToArray();
 0160            count = array.Length;
 0161            v = array;
 0162        }
 45163        encoder.EncodeSize(count);
 7717164        foreach (T item in v)
 3791165        {
 3791166            encodeAction(ref encoder, item);
 3791167        }
 45168    }
 169
 170    /// <summary>Encodes a sequence where the element type is an optional Slice type (T?).</summary>
 171    /// <typeparam name="T">The nullable type of the sequence elements.</typeparam>
 172    /// <param name="encoder">The Slice encoder.</param>
 173    /// <param name="v">The sequence to encode.</param>
 174    /// <param name="encodeAction">The encode action for a non-null value.</param>
 175    /// <remarks>This method always encodes a bit sequence.</remarks>
 176    public static void EncodeSequenceOfOptionals<T>(
 177        this ref SliceEncoder encoder,
 178        IEnumerable<T> v,
 179        EncodeAction<T> encodeAction)
 22180    {
 22181        if (!v.TryGetNonEnumeratedCount(out int count))
 0182        {
 0183            T[] array = v.ToArray();
 0184            count = array.Length;
 0185            v = array;
 0186        }
 22187        encoder.EncodeSize(count);
 22188        if (count > 0)
 22189        {
 22190            BitSequenceWriter bitSequenceWriter = encoder.GetBitSequenceWriter(count);
 2844191            foreach (T item in v)
 1389192            {
 1389193                bitSequenceWriter.Write(item is not null);
 1389194                if (item is not null)
 542195                {
 542196                    encodeAction(ref encoder, item);
 542197                }
 1389198            }
 22199        }
 22200    }
 201
 202    /// <summary>Encodes a span of fixed-size numeric values, such as int or ulong.</summary>
 203    /// <typeparam name="T">The span element type.</typeparam>
 204    /// <param name="encoder">The Slice encoder.</param>
 205    /// <param name="v">The span of numeric values represented by a <see cref="ReadOnlySpan{T}" />.</param>
 206    public static void EncodeSpan<T>(this ref SliceEncoder encoder, ReadOnlySpan<T> v)
 207        where T : struct
 3291208    {
 209        // This method works because (as long as) there is no padding in the memory representation of the ReadOnlySpan.
 3291210        encoder.EncodeSize(v.Length);
 3291211        if (!v.IsEmpty)
 3287212        {
 3287213            encoder.WriteByteSpan(MemoryMarshal.AsBytes(v));
 3287214        }
 3291215    }
 216
 217    /// <summary>Copies a sequence of bytes to the underlying buffer writer.</summary>
 218    /// <param name="encoder">The Slice encoder.</param>
 219    /// <param name="v">The sequence to copy.</param>
 220    public static void WriteByteSequence(this ref SliceEncoder encoder, ReadOnlySequence<byte> v)
 10221    {
 10222        if (!v.IsEmpty)
 5223        {
 5224            if (v.IsSingleSegment)
 5225            {
 5226                encoder.WriteByteSpan(v.FirstSpan);
 5227            }
 228            else
 0229            {
 0230                foreach (ReadOnlyMemory<byte> buffer in v)
 0231                {
 0232                    encoder.WriteByteSpan(buffer.Span);
 0233                }
 0234            }
 5235        }
 10236    }
 237}