Skip to content

Commit a219eb0

Browse files
authored
Merge pull request #18 from progaudi/v3.1.0
## 3.1.0 Opening some extensions methods to public (2019-01-13) #### Features * **ReadOnlySequence:** * GetIntLength tests ([00327ef](00327ef)) * TryFillSpan method interface and tests ([e6c14ce](e6c14ce)) * GetFirst interface and tests. ([f73de91](f73de91)) * make some methods public ([7ef3b6c](7ef3b6c))
2 parents c51f82c + 00327ef commit a219eb0

29 files changed

+391
-104
lines changed

src/msgpack.spec/MsgPackSpec.Array.ReadOnlySequence.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public static ushort ReadArray16Header(ReadOnlySequence<byte> sequence, out int
7474

7575
readSize = length;
7676
Span<byte> buffer = stackalloc byte[length];
77-
if (!sequence.TryRead(buffer))
77+
if (!sequence.TryFillSpan(buffer))
7878
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
7979

8080
var code = buffer[0];
@@ -105,7 +105,7 @@ public static bool TryReadArray16Header(ReadOnlySequence<byte> sequence, out ush
105105
readSize = size;
106106
length = 0;
107107
Span<byte> buffer = stackalloc byte[size];
108-
return sequence.TryRead(buffer) && buffer[0] == Array16 && BinaryPrimitives.TryReadUInt16BigEndian(buffer.Slice(1), out length);
108+
return sequence.TryFillSpan(buffer) && buffer[0] == Array16 && BinaryPrimitives.TryReadUInt16BigEndian(buffer.Slice(1), out length);
109109
}
110110

111111
/// <summary>
@@ -122,7 +122,7 @@ public static uint ReadArray32Header(ReadOnlySequence<byte> sequence, out int re
122122

123123
readSize = length;
124124
Span<byte> buffer = stackalloc byte[length];
125-
if (!sequence.TryRead(buffer))
125+
if (!sequence.TryFillSpan(buffer))
126126
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
127127

128128
var code = buffer[0];
@@ -153,7 +153,7 @@ public static bool TryReadArray32Header(ReadOnlySequence<byte> sequence, out uin
153153
readSize = size;
154154
length = 0;
155155
Span<byte> buffer = stackalloc byte[size];
156-
return sequence.TryRead(buffer) && buffer[0] == Array32 && BinaryPrimitives.TryReadUInt32BigEndian(buffer.Slice(1), out length);
156+
return sequence.TryFillSpan(buffer) && buffer[0] == Array32 && BinaryPrimitives.TryReadUInt32BigEndian(buffer.Slice(1), out length);
157157
}
158158

159159
/// <summary>

src/msgpack.spec/MsgPackSpec.Binary.ReadOnlySequence.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static byte ReadBinary8Header(ReadOnlySequence<byte> sequence, out int re
2727

2828
readSize = length;
2929
Span<byte> buffer = stackalloc byte[length];
30-
if (!sequence.TryRead(buffer))
30+
if (!sequence.TryFillSpan(buffer))
3131
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
3232

3333
var code = buffer[0];
@@ -58,7 +58,7 @@ public static bool TryReadBinary8Header(ReadOnlySequence<byte> sequence, out byt
5858
readSize = size;
5959
length = 0;
6060
Span<byte> buffer = stackalloc byte[size];
61-
if (!sequence.TryRead(buffer) || buffer[0] != DataCodes.Binary8) return false;
61+
if (!sequence.TryFillSpan(buffer) || buffer[0] != DataCodes.Binary8) return false;
6262
length = buffer[1];
6363
return true;
6464
}
@@ -78,7 +78,7 @@ public static ushort ReadBinary16Header(ReadOnlySequence<byte> sequence, out int
7878

7979
readSize = length;
8080
Span<byte> buffer = stackalloc byte[length];
81-
if (!sequence.TryRead(buffer))
81+
if (!sequence.TryFillSpan(buffer))
8282
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
8383

8484
var code = buffer[0];
@@ -109,7 +109,7 @@ public static bool TryReadBinary16Header(ReadOnlySequence<byte> sequence, out us
109109
readSize = size;
110110
length = 0;
111111
Span<byte> buffer = stackalloc byte[size];
112-
return sequence.TryRead(buffer) && buffer[0] == DataCodes.Binary16 && BinaryPrimitives.TryReadUInt16BigEndian(buffer.Slice(1), out length);
112+
return sequence.TryFillSpan(buffer) && buffer[0] == DataCodes.Binary16 && BinaryPrimitives.TryReadUInt16BigEndian(buffer.Slice(1), out length);
113113
}
114114

115115
/// <summary>
@@ -127,7 +127,7 @@ public static uint ReadBinary32Header(ReadOnlySequence<byte> sequence, out int r
127127

128128
readSize = length;
129129
Span<byte> buffer = stackalloc byte[length];
130-
if (!sequence.TryRead(buffer))
130+
if (!sequence.TryFillSpan(buffer))
131131
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
132132

133133
var code = buffer[0];
@@ -158,7 +158,7 @@ public static bool TryReadBinary32Header(ReadOnlySequence<byte> sequence, out ui
158158
readSize = size;
159159
length = 0;
160160
Span<byte> buffer = stackalloc byte[size];
161-
return sequence.TryRead(buffer) && buffer[0] == DataCodes.Binary32 && BinaryPrimitives.TryReadUInt32BigEndian(buffer.Slice(1), out length);
161+
return sequence.TryFillSpan(buffer) && buffer[0] == DataCodes.Binary32 && BinaryPrimitives.TryReadUInt32BigEndian(buffer.Slice(1), out length);
162162
}
163163

164164
/// <summary>

src/msgpack.spec/MsgPackSpec.Boolean.ReadOnlySequence.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static bool ReadBoolean(ReadOnlySequence<byte> sequence, out int readSize
2222
return ReadBoolean(sequence.First.Span, out readSize);
2323

2424
Span<byte> buffer = stackalloc byte[length];
25-
return sequence.TryRead(buffer)
25+
return sequence.TryFillSpan(buffer)
2626
? ReadBoolean(buffer, out readSize)
2727
: throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
2828
}
@@ -45,7 +45,7 @@ public static bool TryReadBoolean(ReadOnlySequence<byte> sequence, out bool valu
4545
readSize = default;
4646

4747
Span<byte> buffer = stackalloc byte[length];
48-
return sequence.TryRead(buffer) && TryReadBoolean(buffer, out value, out readSize);
48+
return sequence.TryFillSpan(buffer) && TryReadBoolean(buffer, out value, out readSize);
4949
}
5050
}
5151
}

src/msgpack.spec/MsgPackSpec.Double.ReadOnlySequence.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static double ReadFixFloat64(ReadOnlySequence<byte> sequence, out int rea
2222
return ReadFixFloat64(sequence.First.Span, out readSize);
2323

2424
Span<byte> buffer = stackalloc byte[length];
25-
return sequence.TryRead(buffer)
25+
return sequence.TryFillSpan(buffer)
2626
? ReadFixFloat64(buffer, out readSize)
2727
: throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
2828
}
@@ -45,7 +45,7 @@ public static bool TryReadFixFloat64(ReadOnlySequence<byte> sequence, out double
4545
readSize = default;
4646

4747
Span<byte> buffer = stackalloc byte[length];
48-
return sequence.TryRead(buffer)
48+
return sequence.TryFillSpan(buffer)
4949
&& TryReadFixFloat64(buffer, out value, out readSize);
5050
}
5151

src/msgpack.spec/MsgPackSpec.Exceptions.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,8 @@ namespace ProGaudi.MsgPack
1313
[PublicAPI]
1414
public static partial class MsgPackSpec
1515
{
16-
private static Exception GetReadOnlySequenceIsTooShortException(int expected, long sequenceLength) => new ArgumentOutOfRangeException(
17-
nameof(sequenceLength),
18-
sequenceLength,
19-
$"ReadOnlySequence is too short. Expected: {expected}"
16+
private static Exception GetReadOnlySequenceIsTooShortException(int expected, long sequenceLength) => new IndexOutOfRangeException(
17+
$"ReadOnlySequence is too short. Expected: {expected}, actual length: {sequenceLength}"
2018
);
2119

2220
private static Exception GetInvalidStringException() => new InvalidOperationException(

src/msgpack.spec/MsgPackSpec.Extension.ReadOnlySequence.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public static (sbyte type, byte extension) ReadFixExtension1(ReadOnlySequence<by
3636

3737
readSize = length;
3838
Span<byte> buffer = stackalloc byte[length];
39-
if (!sequence.TryRead(buffer))
39+
if (!sequence.TryFillSpan(buffer))
4040
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
4141

4242
return (ReadFixExtension1Header(buffer, out _), buffer[2]);
@@ -145,7 +145,7 @@ public static (sbyte type, byte length) ReadExtension8Header(ReadOnlySequence<by
145145

146146
readSize = length;
147147
Span<byte> buffer = stackalloc byte[length];
148-
if (!sequence.TryRead(buffer))
148+
if (!sequence.TryFillSpan(buffer))
149149
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
150150

151151
var type = unchecked((sbyte)buffer[2]);
@@ -181,7 +181,7 @@ public static (sbyte type, ushort length) ReadExtension16Header(ReadOnlySequence
181181

182182
readSize = length;
183183
Span<byte> buffer = stackalloc byte[length];
184-
if (!sequence.TryRead(buffer))
184+
if (!sequence.TryFillSpan(buffer))
185185
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
186186

187187
var type = unchecked((sbyte)buffer[3]);
@@ -216,7 +216,7 @@ public static (sbyte type, uint length) ReadExtension32Header(ReadOnlySequence<b
216216

217217
readSize = length;
218218
Span<byte> buffer = stackalloc byte[length];
219-
if (!sequence.TryRead(buffer))
219+
if (!sequence.TryFillSpan(buffer))
220220
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
221221

222222
var type = unchecked((sbyte)buffer[5]);
@@ -329,7 +329,7 @@ public static bool TryReadFixExtension1(ReadOnlySequence<byte> sequence, out sby
329329

330330
readSize = length;
331331
Span<byte> buffer = stackalloc byte[length];
332-
if (sequence.TryRead(buffer) && TryReadFixExtension1Header(sequence, out type, out readSize))
332+
if (sequence.TryFillSpan(buffer) && TryReadFixExtension1Header(sequence, out type, out readSize))
333333
{
334334
extension = buffer[2];
335335
return true;
@@ -454,7 +454,7 @@ public static bool TryReadExtension8Header(ReadOnlySequence<byte> sequence, out
454454
type = default;
455455
readSize = size;
456456
Span<byte> buffer = stackalloc byte[size];
457-
return sequence.TryRead(buffer) && TryReadExtension8Header(buffer, out type, out length, out readSize);
457+
return sequence.TryFillSpan(buffer) && TryReadExtension8Header(buffer, out type, out length, out readSize);
458458
}
459459

460460
/// <summary>
@@ -490,7 +490,7 @@ public static bool TryReadExtension16Header(ReadOnlySequence<byte> sequence, out
490490
type = default;
491491
readSize = size;
492492
Span<byte> buffer = stackalloc byte[size];
493-
return sequence.TryRead(buffer) && TryReadExtension16Header(buffer, out type, out length, out readSize);
493+
return sequence.TryFillSpan(buffer) && TryReadExtension16Header(buffer, out type, out length, out readSize);
494494
}
495495

496496
/// <summary>
@@ -526,7 +526,7 @@ public static bool TryReadExtension32Header(ReadOnlySequence<byte> sequence, out
526526
type = default;
527527
readSize = size;
528528
Span<byte> buffer = stackalloc byte[size];
529-
return sequence.TryRead(buffer) && TryReadExtension32Header(buffer, out type, out length, out readSize);
529+
return sequence.TryFillSpan(buffer) && TryReadExtension32Header(buffer, out type, out length, out readSize);
530530
}
531531

532532
/// <summary>
@@ -642,7 +642,7 @@ private static bool TryReadFixExtensionHeader(ReadOnlySequence<byte> sequence, b
642642
const int length = DataLengths.FixExtensionHeader;
643643
readSize = length;
644644
Span<byte> buffer = stackalloc byte[length];
645-
if (sequence.TryRead(buffer)) return false;
645+
if (sequence.TryFillSpan(buffer)) return false;
646646
if (buffer[0] != code) return false;
647647
type = unchecked((sbyte)buffer[1]);
648648
return true;
@@ -670,7 +670,7 @@ private static sbyte ReadFixExtensionHeader(ReadOnlySequence<byte> sequence, byt
670670

671671
readSize = length;
672672
Span<byte> buffer = stackalloc byte[length];
673-
if (!sequence.TryRead(buffer))
673+
if (!sequence.TryFillSpan(buffer))
674674
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
675675

676676
var type = unchecked((sbyte)buffer[1]);

src/msgpack.spec/MsgPackSpec.Extension.Timestamp.ReadOnlySequence.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public static Timestamp ReadTimestamp32(ReadOnlySequence<byte> sequence, out int
2323

2424
readSize = length;
2525
Span<byte> buffer = stackalloc byte[length];
26-
if (!sequence.TryRead(buffer))
26+
if (!sequence.TryFillSpan(buffer))
2727
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
2828

2929
var extension = ReadFixExtension4Header(buffer, out var headerSize);
@@ -45,7 +45,7 @@ public static Timestamp ReadTimestamp64(ReadOnlySequence<byte> sequence, out int
4545

4646
readSize = length;
4747
Span<byte> buffer = stackalloc byte[length];
48-
if (!sequence.TryRead(buffer))
48+
if (!sequence.TryFillSpan(buffer))
4949
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
5050

5151
var extension = ReadFixExtension8Header(buffer, out var headerSize);
@@ -67,7 +67,7 @@ public static Timestamp ReadTimestamp96(ReadOnlySequence<byte> sequence, out int
6767

6868
readSize = length;
6969
Span<byte> buffer = stackalloc byte[length];
70-
if (!sequence.TryRead(buffer))
70+
if (!sequence.TryFillSpan(buffer))
7171
throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
7272

7373
var (extension, exLength) = ReadExtension8Header(buffer, out var headerSize);
@@ -127,7 +127,7 @@ public static bool TryReadTimestamp32(ReadOnlySequence<byte> sequence, out Times
127127
readSize = length;
128128
timestamp = Timestamp.Zero;
129129
Span<byte> buffer = stackalloc byte[length];
130-
if (!sequence.TryRead(buffer)) return false;
130+
if (!sequence.TryFillSpan(buffer)) return false;
131131

132132
if (!TryReadFixExtension4Header(buffer, out var extension, out var headerSize)) return false;
133133
if (extension != ExtensionTypes.Timestamp) return false;
@@ -158,7 +158,7 @@ public static bool TryReadTimestamp64(ReadOnlySequence<byte> sequence, out Times
158158
readSize = length;
159159
timestamp = Timestamp.Zero;
160160
Span<byte> buffer = stackalloc byte[length];
161-
if (!sequence.TryRead(buffer)) return false;
161+
if (!sequence.TryFillSpan(buffer)) return false;
162162

163163
if (!TryReadFixExtension8Header(buffer, out var extension, out var headerSize)) return false;
164164
if (extension != ExtensionTypes.Timestamp) return false;
@@ -189,7 +189,7 @@ public static bool TryReadTimestamp96(ReadOnlySequence<byte> sequence, out Times
189189
readSize = length;
190190
timestamp = Timestamp.Zero;
191191
Span<byte> buffer = stackalloc byte[length];
192-
if (!sequence.TryRead(buffer)) return false;
192+
if (!sequence.TryFillSpan(buffer)) return false;
193193

194194
if (!TryReadExtension8Header(sequence, out var extension, out var exLength, out var headerSize)) return false;
195195
if (extension != ExtensionTypes.Timestamp) return false;

src/msgpack.spec/MsgPackSpec.ExtensionMethods.cs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,66 @@ namespace ProGaudi.MsgPack
77
{
88
public static partial class MsgPackSpec
99
{
10-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
11-
private static T GetFirst<T>(this ReadOnlySequence<T> ros)
10+
/// <summary>
11+
/// Returns first element of <paramref name="ros"/> or throws.
12+
/// Takes possible empty segments into account.
13+
/// Has shortcut for sequences from single-element.
14+
/// </summary>
15+
/// <param name="ros">Sequence</param>
16+
/// <typeparam name="T">Type of elements</typeparam>
17+
/// <returns>First element of sequence.</returns>
18+
/// <exception cref="IndexOutOfRangeException">Thrown when <paramref name="ros"/> is empty</exception>
19+
/// <exception cref="InvalidOperationException">When <see cref="ReadOnlySequence{T}.IsEmpty"/> is <c>false</c>, but sequence is still empty.</exception>
20+
public static T GetFirst<T>(this ReadOnlySequence<T> ros)
1221
{
22+
if (ros.IsEmpty) throw GetReadOnlySequenceIsTooShortException(1, 0);
1323
if (ros.IsSingleSegment) return ros.First.Span[0];
14-
if (!ros.IsEmpty)
24+
25+
foreach (var memory in ros)
1526
{
16-
foreach (var memory in ros)
17-
{
18-
if (!memory.IsEmpty)
19-
return memory.Span[0];
20-
}
27+
if (!memory.IsEmpty)
28+
return memory.Span[0];
2129
}
2230

23-
throw GetReadOnlySequenceIsTooShortException(1, 0);
31+
throw new InvalidOperationException("We should never get here, because it means that non-empty sequence is empty.");
2432
}
2533

26-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
27-
private static bool TryRead<T>(this ReadOnlySequence<T> ros, Span<T> destination)
34+
/// <summary>
35+
/// Tries to fill <paramref name="destination"/> by data from <paramref name="ros"/>. Takes nature of <see cref="ReadOnlySequence{T}"/>
36+
/// into account. Does not check <see cref="ReadOnlySequence{T}.Length"/>, because it enumerates sequence.
37+
/// </summary>
38+
/// <param name="ros">Sequence of elements</param>
39+
/// <param name="destination">Span to copy data to.</param>
40+
/// <typeparam name="T">Type of element</typeparam>
41+
/// <returns><c>true</c> if span is fully filled, <c>false</c> otherwise.</returns>
42+
public static bool TryFillSpan<T>(this ReadOnlySequence<T> ros, Span<T> destination)
2843
{
29-
if (destination.Length == 0) return true;
30-
var index = 0;
44+
if (destination.IsEmpty) return true;
45+
46+
var span = destination;
3147
foreach (var memory in ros)
3248
{
33-
for (var i = 0; i < memory.Length; i++)
49+
var source = memory.Length > span.Length
50+
? memory.Span.Slice(0, span.Length)
51+
: memory.Span;
52+
source.CopyTo(span);
53+
span = span.Slice(source.Length);
54+
if (span.IsEmpty)
3455
{
35-
destination[index++] = memory.Span[i];
36-
if (index == destination.Length)
37-
return true;
56+
return true;
3857
}
3958
}
4059

4160
return false;
4261
}
4362

63+
/// <summary>
64+
/// Returns <see cref="int"/> length of <paramref name="ros"/>.
65+
/// </summary>
66+
/// <returns>Casted length</returns>
67+
/// <exception cref="InvalidOperationException">Thrown if length of <paramref name="ros"/> is larger than <see cref="int.MaxValue"/></exception>
4468
[MethodImpl(MethodImplOptions.AggressiveInlining)]
45-
private static int GetIntLength<T>(this ReadOnlySequence<T> ros)
69+
public static int GetIntLength<T>(this ReadOnlySequence<T> ros)
4670
{
4771
var length = ros.Length;
4872
if (length > int.MaxValue)

src/msgpack.spec/MsgPackSpec.Float.ReadOnlySequence.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public static float ReadFixFloat32(ReadOnlySequence<byte> sequence, out int read
2222
return ReadFixFloat32(sequence.First.Span, out readSize);
2323

2424
Span<byte> buffer = stackalloc byte[length];
25-
return sequence.TryRead(buffer)
25+
return sequence.TryFillSpan(buffer)
2626
? ReadFixFloat32(buffer, out readSize)
2727
: throw GetReadOnlySequenceIsTooShortException(length, sequence.Length);
2828
}
@@ -45,7 +45,7 @@ public static bool TryReadFixFloat32(ReadOnlySequence<byte> sequence, out float
4545
readSize = default;
4646

4747
Span<byte> buffer = stackalloc byte[length];
48-
return sequence.TryRead(buffer) && TryReadFixFloat32(buffer, out value, out readSize);
48+
return sequence.TryFillSpan(buffer) && TryReadFixFloat32(buffer, out value, out readSize);
4949
}
5050

5151
/// <summary>

0 commit comments

Comments
 (0)