• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

icerpc / icerpc-csharp / 20870171951

10 Jan 2026 01:03AM UTC coverage: 83.304% (-0.1%) from 83.399%
20870171951

Pull #4221

github

web-flow
Merge fe4f556d8 into f39e9819d
Pull Request #4221: Use new C#14 extension block syntax

12030 of 14441 relevant lines covered (83.3%)

2957.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.58
src/ZeroC.Slice/SliceDecoderExtensions.cs
1
// Copyright (c) ZeroC, Inc.
2

3
using System.Runtime.CompilerServices;
4
using System.Runtime.InteropServices;
5

6
namespace ZeroC.Slice;
7

8
/// <summary>Provides extension methods for <see cref="SliceDecoder" /> to decode sequences or dictionaries.</summary>
9
public static class SliceDecoderExtensions
10
{
11
    /// <summary>Extension methods for <see cref="SliceDecoder" />.</summary>
12
    /// <param name="decoder">The Slice decoder.</param>
13
    extension(ref SliceDecoder decoder)
14
    {
15
        /// <summary>Decodes a dictionary.</summary>
16
        /// <typeparam name="TDictionary">The type of the returned dictionary.</typeparam>
17
        /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
18
        /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
19
        /// <param name="dictionaryFactory">The factory for creating the dictionary instance.</param>
20
        /// <param name="keyDecodeFunc">The decode function for each key of the dictionary.</param>
21
        /// <param name="valueDecodeFunc">The decode function for each value of the dictionary.</param>
22
        /// <returns>The dictionary decoded by this decoder.</returns>
23
        public TDictionary DecodeDictionary<TDictionary, TKey, TValue>(
24
            Func<int, TDictionary> dictionaryFactory,
25
            DecodeFunc<TKey> keyDecodeFunc,
26
            DecodeFunc<TValue> valueDecodeFunc)
27
            where TKey : notnull
28
            where TDictionary : ICollection<KeyValuePair<TKey, TValue>>
29
        {
965✔
30
            int count = decoder.DecodeSize();
965✔
31
            if (count == 0)
963✔
32
            {
296✔
33
                return dictionaryFactory(0);
296✔
34
            }
35
            else
36
            {
667✔
37
                decoder.IncreaseCollectionAllocation(count * (Unsafe.SizeOf<TKey>() + Unsafe.SizeOf<TValue>()));
667✔
38
                TDictionary dictionary = dictionaryFactory(count);
666✔
39
                for (int i = 0; i < count; ++i)
7,524✔
40
                {
3,096✔
41
                    TKey key = keyDecodeFunc(ref decoder);
3,096✔
42
                    TValue value = valueDecodeFunc(ref decoder);
3,096✔
43
                    dictionary.Add(new KeyValuePair<TKey, TValue>(key, value));
3,096✔
44
                }
3,096✔
45
                return dictionary;
666✔
46
            }
47
        }
48

49
        /// <summary>Decodes a dictionary with an optional value type (T? in Slice).</summary>
50
        /// <typeparam name="TDictionary">The type of the returned dictionary.</typeparam>
51
        /// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
52
        /// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
53
        /// <param name="dictionaryFactory">The factory for creating the dictionary instance.</param>
54
        /// <param name="keyDecodeFunc">The decode function for each key of the dictionary.</param>
55
        /// <param name="valueDecodeFunc">The decode function for each non-null value of the dictionary.</param>
56
        /// <returns>The dictionary decoded by this decoder.</returns>
57
        public TDictionary DecodeDictionaryWithOptionalValueType<TDictionary, TKey, TValue>(
58
            Func<int, TDictionary> dictionaryFactory,
59
            DecodeFunc<TKey> keyDecodeFunc,
60
            DecodeFunc<TValue?> valueDecodeFunc)
61
            where TKey : notnull
62
            where TDictionary : ICollection<KeyValuePair<TKey, TValue?>>
63
        {
14✔
64
            int count = decoder.DecodeSize();
14✔
65
            if (count == 0)
14✔
66
            {
×
67
                return dictionaryFactory(0);
×
68
            }
69
            else
70
            {
14✔
71
                decoder.IncreaseCollectionAllocation(count * (Unsafe.SizeOf<TKey>() + Unsafe.SizeOf<TValue?>()));
14✔
72
                TDictionary dictionary = dictionaryFactory(count);
14✔
73
                for (int i = 0; i < count; ++i)
108✔
74
                {
40✔
75
                    // Each entry is encoded like a:
76
                    // compact struct Pair
77
                    // {
78
                    //     key: Key,
79
                    //     value: Value?
80
                    // }
81
                    bool hasValue = decoder.DecodeBool(); // simplified bit sequence
40✔
82
                    TKey key = keyDecodeFunc(ref decoder);
40✔
83
                    TValue? value = hasValue ? valueDecodeFunc(ref decoder) : default;
40✔
84
                    dictionary.Add(new KeyValuePair<TKey, TValue?>(key, value));
40✔
85
                }
40✔
86
                return dictionary;
14✔
87
            }
88
        }
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="successDecodeFunc">The decode function for the success type.</param>
94
        /// <param name="failureDecodeFunc">The decode function for the failure type.</param>
95
        /// <returns>The decoded result.</returns>
96
        public Result<TSuccess, TFailure> DecodeResult<TSuccess, TFailure>(
97
            DecodeFunc<TSuccess> successDecodeFunc,
98
            DecodeFunc<TFailure> failureDecodeFunc) =>
99
            decoder.DecodeVarInt32() switch
4✔
100
            {
4✔
101
                0 => new Result<TSuccess, TFailure>.Success(successDecodeFunc(ref decoder)),
2✔
102
                1 => new Result<TSuccess, TFailure>.Failure(failureDecodeFunc(ref decoder)),
2✔
103
                int value => throw new InvalidDataException(
×
104
                    $"Received invalid discriminant value '{value}' for Result.")
×
105
            };
4✔
106

107
        /// <summary>Decodes a sequence of fixed-size numeric values.</summary>
108
        /// <typeparam name="T">The sequence element type.</typeparam>
109
        /// <param name="checkElement">A delegate used to check each element of the array (optional).</param>
110
        /// <returns>An array of T.</returns>
111
        public T[] DecodeSequence<T>(Action<T>? checkElement = null)
112
            where T : struct
113
        {
3,036✔
114
            int count = decoder.DecodeSize();
3,036✔
115
            if (count == 0)
3,036✔
116
            {
×
117
                return Array.Empty<T>();
×
118
            }
119
            else
120
            {
3,036✔
121
                int elementSize = Unsafe.SizeOf<T>();
3,036✔
122
                decoder.IncreaseCollectionAllocation(count * elementSize);
3,036✔
123
                var value = new T[count];
3,036✔
124
                Span<byte> destination = MemoryMarshal.Cast<T, byte>(value.AsSpan());
3,036✔
125
                decoder.CopyTo(destination);
3,036✔
126

127
                if (checkElement is not null)
3,036✔
128
                {
4✔
129
                    foreach (T e in value)
36✔
130
                    {
12✔
131
                        checkElement(e);
12✔
132
                    }
12✔
133
                }
4✔
134
                return value;
3,036✔
135
            }
136
        }
137

138
        /// <summary>Decodes a sequence.</summary>
139
        /// <typeparam name="T">The type of the elements in the array.</typeparam>
140
        /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
141
        /// <returns>An array of T.</returns>
142
        public T[] DecodeSequence<T>(DecodeFunc<T> decodeFunc)
143
        {
25✔
144
            int count = decoder.DecodeSize();
25✔
145
            if (count == 0)
24✔
146
            {
×
147
                return Array.Empty<T>();
×
148
            }
149
            else
150
            {
24✔
151
                decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<T>());
24✔
152
                var array = new T[count];
24✔
153
                for (int i = 0; i < count; ++i)
150✔
154
                {
51✔
155
                    array[i] = decodeFunc(ref decoder);
51✔
156
                }
51✔
157
                return array;
24✔
158
            }
159
        }
160

161
        /// <summary>Decodes a sequence.</summary>
162
        /// <typeparam name="TSequence">The type of the returned sequence.</typeparam>
163
        /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
164
        /// <param name="sequenceFactory">The factory for creating the sequence instance.</param>
165
        /// <param name="decodeFunc">The decode function for each element of the sequence.</param>
166
        /// <returns>A TSequence.</returns>
167
        public TSequence DecodeSequence<TSequence, TElement>(
168
            Func<int, TSequence> sequenceFactory,
169
            DecodeFunc<TElement> decodeFunc) where TSequence : ICollection<TElement>
170
        {
4✔
171
            int count = decoder.DecodeSize();
4✔
172
            if (count == 0)
4✔
173
            {
×
174
                return sequenceFactory(0);
×
175
            }
176
            else
177
            {
4✔
178
                decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<TElement>());
4✔
179
                TSequence sequence = sequenceFactory(count);
4✔
180
                for (int i = 0; i < count; ++i)
32✔
181
                {
12✔
182
                    sequence.Add(decodeFunc(ref decoder));
12✔
183
                }
12✔
184
                return sequence;
4✔
185
            }
186
        }
187

188
        /// <summary>Decodes a sequence where the element type is an optional Slice type (T?).</summary>
189
        /// <typeparam name="T">The type of the elements in the array.</typeparam>
190
        /// <param name="decodeFunc">The decode function for each non-null element of the sequence.</param>
191
        /// <returns>An array of T.</returns>
192
        /// <remarks>We return a T? and not a T to avoid ambiguities in the generated code with nullable reference
193
        /// types such as string?.</remarks>
194
        public T?[] DecodeSequenceOfOptionals<T>(DecodeFunc<T> decodeFunc)
195
        {
14✔
196
            int count = decoder.DecodeSize();
14✔
197
            if (count == 0)
14✔
198
            {
×
199
                return Array.Empty<T>();
×
200
            }
201
            else
202
            {
14✔
203
                BitSequenceReader bitSequenceReader = decoder.GetBitSequenceReader(count);
14✔
204
                decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<T>());
14✔
205
                var array = new T?[count];
14✔
206
                for (int i = 0; i < count; ++i)
112✔
207
                {
42✔
208
                    array[i] = bitSequenceReader.Read() ? decodeFunc(ref decoder) : default;
42✔
209
                }
42✔
210
                return array;
14✔
211
            }
212
        }
213

214
        /// <summary>Decodes a sequence where the element type is an optional Slice type (T?).</summary>
215
        /// <typeparam name="TSequence">The type of the returned sequence.</typeparam>
216
        /// <typeparam name="TElement">The type of the elements in the sequence.</typeparam>
217
        /// <param name="sequenceFactory">The factory for creating the sequence instance.</param>
218
        /// <param name="decodeFunc">The decode function for each non-null element of the sequence.</param>
219
        /// <returns>A TSequence.</returns>
220
        public TSequence DecodeSequenceOfOptionals<TSequence, TElement>(
221
            Func<int, TSequence> sequenceFactory,
222
            DecodeFunc<TElement> decodeFunc) where TSequence : ICollection<TElement>
223
        {
×
224
            int count = decoder.DecodeSize();
×
225
            if (count == 0)
×
226
            {
×
227
                return sequenceFactory(0);
×
228
            }
229
            else
230
            {
×
231
                BitSequenceReader bitSequenceReader = decoder.GetBitSequenceReader(count);
×
232
                decoder.IncreaseCollectionAllocation(count * Unsafe.SizeOf<TElement>());
×
233
                TSequence sequence = sequenceFactory(count);
×
234
                for (int i = 0; i < count; ++i)
×
235
                {
×
236
                    sequence.Add(bitSequenceReader.Read() ? decodeFunc(ref decoder) : default!);
×
237
                }
×
238
                return sequence;
×
239
            }
240
        }
241
    }
242
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc