Skip to content

Commit f73de91

Browse files
committed
feat(ReadOnlySequence): GetFirst interface and tests.
1 parent 7d94b03 commit f73de91

File tree

4 files changed

+89
-13
lines changed

4 files changed

+89
-13
lines changed

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.ExtensionMethods.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ public static partial class MsgPackSpec
1515
/// <param name="ros">Sequence</param>
1616
/// <typeparam name="T">Type of elements</typeparam>
1717
/// <returns>First element of sequence.</returns>
18-
/// <exception cref="ArgumentOutOfRangeException">Thrown when <paramref name="ros"/> is empty</exception>
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>
1920
public static T GetFirst<T>(this ReadOnlySequence<T> ros)
2021
{
22+
if (ros.IsEmpty) throw GetReadOnlySequenceIsTooShortException(1, 0);
2123
if (ros.IsSingleSegment) return ros.First.Span[0];
22-
if (!ros.IsEmpty)
24+
25+
foreach (var memory in ros)
2326
{
24-
foreach (var memory in ros)
25-
{
26-
if (!memory.IsEmpty)
27-
return memory.Span[0];
28-
}
27+
if (!memory.IsEmpty)
28+
return memory.Span[0];
2929
}
3030

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

3434
/// <summary>
@@ -43,7 +43,7 @@ public static bool TryFillSpan<T>(this ReadOnlySequence<T> ros, Span<T> destinat
4343
{
4444
if (destination.IsEmpty) return true;
4545
if (ros.IsSingleSegment) return ros.First.Span.TryCopyTo(destination);
46-
46+
4747
var span = destination;
4848
foreach (var memory in ros)
4949
{
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using Shouldly;
3+
using Xunit;
4+
5+
namespace ProGaudi.MsgPack.Tests.ReadOnlySequence.MultipleSegments
6+
{
7+
public class PublicExtensions
8+
{
9+
[Theory]
10+
[InlineData(new byte[] {1})]
11+
[InlineData(new byte[] {byte.MaxValue, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})]
12+
public void GetFirstByteNonEmpty(byte[] data)
13+
{
14+
data.ToMultipleSegments().GetFirst().ShouldBe(data[0]);
15+
}
16+
17+
[Fact]
18+
public void GetFirstByteEmpty()
19+
{
20+
var e = Should.Throw<IndexOutOfRangeException>(() => System.Array.Empty<byte>().ToMultipleSegments().GetFirst());
21+
e.Message.ShouldBe("ReadOnlySequence is too short. Expected: 1, actual length: 0");
22+
}
23+
24+
[Theory]
25+
[InlineData(new[] {1})]
26+
[InlineData(new[] {int.MaxValue, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})]
27+
public void GetFirstNonByteNonEmpty(int[] data)
28+
{
29+
data.ToMultipleSegments().GetFirst().ShouldBe(data[0]);
30+
}
31+
32+
[Fact]
33+
public void GetFirstNonByteEmpty()
34+
{
35+
var e = Should.Throw<IndexOutOfRangeException>(() => System.Array.Empty<byte>().ToMultipleSegments().GetFirst());
36+
e.Message.ShouldBe("ReadOnlySequence is too short. Expected: 1, actual length: 0");
37+
}
38+
}
39+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using System;
2+
using Shouldly;
3+
using Xunit;
4+
5+
namespace ProGaudi.MsgPack.Tests.ReadOnlySequence.SingleSegment
6+
{
7+
public class PublicExtensions
8+
{
9+
[Theory]
10+
[InlineData(new byte[] {1})]
11+
[InlineData(new byte[] {byte.MaxValue, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})]
12+
public void GetFirstByteNonEmpty(byte[] data)
13+
{
14+
data.ToSingleSegment().GetFirst().ShouldBe(data[0]);
15+
}
16+
17+
[Fact]
18+
public void GetFirstByteEmpty()
19+
{
20+
var e = Should.Throw<IndexOutOfRangeException>(() => System.Array.Empty<byte>().ToSingleSegment().GetFirst());
21+
e.Message.ShouldBe("ReadOnlySequence is too short. Expected: 1, actual length: 0");
22+
}
23+
24+
[Theory]
25+
[InlineData(new[] {1})]
26+
[InlineData(new[] {int.MaxValue, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10})]
27+
public void GetFirstNonByteNonEmpty(int[] data)
28+
{
29+
data.ToSingleSegment().GetFirst().ShouldBe(data[0]);
30+
}
31+
32+
[Fact]
33+
public void GetFirstNonByteEmpty()
34+
{
35+
var e = Should.Throw<IndexOutOfRangeException>(() => System.Array.Empty<byte>().ToSingleSegment().GetFirst());
36+
e.Message.ShouldBe("ReadOnlySequence is too short. Expected: 1, actual length: 0");
37+
}
38+
}
39+
}

0 commit comments

Comments
 (0)