Skip to content

ReadOnlySequence.Slice which accepts a SequencePosition throws ArgumentOutOfRangeException unexpectedly. #27834

@ahsonkhan

Description

@ahsonkhan

The behavior of Slice(offset, SequencePosition) should match GetPosition(offset) and Slice(offset).
I should be able to slice a ReadOnlySequence past the current sequence if the next one is empty (for example: [97] -> []).

[Fact]
public static void ReadOnlySequenceTest()
{
    string jsonString = "a";

    ReadOnlyMemory<byte> dataMemory = Encoding.UTF8.GetBytes(jsonString);

    var firstSegment = new BufferSegment<byte>(dataMemory.Slice(0, 1));
    ReadOnlyMemory<byte> secondMem = dataMemory.Slice(0, 0);
    BufferSegment<byte> secondSegment = firstSegment.Append(secondMem);

    // A two segment sequence where the second one is empty: [a]-> []
    var sequence = new ReadOnlySequence<byte>(firstSegment, 0, secondSegment, secondMem.Length);

    SequencePosition expectedPosition = sequence.GetPosition(1);
    Console.WriteLine(expectedPosition.GetInteger());   // 0
    Console.WriteLine(expectedPosition.GetObject());    // System.Text.Json.Tests.BufferSegment`1[System.Byte]
    Assert.True(((ReadOnlySequenceSegment<byte>)expectedPosition.GetObject()).Memory.IsEmpty);

    SequencePosition actualPosition = sequence.Slice(1).Start;
    Console.WriteLine(actualPosition.GetInteger()); // 0
    Console.WriteLine(actualPosition.GetObject());  // System.Text.Json.Tests.BufferSegment`1[System.Byte]
    Assert.True(((ReadOnlySequenceSegment<byte>)actualPosition.GetObject()).Memory.IsEmpty);
    Assert.Equal(expectedPosition, actualPosition); // True

    SequencePosition actualPosition2 = sequence.GetPosition(1, sequence.Start);
    Console.WriteLine(actualPosition2.GetInteger());   // 0
    Console.WriteLine(actualPosition2.GetObject());    // System.Text.Json.Tests.BufferSegment`1[System.Byte]
    Assert.True(((ReadOnlySequenceSegment<byte>)actualPosition2.GetObject()).Memory.IsEmpty);

    // System.ArgumentOutOfRangeException : Specified argument was out of the range of valid values.

    /*
        System.ArgumentOutOfRangeException : Specified argument was out of the range of valid values.
        Parameter name: start
        Stack Trace:
        E:\GitHub\Fork\corefx\src\System.Memory\src\System\ThrowHelper.cs(31,0): at System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument)
        E:\GitHub\Fork\corefx\src\System.Memory\src\System\Buffers\ReadOnlySequence.cs(281,0): at System.Buffers.ReadOnlySequence`1.Slice(Int64 start, SequencePosition end)
        E:\GitHub\Fork\corefx\src\System.Memory\src\System\Buffers\ReadOnlySequence.cs(388,0): at System.Buffers.ReadOnlySequence`1.Slice(Int32 start, SequencePosition end)
        E:\GitHub\Fork\corefx\src\System.Text.Json\tests\Utf8JsonReaderTests.TryGet.cs(357,0): at System.Text.Json.Tests.Utf8JsonReaderTests.ReadOnlySequenceTest()
    */
    sequence = sequence.Slice(1, sequence.Start);
}

We need to use the Slice overload that takes a SequencePosition for performance to avoid having to scan the segments from the beginning every time. Using GetPosition with long is too slow:
https://github.com/dotnet/corefxlab/blob/63ef1a5db4fdbfcf9822b8cd2cbc3921b3d3cb9e/src/System.Text.JsonLab/System/Text/Json/JsonUtf8Reader.cs#L112

cc @pakrym, @davidfowl

Metadata

Metadata

Labels

area-System.Memorybughelp wanted[up-for-grabs] Good issue for external contributorsin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions