diff --git a/src/libraries/System.Memory/src/System/Buffers/ReadOnlySequence.cs b/src/libraries/System.Memory/src/System/Buffers/ReadOnlySequence.cs index ff260b6aabbea..46c124c75f112 100644 --- a/src/libraries/System.Memory/src/System/Buffers/ReadOnlySequence.cs +++ b/src/libraries/System.Memory/src/System/Buffers/ReadOnlySequence.cs @@ -150,7 +150,7 @@ public ReadOnlySequence(ReadOnlyMemory memory) _startObject = manager; _endObject = manager; _startInteger = ReadOnlySequence.MemoryManagerToSequenceStart(index); - _endInteger = length; + _endInteger = index + length; } else if (MemoryMarshal.TryGetArray(memory, out ArraySegment segment)) { diff --git a/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs b/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs index d2c430505ec56..8d00793d6df4f 100644 --- a/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs +++ b/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceFactory.byte.cs @@ -4,6 +4,9 @@ using System.Buffers; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading; namespace System.Memory.Tests { @@ -11,6 +14,7 @@ public abstract class ReadOnlySequenceFactory { public static ReadOnlySequenceFactory ArrayFactory { get; } = new ArrayTestSequenceFactory(); public static ReadOnlySequenceFactory MemoryFactory { get; } = new MemoryTestSequenceFactory(); + public static ReadOnlySequenceFactory MemoryManagerFactory { get; } = new MemoryManagerTestSequenceFactory(); public static ReadOnlySequenceFactory SingleSegmentFactory { get; } = new SingleSegmentTestSequenceFactory(); public static ReadOnlySequenceFactory SegmentPerItemFactory { get; } = new BytePerSegmentTestSequenceFactory(); public static ReadOnlySequenceFactory SplitInThree { get; } = new SegmentsTestSequenceFactory(3); @@ -37,7 +41,11 @@ internal class MemoryTestSequenceFactory : ReadOnlySequenceFactory { public override ReadOnlySequence CreateOfSize(int size) { - return CreateWithContent(new T[size]); +#if DEBUG + return new ReadOnlySequence(new ReadOnlyMemory(new T[size + 1]).Slice(1)); +#else + return new ReadOnlySequence(new ReadOnlyMemory(new T[size])); +#endif } public override ReadOnlySequence CreateWithContent(T[] data) @@ -112,6 +120,49 @@ public override ReadOnlySequence CreateWithContent(T[] data) } } + internal class MemoryManagerTestSequenceFactory : ReadOnlySequenceFactory + { + public override ReadOnlySequence CreateOfSize(int size) + { +#if DEBUG + return new ReadOnlySequence(new CustomMemoryManager(size + 1).Memory.Slice(1)); +#else + return new ReadOnlySequence(new CustomMemoryManager(size).Memory); +#endif + } + + public override ReadOnlySequence CreateWithContent(T[] data) + { + return new ReadOnlySequence(new CustomMemoryManager(data).Memory); + } + + private unsafe class CustomMemoryManager : MemoryManager + { + private readonly T[] _buffer; + + public CustomMemoryManager(int size) => _buffer = new T[size]; + + public CustomMemoryManager(T[] content) => _buffer = content; + + public unsafe override Span GetSpan() => _buffer; + + public override unsafe MemoryHandle Pin(int elementIndex = 0) + { + if ((uint)elementIndex > (uint)_buffer.Length) + { + throw new ArgumentOutOfRangeException(nameof(elementIndex)); + } + + var handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned); + return new MemoryHandle(Unsafe.Add((void*)handle.AddrOfPinnedObject(), elementIndex), handle, this); + } + + public override void Unpin() { } + + protected override void Dispose(bool disposing) { } + } + } + public static ReadOnlySequence CreateSegments(params T[][] inputs) => CreateSegments(inputs.Select(input => (ReadOnlyMemory)input.AsMemory())); public static ReadOnlySequence CreateSegments(IEnumerable> inputs) diff --git a/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.byte.cs b/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.byte.cs index eb78a69e2008b..db53f0834fe9e 100644 --- a/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.byte.cs +++ b/src/libraries/System.Memory/tests/ReadOnlyBuffer/ReadOnlySequenceTests.byte.cs @@ -20,6 +20,11 @@ public class Memory : ReadOnlySequenceTestsByte public Memory() : base(ReadOnlySequenceFactory.MemoryFactory) { } } + public class MemoryManager : ReadOnlySequenceTestsByte + { + public MemoryManager() : base(ReadOnlySequenceFactory.MemoryManagerFactory) { } + } + public class SingleSegment : ReadOnlySequenceTestsByte { public SingleSegment() : base(ReadOnlySequenceFactory.SingleSegmentFactory) { }