dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.91k stars 4.63k forks source link

ReadOnlySequence.Slice(int start, int length) has (possibly) unexpected behavior #67607

Open gfr-g opened 2 years ago

gfr-g commented 2 years ago

Description

I'm not sure whether this is a bug or expected behavior but calling ReadOnlySequence.Slice(int start, int length) on a sequence with more than one segment with a start index of 0 and length equal to the size of the first segment, returns a sequence with two segments where the second one is empty (this actually happen for slices of any size, as long as they are on a segment border, and regardless of whether we start from the beginning of the first segment or the beginning of any other segment)

Reproduction Steps

using System.Buffers;

var buffer = new byte[4097];

var seg1 = new Seg(buffer.AsMemory(^1), 4096);
var seg0 = new Seg(buffer.AsMemory(..^1), 0);
seg0.SetNext(seg1);

var sequence = new ReadOnlySequence<byte>(seg0, 0, seg1, 1);
var result = sequence.Slice(0, sequence.First.Length);

Console.WriteLine(result.IsSingleSegment); // this prints False  

internal class Seg : ReadOnlySequenceSegment<byte>
{
    public Seg(ReadOnlyMemory<byte> memory, long runningIndex)
    {
        Memory = memory;
        RunningIndex = runningIndex;
    }

    public void SetNext(Seg seg)
    {
        Next = seg;
    }
}

Expected behavior

When slicing a sequence on segments border, I expect to get a sequence which contains only the sliced segments.

Actual behavior

Currently, slicing as described adds an empty segment at the end of the sequence.

Regression?

No response

Known Workarounds

No response

Configuration

NET 6.0 (but I also tried with the latest 7.0 preview) Windows 10 x64

Other information

No response

ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-buffers See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I'm not sure whether this is a bug or expected behavior but calling `ReadOnlySequence.Slice(int start, int length)` on a sequence with more than one segment with a start index of 0 and length equal to the size of the first segment, returns a sequence with two segments where the second one is empty (this actually happen for slices of any size, as long as they are on a segment border, and regardless of whether we start from the beginning of the first segment or the beginning of any other segment) ### Reproduction Steps ``` using System.IO.Pipelines; var buffer = new byte[6004]; var pipe = new Pipe(); await pipe.Writer.WriteAsync(buffer); await pipe.Writer.FlushAsync(); var read = await pipe.Reader.ReadAsync(); var sequence = read.Result.Buffer; var result = sequence.Slice(0, sequence.First.Length); Console.WriteLine(result.IsSingleSegment); // this prints False ``` ### Expected behavior When slicing a sequence on segments border, I expect to get a sequence which contains only the sliced segments. ### Actual behavior Currently, slicing as described adds an empty segment at the end of the sequence. ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration NET 6.0 (but I also tried with the latest 7.0 preview) Windows 10 x64 ### Other information _No response_
Author: gfr-g
Assignees: adityamandaleeka
Labels: `area-System.Buffers`, `area-System.IO.Pipelines`, `investigate`
Milestone: 7.0.0
ghost commented 2 years ago

Tagging subscribers to this area: @dotnet/area-system-buffers See info in area-owners.md if you want to be subscribed.

Issue Details
### Description I'm not sure whether this is a bug or expected behavior but calling `ReadOnlySequence.Slice(int start, int length)` on a sequence with more than one segment with a start index of 0 and length equal to the size of the first segment, returns a sequence with two segments where the second one is empty (this actually happen for slices of any size, as long as they are on a segment border, and regardless of whether we start from the beginning of the first segment or the beginning of any other segment) ### Reproduction Steps ``` using System.IO.Pipelines; var buffer = new byte[6004]; var pipe = new Pipe(); await pipe.Writer.WriteAsync(buffer); await pipe.Writer.FlushAsync(); var read = await pipe.Reader.ReadAsync(); var sequence = read.Result.Buffer; var result = sequence.Slice(0, sequence.First.Length); Console.WriteLine(result.IsSingleSegment); // this prints False ``` ### Expected behavior When slicing a sequence on segments border, I expect to get a sequence which contains only the sliced segments. ### Actual behavior Currently, slicing as described adds an empty segment at the end of the sequence. ### Regression? _No response_ ### Known Workarounds _No response_ ### Configuration NET 6.0 (but I also tried with the latest 7.0 preview) Windows 10 x64 ### Other information _No response_
Author: gfr-g
Assignees: adityamandaleeka
Labels: `area-System.Buffers`, `area-System.IO.Pipelines`, `investigate`
Milestone: 7.0.0
davidfowl commented 2 years ago

I think this is a read only sequence issue.

danmoseley commented 2 years ago

Is it possible to give a repro snippet that is only in terms of span/sequence and not pipes?

davidfowl commented 2 years ago

Tangentially related to https://github.com/dotnet/runtime/issues/30786

davidfowl commented 2 years ago

Is it possible to give a repro snippet that is only in terms of span/sequence and not pipes?

I updated the issue