From 252c882d272277c9fa98be32f6308b0f4592f15d Mon Sep 17 00:00:00 2001 From: Krzysztof Cwalina Date: Fri, 22 Dec 2017 15:13:02 -0800 Subject: [PATCH] Prepared System.Buffer.Primitives for API Review (#1993) * Unified Positions * Removed fully qualified Position names * Added accidentally removed throw * Removed one copy of TestBufferFactory * Rearrange Seek Methods --- .../BufferSequence.cs | 7 +- .../Framing/Codec.cs | 1 + .../HttpClient/PipelineHttpClientHandler.cs | 1 + .../HttpServer/FormReader.cs | 1 + .../HttpServer/HttpRequestParser.cs | 1 + .../System/Buffers/BufferExtensions.cs | 33 ++- .../System/Buffers/Sequences/MemoryList.cs | 10 +- .../System/Buffers/Sequences/ReadOnlyBytes.cs | 16 +- .../Buffers/Sequences/ReadWriteBytes.cs | 16 +- .../Buffers/Sequences/SequenceExtensions.cs | 26 +-- .../System/Buffers/Text/BufferReader.cs | 26 +-- src/System.Buffers.Primitives/AssemblyInfo.cs | 1 + .../System.Buffers.Primitives.csproj | 1 + .../System/Buffers/BufferExtensions.cs | 72 ------ .../System/Buffers/Position.cs | 67 ------ .../System/Buffers/ReadOnlyBuffer.cs | 32 +-- .../System/Buffers/ReadOnlyBufferReader.cs | 9 +- ...perations.cs => ReadOnlyBuffer_helpers.cs} | 220 +++++++++--------- .../System/Collections}/ISequence.cs | 2 +- .../System/Collections/Position.cs | 82 +++++++ .../System/Runtime/PrimitiveAttribute.cs | 11 - .../System.Collections.Sequences.csproj | 1 + .../System/Collections/Sequences/ArrayList.cs | 2 +- .../System/Collections/Sequences/Position.cs | 59 ----- .../DefaultReadableBufferExtensions.cs | 1 + .../ReadWriteExtensions.cs | 8 + .../ReadableBufferSequence.cs | 7 +- .../SplitEnumerable.cs | 1 + .../SplitEnumerator.cs | 1 + .../System/IO/Pipelines/IPipeReader.cs | 1 + .../System/IO/Pipelines/Pipe.cs | 5 +- .../Formatters/SequenceFormatter.cs | 3 +- .../System/Text/Parsing/SequenceParser.cs | 1 - src/System.Text.Http.Parser/HttpParser.cs | 11 +- src/System.Text.Http.Parser/IHttpParser.cs | 2 +- .../System/Text/Utf8Span.cs | 14 +- tests/Benchmarks/BytesReaderBench.cs | 2 +- tests/Benchmarks/HttpParserBench.cs | 21 +- .../BufferEqualityTests.cs | 0 .../BytesReaderTests.cs | 4 +- .../ReadOnlyBytesTests.cs | 8 +- .../SequenceExtensionsTests.cs | 2 +- .../BufferUtilities.cs | 1 + ...ferFactory.cs => ReadOnlyBufferFactory.cs} | 18 +- .../ReadableBufferFacts.cs | 17 +- .../ReadableBufferReaderFacts.cs | 63 ++--- .../SampleCollections/Hashtable.cs | 6 +- .../SampleCollections/LinkedContainer.cs | 4 +- .../PipelineReaderWriterFacts.cs | 1 + .../ReadableBufferFacts.cs | 3 +- .../ReadCursorOperationsThroughput.cs | 6 +- .../SeekTests.cs | 45 ++-- .../HttpParserTests.cs | 1 + 53 files changed, 437 insertions(+), 517 deletions(-) delete mode 100644 src/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs delete mode 100644 src/System.Buffers.Primitives/System/Buffers/Position.cs rename src/System.Buffers.Primitives/System/Buffers/{ReadCursorOperations.cs => ReadOnlyBuffer_helpers.cs} (87%) rename src/{System.Collections.Sequences/System/Collections/Sequences => System.Buffers.Primitives/System/Collections}/ISequence.cs (94%) create mode 100644 src/System.Buffers.Primitives/System/Collections/Position.cs delete mode 100644 src/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs delete mode 100644 src/System.Collections.Sequences/System/Collections/Sequences/Position.cs rename tests/{System.Buffers.Primitives.Tests => System.Buffers.Experimental.Tests}/BufferEqualityTests.cs (100%) rename tests/System.Buffers.Primitives.Tests/{TestBufferFactory.cs => ReadOnlyBufferFactory.cs} (78%) rename tests/{System.Buffers.Primitives.Tests => System.IO.Pipelines.Tests}/SeekTests.cs (85%) diff --git a/samples/LowAllocationWebServer/LowAllocationWebServerLibrary/BufferSequence.cs b/samples/LowAllocationWebServer/LowAllocationWebServerLibrary/BufferSequence.cs index 6f555b95301..ab3a2f80b30 100644 --- a/samples/LowAllocationWebServer/LowAllocationWebServerLibrary/BufferSequence.cs +++ b/samples/LowAllocationWebServer/LowAllocationWebServerLibrary/BufferSequence.cs @@ -5,7 +5,6 @@ using System; using System.Buffers; using System.Collections.Sequences; -using Position = System.Collections.Sequences.Position; namespace Microsoft.Net { @@ -36,7 +35,7 @@ public BufferSequence(int desiredSize = DefaultBufferSize) public long VirtualIndex => throw new NotImplementedException(); - public Position First => Position.Create(this); + public Position First => new Position(this, 0); public int CopyTo(Span buffer) { @@ -58,7 +57,7 @@ public bool TryGet(ref Position position, out Memory item, bool advance = var (buffer, index) = position.Get(); item = buffer.Memory.Slice(index, buffer._written - index); - if (advance) { position = Position.Create(buffer._next); } + if (advance) { position = new Position(buffer._next, 0); } return true; } @@ -72,7 +71,7 @@ public bool TryGet(ref Position position, out ReadOnlyMemory item, bool ad var (buffer, index) = position.Get(); item = buffer.WrittenMemory.Slice(index); - if (advance) { position = Position.Create(buffer._next); } + if (advance) { position = new Position(buffer._next, 0); } return true; } diff --git a/samples/System.IO.Pipelines.Samples/Framing/Codec.cs b/samples/System.IO.Pipelines.Samples/Framing/Codec.cs index d30fd02f500..fc8c88ced58 100644 --- a/samples/System.IO.Pipelines.Samples/Framing/Codec.cs +++ b/samples/System.IO.Pipelines.Samples/Framing/Codec.cs @@ -9,6 +9,7 @@ using System.IO.Pipelines.Networking.Libuv; using System.IO.Pipelines.Text.Primitives; using System.Buffers.Text; +using System.Collections.Sequences; namespace System.IO.Pipelines.Samples.Framing { diff --git a/samples/System.IO.Pipelines.Samples/HttpClient/PipelineHttpClientHandler.cs b/samples/System.IO.Pipelines.Samples/HttpClient/PipelineHttpClientHandler.cs index 2976d84c8e1..8963f81a0a0 100644 --- a/samples/System.IO.Pipelines.Samples/HttpClient/PipelineHttpClientHandler.cs +++ b/samples/System.IO.Pipelines.Samples/HttpClient/PipelineHttpClientHandler.cs @@ -14,6 +14,7 @@ using System.IO.Pipelines.Text.Primitives; using System.Text.Formatting; using System.Buffers.Text; +using System.Collections.Sequences; namespace System.IO.Pipelines.Samples { diff --git a/samples/System.IO.Pipelines.Samples/HttpServer/FormReader.cs b/samples/System.IO.Pipelines.Samples/HttpServer/FormReader.cs index 46afb1cfd0a..c904a91e99a 100644 --- a/samples/System.IO.Pipelines.Samples/HttpServer/FormReader.cs +++ b/samples/System.IO.Pipelines.Samples/HttpServer/FormReader.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Collections.Generic; +using System.Collections.Sequences; using System.IO.Pipelines.Text.Primitives; using Microsoft.Extensions.Primitives; diff --git a/samples/System.IO.Pipelines.Samples/HttpServer/HttpRequestParser.cs b/samples/System.IO.Pipelines.Samples/HttpServer/HttpRequestParser.cs index 750ed527737..0e3cd538df3 100644 --- a/samples/System.IO.Pipelines.Samples/HttpServer/HttpRequestParser.cs +++ b/samples/System.IO.Pipelines.Samples/HttpServer/HttpRequestParser.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Collections.Sequences; using System.IO.Pipelines.Samples.Http; using System.IO.Pipelines.Text.Primitives; diff --git a/src/System.Buffers.Experimental/System/Buffers/BufferExtensions.cs b/src/System.Buffers.Experimental/System/Buffers/BufferExtensions.cs index 97164e64808..bd5e6d4bce5 100644 --- a/src/System.Buffers.Experimental/System/Buffers/BufferExtensions.cs +++ b/src/System.Buffers.Experimental/System/Buffers/BufferExtensions.cs @@ -50,13 +50,13 @@ public static int CopyTo(this IMemoryList list, Span destination) return copied; } - public static Collections.Sequences.Position? PositionOf(this IMemoryList list, byte value) + public static Position? PositionOf(this IMemoryList list, byte value) { while (list != null) { var current = list.Memory.Span; var index = current.IndexOf(value); - if (index != -1) return Collections.Sequences.Position.Create(list, index); + if (index != -1) return new Position(list, index); list = list.Next; } return null; @@ -135,7 +135,7 @@ public static void Pipe(this IBufferOperation transformation, ReadOnlyBytes sour ReadOnlySpan remainder = stackalloc byte[0]; Span stackSpan = stackalloc byte[stackLength]; - Collections.Sequences.Position poisition = default; + Position poisition = default; while (source.TryGet(ref poisition, out var sourceBuffer)) { Span outputSpan = destination.GetSpan(); @@ -225,6 +225,33 @@ public static void Pipe(this IBufferOperation transformation, ReadOnlyBytes sour return; } + public static bool SequenceEqual(this Memory first, Memory second) where T : struct, IEquatable + { + return first.Span.SequenceEqual(second.Span); + } + + public static bool SequenceEqual(this ReadOnlyMemory first, ReadOnlyMemory second) where T : struct, IEquatable + { + return first.Span.SequenceEqual(second.Span); + } + + public static int SequenceCompareTo(this Span left, ReadOnlySpan right) + { + return SequenceCompareTo((ReadOnlySpan)left, right); + } + + public static int SequenceCompareTo(this ReadOnlySpan left, ReadOnlySpan right) + { + var minLength = left.Length; + if (minLength > right.Length) minLength = right.Length; + for (int i = 0; i < minLength; i++) + { + var result = left[i].CompareTo(right[i]); + if (result != 0) return result; + } + return left.Length.CompareTo(right.Length); + } + public static bool TryIndicesOf(this Span buffer, byte value, Span indices, out int numberOfIndices) { var length = buffer.Length; diff --git a/src/System.Buffers.Experimental/System/Buffers/Sequences/MemoryList.cs b/src/System.Buffers.Experimental/System/Buffers/Sequences/MemoryList.cs index a56ff912fa9..59cc30a00c7 100644 --- a/src/System.Buffers.Experimental/System/Buffers/Sequences/MemoryList.cs +++ b/src/System.Buffers.Experimental/System/Buffers/Sequences/MemoryList.cs @@ -39,12 +39,12 @@ public MemoryList Append(Memory bytes) public long VirtualIndex => _virtualIndex; - public Collections.Sequences.Position First => Collections.Sequences.Position.Create(this); + public Position First => new Position(this, 0); public int CopyTo(Span buffer) { int copied = 0; - Collections.Sequences.Position position = default; + Position position = default; var free = buffer; while (TryGet(ref position, out ReadOnlyMemory segment, true)) { @@ -64,14 +64,14 @@ public int CopyTo(Span buffer) return copied; } - public bool TryGet(ref Collections.Sequences.Position position, out ReadOnlyMemory item, bool advance = true) + public bool TryGet(ref Position position, out ReadOnlyMemory item, bool advance = true) { var result = TryGet(ref position, out Memory memory, advance); item = memory; return result; } - public bool TryGet(ref Collections.Sequences.Position position, out Memory item, bool advance = true) + public bool TryGet(ref Position position, out Memory item, bool advance = true) { if (position == default) { @@ -81,7 +81,7 @@ public bool TryGet(ref Collections.Sequences.Position position, out Memory var (list, index) = position.Get(); item = list._data.Slice(index); - if (advance) { position = Collections.Sequences.Position.Create(list._next); } + if (advance) { position = new Position(list._next, 0); } return true; } diff --git a/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadOnlyBytes.cs b/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadOnlyBytes.cs index 8fdaa736322..e224be4cd7b 100644 --- a/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadOnlyBytes.cs +++ b/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadOnlyBytes.cs @@ -54,7 +54,7 @@ public ReadOnlyBytes(IMemoryList first, IMemoryList last) Validate(); } - public ReadOnlyBytes(Collections.Sequences.Position first, Collections.Sequences.Position last) + public ReadOnlyBytes(Position first, Position last) { (_start, _startIndex) = first.Get(); (_end, _endIndex) = last.Get(); @@ -134,7 +134,7 @@ public ReadOnlyBytes Slice(long index) public ReadOnlyBytes Slice(int index) => Slice((long)index); - public ReadOnlyBytes Slice(Collections.Sequences.Position position) + public ReadOnlyBytes Slice(Position position) { var kind = Kind; switch (kind) @@ -143,12 +143,12 @@ public ReadOnlyBytes Slice(Collections.Sequences.Position position) var (array, index) = position.Get(); return new ReadOnlyBytes(array, index, array.Length - index); case Type.MemoryList: - return Slice(position, Collections.Sequences.Position.Create((IMemoryList)_end, _endIndex)); + return Slice(position, new Position((IMemoryList)_end, _endIndex)); default: throw new NotImplementedException(); } } - public ReadOnlyBytes Slice(Collections.Sequences.Position start, Collections.Sequences.Position end) + public ReadOnlyBytes Slice(Position start, Position end) { var kind = Kind; switch (kind) @@ -236,7 +236,7 @@ Type Kind } } - public Collections.Sequences.Position First => Collections.Sequences.Position.Create(_start, _startIndex); + public Position Start => new Position(_start, _startIndex); public int CopyTo(Span buffer) { @@ -249,7 +249,7 @@ public int CopyTo(Span buffer) return length; } - var position = First; + var position = Start; int copied = 0; while (TryGet(ref position, out var memory) && buffer.Length > 0) { @@ -270,7 +270,7 @@ public Span ToSpan() return array; } - public bool TryGet(ref Collections.Sequences.Position position, out ReadOnlyMemory item, bool advance = true) + public bool TryGet(ref Position position, out ReadOnlyMemory item, bool advance = true) { if(position == default) { @@ -299,7 +299,7 @@ public bool TryGet(ref Collections.Sequences.Position position, out ReadOnlyMemo } else { - if (advance) position = Collections.Sequences.Position.Create(node.Next); + if (advance) position = new Position(node.Next, 0); } return true; } diff --git a/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadWriteBytes.cs b/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadWriteBytes.cs index 5424c24b395..578e99b1e51 100644 --- a/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadWriteBytes.cs +++ b/src/System.Buffers.Experimental/System/Buffers/Sequences/ReadWriteBytes.cs @@ -50,7 +50,7 @@ public ReadWriteBytes(IMemoryList first, IMemoryList last) Validate(); } - public ReadWriteBytes(Collections.Sequences.Position first, Collections.Sequences.Position last) + public ReadWriteBytes(Position first, Position last) { (_start, _startIndex) = first.Get(); (_end, _endIndex) = last.Get(); @@ -130,7 +130,7 @@ public ReadWriteBytes Slice(long index) public ReadWriteBytes Slice(int index) => Slice((long)index); - public ReadWriteBytes Slice(Collections.Sequences.Position position) + public ReadWriteBytes Slice(Position position) { var kind = Kind; switch (kind) @@ -139,12 +139,12 @@ public ReadWriteBytes Slice(Collections.Sequences.Position position) var (array, index) = position.Get(); return new ReadWriteBytes(array, index, array.Length - index); case Type.MemoryList: - return Slice(position, Collections.Sequences.Position.Create((IMemoryList)_end, _endIndex)); + return Slice(position, new Position((IMemoryList)_end, _endIndex)); default: throw new NotImplementedException(); } } - public ReadWriteBytes Slice(Collections.Sequences.Position start, Collections.Sequences.Position end) + public ReadWriteBytes Slice(Position start, Position end) { var kind = Kind; switch (kind) @@ -233,7 +233,7 @@ Type Kind } } - public Collections.Sequences.Position First => Collections.Sequences.Position.Create(_start, _startIndex); + public Position Start => new Position(_start, _startIndex); public int CopyTo(Span buffer) { @@ -246,7 +246,7 @@ public int CopyTo(Span buffer) return length; } - var position = First; + var position = Start; int copied = 0; while (TryGet(ref position, out var memory) && buffer.Length > 0) { @@ -267,7 +267,7 @@ public Span ToSpan() return array; } - public bool TryGet(ref Collections.Sequences.Position position, out Memory item, bool advance = true) + public bool TryGet(ref Position position, out Memory item, bool advance = true) { if (position == default) { @@ -296,7 +296,7 @@ public bool TryGet(ref Collections.Sequences.Position position, out Memory } else { - if (advance) position = Collections.Sequences.Position.Create(node.Next); + if (advance) position = new Position(node.Next, 0); } return true; } diff --git a/src/System.Buffers.Experimental/System/Buffers/Sequences/SequenceExtensions.cs b/src/System.Buffers.Experimental/System/Buffers/Sequences/SequenceExtensions.cs index d5936df84eb..e3b492087d9 100644 --- a/src/System.Buffers.Experimental/System/Buffers/Sequences/SequenceExtensions.cs +++ b/src/System.Buffers.Experimental/System/Buffers/Sequences/SequenceExtensions.cs @@ -11,7 +11,7 @@ public static class Sequence { public static ReadOnlySpan ToSpan(this T sequence) where T : ISequence> { - Collections.Sequences.Position position = sequence.First; + Position position = sequence.Start; ResizableArray array = new ResizableArray(1024); while (sequence.TryGet(ref position, out ReadOnlyMemory buffer)) { @@ -26,7 +26,7 @@ public static ReadOnlySpan ToSpan(this T sequence) where T : ISequence< // be used as a type parameter. public static long IndexOf(TSequence sequence, byte value) where TSequence : ISequence> { - Collections.Sequences.Position position = sequence.First; + Position position = sequence.Start; int totalIndex = 0; while (sequence.TryGet(ref position, out ReadOnlyMemory memory)) { @@ -39,7 +39,7 @@ public static long IndexOf(TSequence sequence, byte value) where TSeq public static long IndexOf(TSequence sequence, byte v1, byte v2) where TSequence : ISequence> { - Collections.Sequences.Position position = sequence.First; + Position position = sequence.Start; int totalIndex = 0; while (sequence.TryGet(ref position, out ReadOnlyMemory memory)) { @@ -68,12 +68,12 @@ public static long IndexOf(TSequence sequence, byte v1, byte v2) wher return -1; } - public static Collections.Sequences.Position? PositionOf(this TSequence sequence, byte value) where TSequence : ISequence> + public static Position? PositionOf(this TSequence sequence, byte value) where TSequence : ISequence> { if (sequence == null) return null; - Collections.Sequences.Position position = sequence.First; - Collections.Sequences.Position result = position; + Position position = sequence.Start; + Position result = position; while (sequence.TryGet(ref position, out ReadOnlyMemory memory)) { var index = MemoryExtensions.IndexOf(memory.Span, value); @@ -87,12 +87,12 @@ public static long IndexOf(TSequence sequence, byte v1, byte v2) wher return null; } - public static Collections.Sequences.Position? PositionAt(this TSequence sequence, long index) where TSequence : ISequence> + public static Position? PositionAt(this TSequence sequence, long index) where TSequence : ISequence> { if (sequence == null) return null; - Collections.Sequences.Position position = sequence.First; - Collections.Sequences.Position result = position; + Position position = sequence.Start; + Position result = position; while (sequence.TryGet(ref position, out ReadOnlyMemory memory)) { var span = memory.Span; @@ -111,7 +111,7 @@ public static long IndexOf(TSequence sequence, byte v1, byte v2) wher public static int Copy(TSequence sequence, Span buffer) where TSequence : ISequence> { int copied = 0; - var position = sequence.First; + var position = sequence.Start; while (sequence.TryGet(ref position, out ReadOnlyMemory memory, true)) { var span = memory.Span; @@ -123,7 +123,7 @@ public static int Copy(TSequence sequence, Span buffer) where T return copied; } - public static int Copy(TSequence sequence, Collections.Sequences.Position from, Span buffer) where TSequence : ISequence> + public static int Copy(TSequence sequence, Position from, Span buffer) where TSequence : ISequence> { int copied = 0; while (sequence.TryGet(ref from, out ReadOnlyMemory memory, true)) @@ -139,7 +139,7 @@ public static int Copy(TSequence sequence, Collections.Sequences.Posi public static bool TryParse(TSequence sequence, out int value, out int consumed) where TSequence : ISequence> { - var position = sequence.First; + var position = sequence.Start; if(sequence.TryGet(ref position, out ReadOnlyMemory memory)) { var span = memory.Span; @@ -162,7 +162,7 @@ public static bool TryParse(TSequence sequence, out int value, out in return false; } - public static bool TryParse(TSequence sequence, out int value, out Collections.Sequences.Position consumed) where TSequence : ISequence> + public static bool TryParse(TSequence sequence, out int value, out Position consumed) where TSequence : ISequence> { if(!TryParse(sequence, out value, out int consumedBytes)) { diff --git a/src/System.Buffers.Experimental/System/Buffers/Text/BufferReader.cs b/src/System.Buffers.Experimental/System/Buffers/Text/BufferReader.cs index 9fb7509eb8c..a6f3244029e 100644 --- a/src/System.Buffers.Experimental/System/Buffers/Text/BufferReader.cs +++ b/src/System.Buffers.Experimental/System/Buffers/Text/BufferReader.cs @@ -14,8 +14,8 @@ namespace System.Buffers.Text public ref struct BufferReader where TSequence : ISequence> { readonly TSequence _bytes; - Collections.Sequences.Position _currentSegmentPosition; - Collections.Sequences.Position _nextSegmentPosition; + Position _currentSegmentPosition; + Position _nextSegmentPosition; ReadOnlySpan _currentSpan; int _currentSpanIndex; @@ -24,7 +24,7 @@ namespace System.Buffers.Text public BufferReader(TSequence bytes) { _bytes = bytes; - _nextSegmentPosition = bytes.First; + _nextSegmentPosition = bytes.Start; _currentSegmentPosition = _nextSegmentPosition; if(_bytes.TryGet(ref _nextSegmentPosition, out ReadOnlyMemory memory)) { @@ -41,7 +41,7 @@ public BufferReader(ReadOnlyMemory bytes) { _bytes = default; _nextSegmentPosition = default; - _currentSegmentPosition = 0; + _currentSegmentPosition = default; _currentSpan = bytes.Span; _currentSpanIndex = 0; } @@ -50,7 +50,7 @@ public BufferReader(ReadOnlySpan bytes) { _bytes = default; _nextSegmentPosition = default; - _currentSegmentPosition = 0; + _currentSegmentPosition = default; _currentSpan = bytes; _currentSpanIndex = 0; } @@ -62,7 +62,7 @@ public bool IsEmpty { return false; } - Collections.Sequences.Position position = _nextSegmentPosition; + Position position = _nextSegmentPosition; while (_bytes.TryGet(ref position, out ReadOnlyMemory next)) { if (!next.IsEmpty) return false; @@ -175,7 +175,7 @@ private void AdvanceNextSegment(long count, int currentSegmentUnread) Advance(count - currentSegmentUnread); } - public void Advance(Collections.Sequences.Position position) + public void Advance(Position position) { _currentSegmentPosition = position; _nextSegmentPosition = position; @@ -302,9 +302,9 @@ public bool TryRead(out int value, bool littleEndian = false) ReadOnlySpan Unread => _currentSpan.Slice(_currentSpanIndex); - Collections.Sequences.Position Position =>_currentSegmentPosition + _currentSpanIndex; + Position Position =>_currentSegmentPosition + _currentSpanIndex; - Collections.Sequences.Position? AdvanceToDelimiter(byte value) + Position? AdvanceToDelimiter(byte value) { var unread = Unread; var index = unread.IndexOf(value); @@ -338,7 +338,7 @@ public bool TryRead(out int value, bool littleEndian = false) return null; } - Collections.Sequences.Position? PositionOf(ReadOnlySpan value) + Position? PositionOf(ReadOnlySpan value) { var unread = Unread; var index = unread.IndexOf(value); @@ -394,10 +394,10 @@ public static BufferReader Create(T sequence) where T : ISequence + diff --git a/src/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs b/src/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs deleted file mode 100644 index f77ec7a7d7b..00000000000 --- a/src/System.Buffers.Primitives/System/Buffers/BufferExtensions.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Buffers -{ - public static class BufferExtensions - { - public static bool SequenceEqual(this Memory first, Memory second) where T : struct, IEquatable - { - return first.Span.SequenceEqual(second.Span); - } - - public static bool SequenceEqual(this ReadOnlyMemory first, ReadOnlyMemory second) where T : struct, IEquatable - { - return first.Span.SequenceEqual(second.Span); - } - - public static int LastIndexOf(this Span buffer, ReadOnlySpan values) - { - return LastIndexOf((ReadOnlySpan)buffer, values); - } - - public static int LastIndexOf(this ReadOnlySpan buffer, ReadOnlySpan values) - { - if (buffer.Length < values.Length) return -1; - if (values.Length == 0) return 0; - - int candidateLength = buffer.Length; - var firstByte = values[0]; - while (true) - { - int index = LastIndexOf(buffer.Slice(0, candidateLength), firstByte); - if (index == -1) return -1; - var slice = buffer.Slice(index); - if (slice.StartsWith(values)) return index; - candidateLength = index; - } - } - - public static int LastIndexOf(this Span buffer, byte value) - { - return LastIndexOf((ReadOnlySpan)buffer, value); - } - - public static int LastIndexOf(this ReadOnlySpan buffer, byte value) - { - for (int i = buffer.Length - 1; i >= 0; i--) - { - if (buffer[i] == value) return i; - } - return -1; - } - - public static int SequenceCompareTo(this Span left, ReadOnlySpan right) - { - return SequenceCompareTo((ReadOnlySpan)left, right); - } - - public static int SequenceCompareTo(this ReadOnlySpan left, ReadOnlySpan right) - { - var minLength = left.Length; - if (minLength > right.Length) minLength = right.Length; - for (int i = 0; i < minLength; i++) - { - var result = left[i].CompareTo(right[i]); - if (result != 0) return result; - } - return left.Length.CompareTo(right.Length); - } - } -} diff --git a/src/System.Buffers.Primitives/System/Buffers/Position.cs b/src/System.Buffers.Primitives/System/Buffers/Position.cs deleted file mode 100644 index 6958218491a..00000000000 --- a/src/System.Buffers.Primitives/System/Buffers/Position.cs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Diagnostics; -using System.IO.Pipelines; -using System.Runtime.CompilerServices; - -namespace System.Buffers -{ - [DebuggerDisplay("{Segment}[{Index}]")] - public readonly struct Position : IEquatable - { - public object Segment { get; } - public int Index { get; } - - public Position(object segment, int index) - { - Segment = segment; - Index = index; - } - - public bool IsDefault => Segment == null; - - public static bool operator ==(Position c1, Position c2) - { - return c1.Equals(c2); - } - - public static bool operator !=(Position c1, Position c2) - { - return !c1.Equals(c2); - } - - public bool Equals(Position other) - { - return other.Segment == Segment && other.Index == Index; - } - - public override bool Equals(object obj) - { - return Equals((Position)obj); - } - - public override int GetHashCode() - { - var h1 = Segment?.GetHashCode() ?? 0; - var h2 = Index.GetHashCode(); - - var shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27); - return ((int)shift5 + h1) ^ h2; - } - - public T Get() - { - switch (Segment) - { - case null: - return default; - case T segment: - return segment; - } - - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.UnexpectedSegmentType); - return default; - } - } -} diff --git a/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs b/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs index dfa21372ff6..cba48a036ec 100644 --- a/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs +++ b/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer.cs @@ -12,7 +12,7 @@ namespace System.Buffers /// /// Represents a buffer that can read a sequential series of bytes. /// - public readonly struct ReadOnlyBuffer + public readonly partial struct ReadOnlyBuffer : ISequence> { internal readonly Position BufferStart; internal readonly Position BufferEnd; @@ -20,7 +20,7 @@ public readonly struct ReadOnlyBuffer /// /// Length of the in bytes. /// - public long Length => ReadCursorOperations.GetLength(BufferStart, BufferEnd); + public long Length => GetLength(BufferStart, BufferEnd); /// /// Determines if the is empty. @@ -36,7 +36,7 @@ public ReadOnlyMemory First { get { - ReadCursorOperations.TryGetBuffer(BufferStart, BufferEnd, out var first, out _); + TryGetBuffer(BufferStart, BufferEnd, out var first, out _); return first; } } @@ -116,8 +116,8 @@ public ReadOnlyBuffer(OwnedMemory data, int offset, int length) /// The length of the slice public ReadOnlyBuffer Slice(long start, long length) { - var begin = ReadCursorOperations.Seek(BufferStart, BufferEnd, start, false); - var end = ReadCursorOperations.Seek(begin, BufferEnd, length, false); + var begin = Seek(BufferStart, BufferEnd, start, false); + var end = Seek(begin, BufferEnd, length, false); return new ReadOnlyBuffer(begin, end); } @@ -128,8 +128,8 @@ public ReadOnlyBuffer Slice(long start, long length) /// The end (inclusive) of the slice public ReadOnlyBuffer Slice(long start, Position end) { - ReadCursorOperations.BoundsCheck(BufferEnd, end); - var begin = ReadCursorOperations.Seek(BufferStart, end, start); + BoundsCheck(BufferEnd, end); + var begin = Seek(BufferStart, end, start); return new ReadOnlyBuffer(begin, end); } @@ -140,8 +140,8 @@ public ReadOnlyBuffer Slice(long start, Position end) /// The ending (inclusive) of the slice public ReadOnlyBuffer Slice(Position start, Position end) { - ReadCursorOperations.BoundsCheck(BufferEnd, end); - ReadCursorOperations.BoundsCheck(end, start); + BoundsCheck(BufferEnd, end); + BoundsCheck(end, start); return new ReadOnlyBuffer(start, end); } @@ -153,9 +153,9 @@ public ReadOnlyBuffer Slice(Position start, Position end) /// The length of the slice public ReadOnlyBuffer Slice(Position start, long length) { - ReadCursorOperations.BoundsCheck(BufferEnd, start); + BoundsCheck(BufferEnd, start); - var end = ReadCursorOperations.Seek(start, BufferEnd, length, false); + var end = Seek(start, BufferEnd, length, false); return new ReadOnlyBuffer(start, end); } @@ -166,7 +166,7 @@ public ReadOnlyBuffer Slice(Position start, long length) /// The starting (inclusive) at which to begin this slice. public ReadOnlyBuffer Slice(Position start) { - ReadCursorOperations.BoundsCheck(BufferEnd, start); + BoundsCheck(BufferEnd, start); return new ReadOnlyBuffer(start, BufferEnd); } @@ -179,7 +179,7 @@ public ReadOnlyBuffer Slice(long start) { if (start == 0) return this; - var begin = ReadCursorOperations.Seek(BufferStart, BufferEnd, start, false); + var begin = Seek(BufferStart, BufferEnd, start, false); return new ReadOnlyBuffer(begin, BufferEnd); } @@ -239,12 +239,12 @@ public Position Move(Position cursor, long count) { throw new ArgumentOutOfRangeException(nameof(count)); } - return ReadCursorOperations.Seek(cursor, BufferEnd, count, false); + return Seek(cursor, BufferEnd, count, false); } public bool TryGet(ref Position cursor, out ReadOnlyMemory data, bool advance = true) { - var result = ReadCursorOperations.TryGetBuffer(cursor, End, out data, out var next); + var result = TryGetBuffer(cursor, End, out data, out var next); if (advance) { cursor = next; @@ -290,7 +290,7 @@ public ReadOnlyMemory Current /// public bool MoveNext() { - if (_next.IsDefault) + if (_next.Segment == null) { return false; } diff --git a/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBufferReader.cs b/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBufferReader.cs index a6c01339571..b39be58dd7d 100644 --- a/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBufferReader.cs +++ b/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBufferReader.cs @@ -1,12 +1,12 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Buffers; +using System.Collections.Sequences; using System.Runtime.CompilerServices; -namespace System.IO.Pipelines +namespace System.Buffers { - public ref struct ReadOnlyBufferReader + public ref struct BufferReader { private ReadOnlySpan _currentSpan; private int _index; @@ -14,7 +14,7 @@ public ref struct ReadOnlyBufferReader private int _consumedBytes; private bool _end; - public ReadOnlyBufferReader(ReadOnlyBuffer buffer) + public BufferReader(ReadOnlyBuffer buffer) { _end = false; _index = 0; @@ -23,7 +23,6 @@ public ReadOnlyBufferReader(ReadOnlyBuffer buffer) _currentSpan = default; MoveNext(); } - public bool End => _end; diff --git a/src/System.Buffers.Primitives/System/Buffers/ReadCursorOperations.cs b/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer_helpers.cs similarity index 87% rename from src/System.Buffers.Primitives/System/Buffers/ReadCursorOperations.cs rename to src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer_helpers.cs index 41d4d95ca73..8d53c722ce8 100644 --- a/src/System.Buffers.Primitives/System/Buffers/ReadCursorOperations.cs +++ b/src/System.Buffers.Primitives/System/Buffers/ReadOnlyBuffer_helpers.cs @@ -6,9 +6,9 @@ using System.Collections.Sequences; using System.Runtime.CompilerServices; -namespace System.IO.Pipelines +namespace System.Buffers { - public static class ReadCursorOperations + public readonly partial struct ReadOnlyBuffer { public static int Seek(Position begin, Position end, out Position result, byte byte0) { @@ -68,42 +68,74 @@ public static int Seek(Position begin, Position end, out Position result, byte b } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static long GetLength(Position begin, Position end) + internal static bool TryGetBuffer(Position begin, Position end, out ReadOnlyMemory data, out Position next) { - if (begin.IsDefault) - { - return 0; - } - var segment = begin.Segment; + switch (segment) { + case null: + data = default; + next = default; + return false; + case IMemoryList bufferSegment: - return GetLength(bufferSegment, begin.Index, end.Get>(), end.Index); - case byte[] _: - case OwnedMemory _: - return end.Index - begin.Index; - } + var startIndex = begin.Index; + var endIndex = bufferSegment.Memory.Length; - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.UnexpectedSegmentType); - return default; - } + if (segment == end.Segment) + { + endIndex = end.Index; + next = default; + } + else + { + var nextSegment = bufferSegment.Next; + if (nextSegment == null) + { + if (end.Segment != null) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static long GetLength( - IMemoryList start, - int startIndex, - IMemoryList endSegment, - int endIndex) - { - if (start == endSegment) - { - return endIndex - startIndex; + next = default; + } + else + { + next = new Position(nextSegment, 0); + } + } + + data = bufferSegment.Memory.Slice(startIndex, endIndex - startIndex); + + return true; + + + case OwnedMemory ownedMemory: + data = ownedMemory.Memory.Slice(begin.Index, end.Index - begin.Index); + + if (segment != end.Segment) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); + } + + next = default; + return true; + + case byte[] array: + data = new Memory(array, begin.Index, end.Index - begin.Index); + + if (segment != end.Segment) + { + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); + } + next = default; + return true; } - return (endSegment.VirtualIndex - start.Next.VirtualIndex) - + (start.Memory.Length - startIndex) - + endIndex; + ThrowHelper.ThrowNotSupportedException(); + next = default; + return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -124,7 +156,7 @@ internal static Position Seek(Position begin, Position end, long bytes, bool che } [MethodImpl(MethodImplOptions.NoInlining)] - private static Position SeekMultiSegment(Position begin, Position end, long bytes, bool checkEndReachable) + private static Position SeekMultiSegment(Position begin, Position end, long bytes, bool checkEndReachable) { Position result = default; var foundResult = false; @@ -139,7 +171,7 @@ private static Position SeekMultiSegment(Position begin, Position end, long byte // then past the end of previous one, but only if next exists if (memory.Length > bytes || - (memory.Length == bytes && begin.IsDefault)) + (memory.Length == bytes && begin.Segment == null)) { result = new Position(current.Segment, current.Index + (int)bytes); foundResult = true; @@ -163,106 +195,66 @@ private static Position SeekMultiSegment(Position begin, Position end, long byte } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static void BoundsCheck(Position end, Position newCursor) + private static long GetLength(Position begin, Position end) { - switch (end.Segment) + if (begin.Segment == null) { - case byte[] _ : - case OwnedMemory _ : - if (newCursor.Index > end.Index) - { - ThrowHelper.ThrowCursorOutOfBoundsException(); - } - return; - case IMemoryList memoryList: - if (!GreaterOrEqual(memoryList, end.Index, newCursor.Get>(), newCursor.Index)) - { - ThrowHelper.ThrowCursorOutOfBoundsException(); - } - return; - default: - ThrowHelper.ThrowCursorOutOfBoundsException(); - return; + return 0; } - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static bool TryGetBuffer(Position begin, Position end, out ReadOnlyMemory data, out Position next) - { var segment = begin.Segment; - switch (segment) { - case null: - data = default; - next = default; - return false; - case IMemoryList bufferSegment: - var startIndex = begin.Index; - var endIndex = bufferSegment.Memory.Length; - - if (segment == end.Segment) - { - endIndex = end.Index; - next = default; - } - else - { - var nextSegment = bufferSegment.Next; - if (nextSegment == null) - { - if (end.Segment != null) - { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); - } - - next = default; - } - else - { - next = new Position(nextSegment, 0); - } - } - - data = bufferSegment.Memory.Slice(startIndex, endIndex - startIndex); + return GetLength(bufferSegment, begin.Index, end.GetSegment>(), end.Index); + case byte[] _: + case OwnedMemory _: + return end.Index - begin.Index; + } - return true; + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.UnexpectedSegmentType); + return default; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static long GetLength( + IMemoryList start, + int startIndex, + IMemoryList endSegment, + int endIndex) + { + if (start == endSegment) + { + return endIndex - startIndex; + } - case OwnedMemory ownedMemory: - data = ownedMemory.Memory.Slice(begin.Index, end.Index - begin.Index); + return (endSegment.VirtualIndex - start.Next.VirtualIndex) + + (start.Memory.Length - startIndex) + + endIndex; + } - if (segment != end.Segment) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void BoundsCheck(Position end, Position newCursor) + { + switch (end.Segment) + { + case byte[] _: + case OwnedMemory _: + if (newCursor.Index > end.Index) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); + ThrowHelper.ThrowCursorOutOfBoundsException(); } - - next = default; - return true; - - case byte[] array: - data = new Memory(array, begin.Index, end.Index - begin.Index); - - if (segment != end.Segment) + return; + case IMemoryList memoryList: + if(newCursor.GetSegment>().VirtualIndex - end.Index > memoryList.VirtualIndex - newCursor.Index) { - ThrowHelper.ThrowInvalidOperationException(ExceptionResource.EndCursorNotReached); + ThrowHelper.ThrowCursorOutOfBoundsException(); } - next = default; - return true; + return; + default: + ThrowHelper.ThrowCursorOutOfBoundsException(); + return; } - - ThrowHelper.ThrowNotSupportedException(); - next = default; - return false; - } - - internal static bool GreaterOrEqual(IMemoryList start, int startIndex, IMemoryList end, int endIndex) - { - // other.Segment.RunningLength + other.Index - other.Segment.Start <= Segment.RunningLength + Index- Segment.Start - // fliped to avoid overflows - - return end.VirtualIndex - startIndex <= start.VirtualIndex - endIndex; } } } diff --git a/src/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs b/src/System.Buffers.Primitives/System/Collections/ISequence.cs similarity index 94% rename from src/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs rename to src/System.Buffers.Primitives/System/Collections/ISequence.cs index 5afce836df8..bffaa90b46b 100644 --- a/src/System.Collections.Sequences/System/Collections/Sequences/ISequence.cs +++ b/src/System.Buffers.Primitives/System/Collections/ISequence.cs @@ -15,6 +15,6 @@ public interface ISequence /// bool TryGet(ref Position position, out T item, bool advance = true); - Position First { get; } + Position Start { get; } } } diff --git a/src/System.Buffers.Primitives/System/Collections/Position.cs b/src/System.Buffers.Primitives/System/Collections/Position.cs new file mode 100644 index 00000000000..c8f58414891 --- /dev/null +++ b/src/System.Buffers.Primitives/System/Collections/Position.cs @@ -0,0 +1,82 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Buffers; +using System.ComponentModel; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Collections.Sequences +{ + public readonly struct Position : IEquatable + { + readonly object _segment; + readonly int _index; + + public Position(object segment, int index) + { + _segment = segment; + _index = index; + } + + public Position(object segment) + { + _segment = segment; + _index = 0; + } + + public object Segment => _segment; + public int Index => _index; + + public static explicit operator int(Position position) => position._index; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public (T segment, int index) Get() + { + var segment = _segment == null ? default : (T)_segment; + return (segment, _index); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public T GetSegment() + { + switch (Segment) + { + case null: + return default; + case T segment: + return segment; + } + + ThrowHelper.ThrowInvalidOperationException(ExceptionResource.UnexpectedSegmentType); + return default; + } + + public static bool operator ==(Position left, Position right) => left._index == right._index && left._segment == right._segment; + public static bool operator !=(Position left, Position right) => left._index != right._index || left._segment != right._segment; + + public static Position operator +(Position value, int index) + => new Position(value._segment, value._index + index); + + [EditorBrowsable(EditorBrowsableState.Never)] + public bool Equals(Position position) => this == position; + + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => + obj is Position ? this == (Position)obj : false; + + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + { + var h1 = _segment?.GetHashCode() ?? 0; + var h2 = _index.GetHashCode(); + + var shift5 = ((uint)h1 << 5) | ((uint)h1 >> 27); + return ((int)shift5 + h1) ^ h2; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public override string ToString() => + this == default ? "(default)" : _segment == null ? $"{_index}" : $"{_segment}[{_index}]"; + } +} diff --git a/src/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs b/src/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs deleted file mode 100644 index 8ef158b7734..00000000000 --- a/src/System.Buffers.Primitives/System/Runtime/PrimitiveAttribute.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -namespace System.Runtime -{ - [AttributeUsage(AttributeTargets.GenericParameter)] - public sealed class PrimitiveAttribute : Attribute - { - } -} - diff --git a/src/System.Collections.Sequences/System.Collections.Sequences.csproj b/src/System.Collections.Sequences/System.Collections.Sequences.csproj index ec4d691ebf1..0b32f3dca6a 100644 --- a/src/System.Collections.Sequences/System.Collections.Sequences.csproj +++ b/src/System.Collections.Sequences/System.Collections.Sequences.csproj @@ -8,6 +8,7 @@ http://go.microsoft.com/fwlink/?linkid=833199 + diff --git a/src/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs b/src/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs index 8c0821b33a9..c079436b519 100644 --- a/src/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs +++ b/src/System.Collections.Sequences/System/Collections/Sequences/ArrayList.cs @@ -15,7 +15,7 @@ public sealed class ArrayList : ISequence public int Length => _items.Count; - public Position First => default; + public Position Start => default; public T this[int index] => _items[index]; diff --git a/src/System.Collections.Sequences/System/Collections/Sequences/Position.cs b/src/System.Collections.Sequences/System/Collections/Sequences/Position.cs deleted file mode 100644 index a083f9e2cf2..00000000000 --- a/src/System.Collections.Sequences/System/Collections/Sequences/Position.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.ComponentModel; -using System.Runtime.CompilerServices; - -namespace System.Collections.Sequences -{ - public readonly struct Position : IEquatable - { - readonly object _item; - readonly int _index; - - public static Position Create(T item, int index = 0) where T : class - => item == null ? default : new Position(index, item); - - public static implicit operator Position(int index) => new Position(index, null); - - public static explicit operator int(Position position) => position._index; - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public (T item, int index) Get() { - var item = _item == null ? default : (T) _item; - return (item, _index); - } - - public static bool operator ==(Position left, Position right) => left._index == right._index && left._item == right._item; - public static bool operator !=(Position left, Position right) => left._index != right._index || left._item != right._item; - - public static Position operator +(Position value, int index) - => new Position(value._index + index, value._item); - - [EditorBrowsable(EditorBrowsableState.Never)] - public bool Equals(Position position) => this == position; - - [EditorBrowsable(EditorBrowsableState.Never)] - public override bool Equals(object obj) => - obj is Position ? this == (Position)obj : false; - - [EditorBrowsable(EditorBrowsableState.Never)] - public override int GetHashCode() => - _index.GetHashCode() ^ (_item == null ? 0 : _item.GetHashCode()); - - [EditorBrowsable(EditorBrowsableState.Never)] - public override string ToString() => - this==default ? "(default)" : _item == null ? $"{_index}" : $"{_index}, {_item}"; - - private Position(int index, object item) - { - _item = item; - _index = index; - } - private Position(int index) - { - _item = null; - _index = index; - } - } -} diff --git a/src/System.IO.Pipelines.Extensions/DefaultReadableBufferExtensions.cs b/src/System.IO.Pipelines.Extensions/DefaultReadableBufferExtensions.cs index 4d1eab794a0..adeb2c28964 100644 --- a/src/System.IO.Pipelines.Extensions/DefaultReadableBufferExtensions.cs +++ b/src/System.IO.Pipelines.Extensions/DefaultReadableBufferExtensions.cs @@ -1,4 +1,5 @@ using System.Buffers; +using System.Collections.Sequences; using System.Numerics; using System.Runtime.CompilerServices; diff --git a/src/System.IO.Pipelines.Extensions/ReadWriteExtensions.cs b/src/System.IO.Pipelines.Extensions/ReadWriteExtensions.cs index b152f4e2c5e..128e47e64be 100644 --- a/src/System.IO.Pipelines.Extensions/ReadWriteExtensions.cs +++ b/src/System.IO.Pipelines.Extensions/ReadWriteExtensions.cs @@ -179,3 +179,11 @@ public static void WriteLittleEndian<[Primitive]T>(this WritableBuffer buffer, T } } } + +namespace System.Runtime +{ + [AttributeUsage(AttributeTargets.GenericParameter)] + public sealed class PrimitiveAttribute : Attribute + { + } +} diff --git a/src/System.IO.Pipelines.Extensions/ReadableBufferSequence.cs b/src/System.IO.Pipelines.Extensions/ReadableBufferSequence.cs index f530aff3a63..ed8515a6d6d 100644 --- a/src/System.IO.Pipelines.Extensions/ReadableBufferSequence.cs +++ b/src/System.IO.Pipelines.Extensions/ReadableBufferSequence.cs @@ -3,7 +3,6 @@ using System.Buffers; using System.Collections.Sequences; -using Position = System.Buffers.Position; namespace System.IO.Pipelines { @@ -16,16 +15,16 @@ public ReadableBufferSequence(ReadOnlyBuffer buffer) : this() _buffer = buffer; } - public Collections.Sequences.Position First => Collections.Sequences.Position.Create(_buffer.Start.Segment, _buffer.Start.Index); + public Position Start => new Position(_buffer.Start.Segment, _buffer.Start.Index); - public bool TryGet(ref Collections.Sequences.Position position, out ReadOnlyMemory item, bool advance = true) + public bool TryGet(ref Position position, out ReadOnlyMemory item, bool advance = true) { var (data, index) = position.Get(); var p = new Position(data, index); var result = _buffer.TryGet(ref p, out item); if (advance) { - position = Collections.Sequences.Position.Create(p.Segment, p.Index); + position = new Position(p.Segment, p.Index); } return result; diff --git a/src/System.IO.Pipelines.Text.Primitives/SplitEnumerable.cs b/src/System.IO.Pipelines.Text.Primitives/SplitEnumerable.cs index f8b7abb0fbe..2ddbd326275 100644 --- a/src/System.IO.Pipelines.Text.Primitives/SplitEnumerable.cs +++ b/src/System.IO.Pipelines.Text.Primitives/SplitEnumerable.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Collections; using System.Collections.Generic; +using System.Collections.Sequences; namespace System.IO.Pipelines.Text.Primitives { diff --git a/src/System.IO.Pipelines.Text.Primitives/SplitEnumerator.cs b/src/System.IO.Pipelines.Text.Primitives/SplitEnumerator.cs index 40051f53ce0..93b5e131322 100644 --- a/src/System.IO.Pipelines.Text.Primitives/SplitEnumerator.cs +++ b/src/System.IO.Pipelines.Text.Primitives/SplitEnumerator.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Collections; using System.Collections.Generic; +using System.Collections.Sequences; namespace System.IO.Pipelines.Text.Primitives { diff --git a/src/System.IO.Pipelines/System/IO/Pipelines/IPipeReader.cs b/src/System.IO.Pipelines/System/IO/Pipelines/IPipeReader.cs index ebe82de2182..856240f0254 100644 --- a/src/System.IO.Pipelines/System/IO/Pipelines/IPipeReader.cs +++ b/src/System.IO.Pipelines/System/IO/Pipelines/IPipeReader.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Buffers; +using System.Collections.Sequences; using System.Threading; namespace System.IO.Pipelines diff --git a/src/System.IO.Pipelines/System/IO/Pipelines/Pipe.cs b/src/System.IO.Pipelines/System/IO/Pipelines/Pipe.cs index 8c5175b3971..ef52d2ef15f 100644 --- a/src/System.IO.Pipelines/System/IO/Pipelines/Pipe.cs +++ b/src/System.IO.Pipelines/System/IO/Pipelines/Pipe.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Buffers; +using System.Collections.Sequences; using System.Diagnostics; using System.Runtime.CompilerServices; @@ -411,7 +412,7 @@ void IPipeReader.Advance(Position consumed, Position examined) examinedEverything = _commitHead != null ? examined.Index == _commitHeadIndex - _commitHead.Start : examined.Index == 0; } - if (!consumed.IsDefault) + if (consumed.Segment != null) { if (_readHead == null) { @@ -419,7 +420,7 @@ void IPipeReader.Advance(Position consumed, Position examined) return; } - var consumedSegment = consumed.Get(); + var consumedSegment = consumed.GetSegment(); returnStart = _readHead; returnEnd = consumedSegment; diff --git a/src/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs b/src/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs index 655bede0c9f..5f76176ace6 100644 --- a/src/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs +++ b/src/System.Text.Formatting/System/Text/Formatting/Formatters/SequenceFormatter.cs @@ -5,7 +5,6 @@ using System.Buffers; using System.Buffers.Text; using System.Collections.Sequences; -using Position = System.Collections.Sequences.Position; namespace System.Text.Formatting { @@ -32,7 +31,7 @@ public SequenceFormatter(TSequence buffers, SymbolTable symbolTable) { _symbolTable = symbolTable; _buffers = buffers; - _currentPosition = _buffers.First; + _currentPosition = _buffers.Start; _previousWrittenBytes = -1; } diff --git a/src/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs b/src/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs index 47c88dbccb4..2b7ca4eceb4 100644 --- a/src/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs +++ b/src/System.Text.Formatting/System/Text/Parsing/SequenceParser.cs @@ -4,7 +4,6 @@ using System.Buffers; using System.Buffers.Text; using System.Collections.Sequences; -using Position = System.Collections.Sequences.Position; namespace System.Text.Parsing { diff --git a/src/System.Text.Http.Parser/HttpParser.cs b/src/System.Text.Http.Parser/HttpParser.cs index dd1384713dc..d6ee38fbf55 100644 --- a/src/System.Text.Http.Parser/HttpParser.cs +++ b/src/System.Text.Http.Parser/HttpParser.cs @@ -8,7 +8,6 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.Http.Parser.Internal; -using Position = System.Buffers.Position; namespace System.Text.Http.Parser { @@ -238,8 +237,8 @@ public unsafe bool ParseHeaders(T handler, in ReadOnlyBuffer buffer, out Posi var bufferEnd = buffer.End; - var reader = new ReadOnlyBufferReader(buffer); - var start = default(ReadOnlyBufferReader); + var reader = new BufferReader(buffer); + var start = default(BufferReader); var done = false; try @@ -323,7 +322,7 @@ public unsafe bool ParseHeaders(T handler, in ReadOnlyBuffer buffer, out Posi var current = reader.Cursor; // Split buffers - if (ReadCursorOperations.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1) + if (ReadOnlyBuffer.Seek(current, bufferEnd, out var lineEnd, ByteLF) == -1) { // Not there return false; @@ -370,7 +369,7 @@ public unsafe bool ParseHeaders(ref T handler, ReadOnlyBytes buffer, out int { var index = 0; consumedBytes = 0; - Collections.Sequences.Position position = buffer.First; + Position position = buffer.Start; if(!buffer.TryGet(ref position, out ReadOnlyMemory currentMemory)) { @@ -641,7 +640,7 @@ private static unsafe bool Contains(byte* searchSpace, int length, byte value) private static bool TryGetNewLineSpan(in ReadOnlyBuffer buffer, out Position found) { var start = buffer.Start; - if (ReadCursorOperations.Seek(start, buffer.End, out found, ByteLF) != -1) + if (ReadOnlyBuffer.Seek(start, buffer.End, out found, ByteLF) != -1) { // Move 1 byte past the \n found = buffer.Move(found, 1); diff --git a/src/System.Text.Http.Parser/IHttpParser.cs b/src/System.Text.Http.Parser/IHttpParser.cs index 06e13d1a7a5..25bfa0274c7 100644 --- a/src/System.Text.Http.Parser/IHttpParser.cs +++ b/src/System.Text.Http.Parser/IHttpParser.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System.Buffers; -using System.IO.Pipelines; +using System.Collections.Sequences; namespace System.Text.Http.Parser { diff --git a/src/System.Text.Utf8String/System/Text/Utf8Span.cs b/src/System.Text.Utf8String/System/Text/Utf8Span.cs index 190b432f177..2615796f41e 100644 --- a/src/System.Text.Utf8String/System/Text/Utf8Span.cs +++ b/src/System.Text.Utf8String/System/Text/Utf8Span.cs @@ -162,7 +162,7 @@ public override int GetHashCode() public static bool operator !=(string left, Utf8Span right) => !right.Equals(left); - public int CompareTo(Utf8Span other) => Bytes.SequenceCompareTo(other.Bytes); + public int CompareTo(Utf8Span other) => SequenceCompareTo(Bytes, other.Bytes); public int CompareTo(Utf8String other) => CompareTo(other.Span); @@ -455,5 +455,17 @@ public int LastIndexOf(uint codePoint) return StringNotFound; } #endregion + + static int SequenceCompareTo(ReadOnlySpan left, ReadOnlySpan right) + { + var minLength = left.Length; + if (minLength > right.Length) minLength = right.Length; + for (int i = 0; i < minLength; i++) + { + var result = left[i].CompareTo(right[i]); + if (result != 0) return result; + } + return left.Length.CompareTo(right.Length); + } } } diff --git a/tests/Benchmarks/BytesReaderBench.cs b/tests/Benchmarks/BytesReaderBench.cs index 152c7883312..9606cbca6cc 100644 --- a/tests/Benchmarks/BytesReaderBench.cs +++ b/tests/Benchmarks/BytesReaderBench.cs @@ -80,7 +80,7 @@ static void ParseInt32ReadableBufferReader() foreach (var iteration in Benchmark.Iterations) { var buffer = new ReadOnlyBuffer(s_data); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); using (iteration.StartMeasurement()) { diff --git a/tests/Benchmarks/HttpParserBench.cs b/tests/Benchmarks/HttpParserBench.cs index 5d6ed3c33ed..72dacf0bbe6 100644 --- a/tests/Benchmarks/HttpParserBench.cs +++ b/tests/Benchmarks/HttpParserBench.cs @@ -7,11 +7,8 @@ using System.Buffers; using System.Collections.Generic; using System.Collections.Sequences; -using System.IO.Pipelines; using System.Text; -using System.Text.Http; using System.Text.Http.Parser; -using Position = System.Buffers.Position; public class HttpParserBench { @@ -74,8 +71,8 @@ static bool RequestLineRobCursors() var buffer = new ReadOnlyBytes(s_plaintextTechEmpowerRequestBytes); var parser = new HttpParser(); var request = new Request(); - System.Collections.Sequences.Position consumed = default; - System.Collections.Sequences.Position read; + Position consumed = default; + Position read; bool success = true; foreach (var iteration in Benchmark.Iterations) @@ -171,8 +168,8 @@ static bool HeadersRobCursors() var buffer = new ReadOnlyBytes(s_plaintextTechEmpowerHeadersBytes); var parser = new HttpParser(); var request = new Request(); - System.Collections.Sequences.Position consumed = default; - System.Collections.Sequences.Position examined; + Position consumed = default; + Position examined; int consumedBytes; bool success = true; @@ -327,8 +324,8 @@ static bool FullRequestRobCursors() var buffer = new ReadOnlyBytes(s_plaintextTechEmpowerRequestBytes); var parser = new HttpParser(); var request = new RequestStruct(); - System.Collections.Sequences.Position consumed = default; - System.Collections.Sequences.Position examined; + Position consumed = default; + Position examined; bool success = true; foreach (var iteration in Benchmark.Iterations) @@ -352,7 +349,7 @@ static bool FullRequestRobCursors() static class HttpParserExtensions { - public static bool ParseRequestLine(this HttpParser parser, ref T handler, in ReadOnlyBytes buffer, out System.Collections.Sequences.Position consumed, out System.Collections.Sequences.Position examined) where T : IHttpRequestLineHandler + public static bool ParseRequestLine(this HttpParser parser, ref T handler, in ReadOnlyBytes buffer, out Position consumed, out Position examined) where T : IHttpRequestLineHandler { if(parser.ParseRequestLine(ref handler, buffer, out int consumedBytes)) { @@ -365,7 +362,7 @@ public static bool ParseRequestLine(this HttpParser parser, ref T handler, in return false; } - public static bool ParseHeaders(this HttpParser parser, ref T handler, in ReadOnlyBytes buffer, out System.Collections.Sequences.Position consumed, out System.Collections.Sequences.Position examined, out int consumedBytes) where T : IHttpHeadersHandler + public static bool ParseHeaders(this HttpParser parser, ref T handler, in ReadOnlyBytes buffer, out Position consumed, out Position examined, out int consumedBytes) where T : IHttpHeadersHandler { if (parser.ParseHeaders(ref handler, buffer, out consumedBytes)) { @@ -378,7 +375,7 @@ public static bool ParseHeaders(this HttpParser parser, ref T handler, in Rea return false; } - public static bool ParseRequest(this HttpParser parser, ref T handler, in ReadOnlyBytes buffer, out System.Collections.Sequences.Position consumed, out System.Collections.Sequences.Position examined) where T : IHttpRequestLineHandler, IHttpHeadersHandler + public static bool ParseRequest(this HttpParser parser, ref T handler, in ReadOnlyBytes buffer, out Position consumed, out Position examined) where T : IHttpRequestLineHandler, IHttpHeadersHandler { if ( parser.ParseRequestLine(ref handler, buffer, out var consumedRLBytes) && diff --git a/tests/System.Buffers.Primitives.Tests/BufferEqualityTests.cs b/tests/System.Buffers.Experimental.Tests/BufferEqualityTests.cs similarity index 100% rename from tests/System.Buffers.Primitives.Tests/BufferEqualityTests.cs rename to tests/System.Buffers.Experimental.Tests/BufferEqualityTests.cs diff --git a/tests/System.Buffers.Experimental.Tests/BytesReaderTests.cs b/tests/System.Buffers.Experimental.Tests/BytesReaderTests.cs index 6a5e8eda315..5c5beb27a63 100644 --- a/tests/System.Buffers.Experimental.Tests/BytesReaderTests.cs +++ b/tests/System.Buffers.Experimental.Tests/BytesReaderTests.cs @@ -172,7 +172,7 @@ public static string ToString(this TSequence bytes, SymbolTable symbo var sb = new StringBuilder(); if (symbolTable == SymbolTable.InvariantUtf8) { - Collections.Sequences.Position position = bytes.First; + Position position = bytes.Start; while (bytes.TryGet(ref position, out ReadOnlyMemory segment)) { sb.Append(new Utf8Span(segment.Span).ToString()); @@ -189,7 +189,7 @@ public static string Utf8ToString(this TSequence bytes) where TSequen { var sb = new StringBuilder(); - Collections.Sequences.Position position = bytes.First; + Position position = bytes.Start; while (bytes.TryGet(ref position, out ReadOnlyMemory segment)) { sb.Append(new Utf8Span(segment.Span).ToString()); diff --git a/tests/System.Buffers.Experimental.Tests/ReadOnlyBytesTests.cs b/tests/System.Buffers.Experimental.Tests/ReadOnlyBytesTests.cs index 402d783fd0d..cb18b5179ae 100644 --- a/tests/System.Buffers.Experimental.Tests/ReadOnlyBytesTests.cs +++ b/tests/System.Buffers.Experimental.Tests/ReadOnlyBytesTests.cs @@ -357,7 +357,7 @@ public void ReadOnlyBytesEnumeration() { var buffer = new byte[] { 1, 2, 3, 4, 5, 6 }; var bytes = new ReadOnlyBytes(buffer); - Collections.Sequences.Position position = bytes.First; + Position position = bytes.Start; int length = 0; ReadOnlyMemory segment; while (bytes.TryGet(ref position, out segment)) @@ -367,7 +367,7 @@ public void ReadOnlyBytesEnumeration() Assert.Equal(buffer.Length, length); var multibytes = Parse("A|CD|EFG"); - position = multibytes.First; + position = multibytes.Start; length = 0; while (multibytes.TryGet(ref position, out segment)) { @@ -401,7 +401,7 @@ public void ReadOnlyTailBytesEnumeration() multibytes = multibytes.Slice(i); { - Collections.Sequences.Position position = multibytes.First; + Position position = multibytes.Start; var length = 0; while (multibytes.TryGet(ref position, out ReadOnlyMemory segment)) { @@ -429,7 +429,7 @@ public void ReadOnlyFrontBytesEnumeration() multibytes = multibytes.Slice(0, i); { - Collections.Sequences.Position position = multibytes.First; + Position position = multibytes.Start; var length = 0; while (multibytes.TryGet(ref position, out ReadOnlyMemory segment)) { diff --git a/tests/System.Buffers.Experimental.Tests/SequenceExtensionsTests.cs b/tests/System.Buffers.Experimental.Tests/SequenceExtensionsTests.cs index 20d72d09a83..9530bce5459 100644 --- a/tests/System.Buffers.Experimental.Tests/SequenceExtensionsTests.cs +++ b/tests/System.Buffers.Experimental.Tests/SequenceExtensionsTests.cs @@ -139,7 +139,7 @@ public void TryParseInt32Multisegment(int expected) Assert.True(Sequence.TryParse(bytes, out int value, out int consumed)); Assert.Equal(expected, value); - Assert.True(Sequence.TryParse(bytes, out value, out Collections.Sequences.Position consumedPosition)); + Assert.True(Sequence.TryParse(bytes, out value, out Position consumedPosition)); Assert.Equal(expected, value); var afterValue = bytes.Slice(consumedPosition); diff --git a/tests/System.Buffers.Primitives.Tests/BufferUtilities.cs b/tests/System.Buffers.Primitives.Tests/BufferUtilities.cs index ff50fd60ef6..cb808c684e6 100644 --- a/tests/System.Buffers.Primitives.Tests/BufferUtilities.cs +++ b/tests/System.Buffers.Primitives.Tests/BufferUtilities.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Collections.Sequences; using System.Text; namespace System.IO.Pipelines.Testing diff --git a/tests/System.Buffers.Primitives.Tests/TestBufferFactory.cs b/tests/System.Buffers.Primitives.Tests/ReadOnlyBufferFactory.cs similarity index 78% rename from tests/System.Buffers.Primitives.Tests/TestBufferFactory.cs rename to tests/System.Buffers.Primitives.Tests/ReadOnlyBufferFactory.cs index 67979a64e57..6754c3b345b 100644 --- a/tests/System.Buffers.Primitives.Tests/TestBufferFactory.cs +++ b/tests/System.Buffers.Primitives.Tests/ReadOnlyBufferFactory.cs @@ -10,12 +10,12 @@ namespace System.IO.Pipelines.Tests { - internal abstract class TestBufferFactory + public abstract class ReadOnlyBufferFactory { - public static TestBufferFactory Array { get; } = new ArrayTestBufferFactory(); - public static TestBufferFactory OwnedMemory { get; } = new OwnedMemoryTestBufferFactory(); - public static TestBufferFactory SingleSegment { get; } = new SingleSegmentTestBufferFactory(); - public static TestBufferFactory SegmentPerByte { get; } = new BytePerSegmentTestBufferFactory(); + public static ReadOnlyBufferFactory Array { get; } = new ArrayTestBufferFactory(); + public static ReadOnlyBufferFactory OwnedMemory { get; } = new OwnedMemoryTestBufferFactory(); + public static ReadOnlyBufferFactory SingleSegment { get; } = new SingleSegmentTestBufferFactory(); + public static ReadOnlyBufferFactory SegmentPerByte { get; } = new BytePerSegmentTestBufferFactory(); public abstract ReadOnlyBuffer CreateOfSize(int size); public abstract ReadOnlyBuffer CreateWithContent(byte[] data); @@ -25,7 +25,7 @@ public ReadOnlyBuffer CreateWithContent(string data) return CreateWithContent(Encoding.ASCII.GetBytes(data)); } - internal class ArrayTestBufferFactory : TestBufferFactory + internal class ArrayTestBufferFactory : ReadOnlyBufferFactory { public override ReadOnlyBuffer CreateOfSize(int size) { @@ -40,7 +40,7 @@ public override ReadOnlyBuffer CreateWithContent(byte[] data) } } - internal class OwnedMemoryTestBufferFactory : TestBufferFactory + internal class OwnedMemoryTestBufferFactory : ReadOnlyBufferFactory { public override ReadOnlyBuffer CreateOfSize(int size) { @@ -55,7 +55,7 @@ public override ReadOnlyBuffer CreateWithContent(byte[] data) } } - internal class SingleSegmentTestBufferFactory: TestBufferFactory + internal class SingleSegmentTestBufferFactory: ReadOnlyBufferFactory { public override ReadOnlyBuffer CreateOfSize(int size) { @@ -68,7 +68,7 @@ public override ReadOnlyBuffer CreateWithContent(byte[] data) } } - internal class BytePerSegmentTestBufferFactory: TestBufferFactory + internal class BytePerSegmentTestBufferFactory: ReadOnlyBufferFactory { public override ReadOnlyBuffer CreateOfSize(int size) { diff --git a/tests/System.Buffers.Primitives.Tests/ReadableBufferFacts.cs b/tests/System.Buffers.Primitives.Tests/ReadableBufferFacts.cs index f1bfc173741..a55e33d8fe8 100644 --- a/tests/System.Buffers.Primitives.Tests/ReadableBufferFacts.cs +++ b/tests/System.Buffers.Primitives.Tests/ReadableBufferFacts.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Collections.Sequences; using System.IO.Pipelines.Testing; using System.Linq; using Xunit; @@ -13,22 +14,22 @@ public abstract class ReadableBufferFacts { public class Array: ReadableBufferFacts { - public Array() : base(TestBufferFactory.Array) { } + public Array() : base(ReadOnlyBufferFactory.Array) { } } public class OwnedMemory: ReadableBufferFacts { - public OwnedMemory() : base(TestBufferFactory.OwnedMemory) { } + public OwnedMemory() : base(ReadOnlyBufferFactory.OwnedMemory) { } } public class SingleSegment: ReadableBufferFacts { - public SingleSegment() : base(TestBufferFactory.SingleSegment) { } + public SingleSegment() : base(ReadOnlyBufferFactory.SingleSegment) { } } public class SegmentPerByte: ReadableBufferFacts { - public SegmentPerByte() : base(TestBufferFactory.SegmentPerByte) { } + public SegmentPerByte() : base(ReadOnlyBufferFactory.SegmentPerByte) { } [Fact] // This test verifies that optimization for known cursors works and @@ -37,13 +38,13 @@ public void ReadCursorSeekDoesNotCheckEndIfTrustingEnd() { var buffer = Factory.CreateOfSize(3); var buffer2 = Factory.CreateOfSize(3); - ReadCursorOperations.Seek(buffer.Start, buffer2.End, 2, false); + ReadOnlyBuffer.Seek(buffer.Start, buffer2.End, 2, false); } } - internal TestBufferFactory Factory { get; } + internal ReadOnlyBufferFactory Factory { get; } - internal ReadableBufferFacts(TestBufferFactory factory) + internal ReadableBufferFacts(ReadOnlyBufferFactory factory) { Factory = factory; } @@ -111,7 +112,7 @@ public void ReadCursorSeekChecksEndIfNotTrustingEnd() { var buffer = Factory.CreateOfSize(3); var buffer2 = Factory.CreateOfSize(3); - Assert.Throws(() => ReadCursorOperations.Seek(buffer.Start, buffer2.End, 2, true)); + Assert.Throws(() => ReadOnlyBuffer.Seek(buffer.Start, buffer2.End, 2, true)); } [Fact] diff --git a/tests/System.Buffers.Primitives.Tests/ReadableBufferReaderFacts.cs b/tests/System.Buffers.Primitives.Tests/ReadableBufferReaderFacts.cs index d4862a8dbf4..5fa5ddc38be 100644 --- a/tests/System.Buffers.Primitives.Tests/ReadableBufferReaderFacts.cs +++ b/tests/System.Buffers.Primitives.Tests/ReadableBufferReaderFacts.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Collections.Sequences; using System.IO.Pipelines.Testing; using Xunit; @@ -12,24 +13,24 @@ public abstract class ReadableBufferReaderFacts { public class Array: SingleSegment { - public Array() : base(TestBufferFactory.Array) { } - internal Array(TestBufferFactory factory) : base(factory) { } + public Array() : base(ReadOnlyBufferFactory.Array) { } + internal Array(ReadOnlyBufferFactory factory) : base(factory) { } } public class OwnedMemory: SingleSegment { - public OwnedMemory() : base(TestBufferFactory.OwnedMemory) { } + public OwnedMemory() : base(ReadOnlyBufferFactory.OwnedMemory) { } } public class SingleSegment: SegmentPerByte { - public SingleSegment() : base(TestBufferFactory.SingleSegment) { } - internal SingleSegment(TestBufferFactory factory) : base(factory) { } + public SingleSegment() : base(ReadOnlyBufferFactory.SingleSegment) { } + internal SingleSegment(ReadOnlyBufferFactory factory) : base(factory) { } [Fact] public void SkipSingleBufferSkipsBytes() { - var reader = new ReadOnlyBufferReader(BufferUtilities.CreateBuffer(new byte[] { 1, 2, 3, 4, 5 })); + var reader = new BufferReader(BufferUtilities.CreateBuffer(new byte[] { 1, 2, 3, 4, 5 })); reader.Skip(2); Assert.Equal(2, reader.Index); Assert.Equal(3, reader.Span[reader.Index]); @@ -43,7 +44,7 @@ public void SkipSingleBufferSkipsBytes() [Fact] public void TakeReturnsByteAndMoves() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); Assert.Equal(0, reader.Index); Assert.Equal(1, reader.Span[reader.Index]); Assert.Equal(1, reader.Take()); @@ -56,13 +57,13 @@ public void TakeReturnsByteAndMoves() public class SegmentPerByte: ReadableBufferReaderFacts { - public SegmentPerByte() : base(TestBufferFactory.SegmentPerByte) { } - internal SegmentPerByte(TestBufferFactory factory) : base(factory) { } + public SegmentPerByte() : base(ReadOnlyBufferFactory.SegmentPerByte) { } + internal SegmentPerByte(ReadOnlyBufferFactory factory) : base(factory) { } } - internal TestBufferFactory Factory { get; } + internal ReadOnlyBufferFactory Factory { get; } - internal ReadableBufferReaderFacts(TestBufferFactory factory) + internal ReadableBufferReaderFacts(ReadOnlyBufferFactory factory) { Factory = factory; } @@ -70,7 +71,7 @@ internal ReadableBufferReaderFacts(TestBufferFactory factory) [Fact] public void PeekReturnsByteWithoutMoving() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); Assert.Equal(1, reader.Peek()); Assert.Equal(1, reader.Peek()); } @@ -78,7 +79,7 @@ public void PeekReturnsByteWithoutMoving() [Fact] public void CursorIsCorrectAtEnd() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); reader.Take(); reader.Take(); Assert.True(reader.End); @@ -97,7 +98,7 @@ public void CursorIsCorrectWithEmptyLastBlock() var start = new Position(first, first.Start); var end = new Position(last, last.Start); - var reader = new ReadOnlyBufferReader(new ReadOnlyBuffer(start, end)); + var reader = new BufferReader(new ReadOnlyBuffer(start, end)); reader.Take(); reader.Take(); reader.Take(); @@ -109,7 +110,7 @@ public void CursorIsCorrectWithEmptyLastBlock() [Fact] public void PeekReturnsMinuOneByteInTheEnd() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { 1, 2 })); Assert.Equal(1, reader.Take()); Assert.Equal(2, reader.Take()); Assert.Equal(-1, reader.Peek()); @@ -118,7 +119,7 @@ public void PeekReturnsMinuOneByteInTheEnd() [Fact] public void SkipToEndThenPeekReturnsMinusOne() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { 1, 2, 3, 4, 5 })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { 1, 2, 3, 4, 5 })); reader.Skip(5); Assert.True(reader.End); Assert.Equal(-1, reader.Peek()); @@ -127,7 +128,7 @@ public void SkipToEndThenPeekReturnsMinusOne() [Fact] public void SkippingPastLengthThrows() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { 1, 2, 3, 4, 5 })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { 1, 2, 3, 4, 5 })); try { reader.Skip(6); @@ -143,7 +144,7 @@ public void SkippingPastLengthThrows() public void CtorFindsFirstNonEmptySegment() { var buffer = Factory.CreateWithContent(new byte[] { 1 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); Assert.Equal(1, reader.Peek()); } @@ -152,7 +153,7 @@ public void CtorFindsFirstNonEmptySegment() public void EmptySegmentsAreSkippedOnMoveNext() { var buffer = Factory.CreateWithContent(new byte[] { 1, 2 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); Assert.Equal(1, reader.Peek()); reader.Skip(1); @@ -163,7 +164,7 @@ public void EmptySegmentsAreSkippedOnMoveNext() public void PeekGoesToEndIfAllEmptySegments() { var buffer = BufferUtilities.CreateBuffer(new[] { new byte[] { }, new byte[] { }, new byte[] { }, new byte[] { } }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); Assert.Equal(-1, reader.Peek()); Assert.True(reader.End); @@ -173,7 +174,7 @@ public void PeekGoesToEndIfAllEmptySegments() public void SkipTraversesSegments() { var buffer = Factory.CreateWithContent(new byte[] { 1, 2, 3 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); reader.Skip(2); Assert.Equal(3, reader.Span[reader.Index]); @@ -184,7 +185,7 @@ public void SkipTraversesSegments() public void SkipThrowsPastLengthMultipleSegments() { var buffer = Factory.CreateWithContent(new byte[] { 1, 2, 3 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); try { @@ -201,7 +202,7 @@ public void SkipThrowsPastLengthMultipleSegments() public void TakeTraversesSegments() { var buffer = Factory.CreateWithContent(new byte[] { 1, 2, 3 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); Assert.Equal(1, reader.Take()); Assert.Equal(2, reader.Take()); @@ -213,7 +214,7 @@ public void TakeTraversesSegments() public void PeekTraversesSegments() { var buffer = Factory.CreateWithContent(new byte[] { 1, 2 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); Assert.Equal(1, reader.Span[reader.Index]); Assert.Equal(1, reader.Take()); @@ -229,7 +230,7 @@ public void PeekTraversesSegments() public void PeekWorkesWithEmptySegments() { var buffer = Factory.CreateWithContent(new byte[] { 1 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); Assert.Equal(0, reader.Index); Assert.Equal(1, reader.Span.Length); @@ -242,7 +243,7 @@ public void PeekWorkesWithEmptySegments() [Fact] public void WorkesWithEmptyBuffer() { - var reader = new ReadOnlyBufferReader(Factory.CreateWithContent(new byte[] { })); + var reader = new BufferReader(Factory.CreateWithContent(new byte[] { })); Assert.Equal(0, reader.Index); Assert.Equal(0, reader.Span.Length); @@ -260,13 +261,13 @@ public void WorkesWithEmptyBuffer() public void ReturnsCorrectCursor(int takes, bool end) { var readableBuffer = Factory.CreateWithContent(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); - var reader = new ReadOnlyBufferReader(readableBuffer); + var reader = new BufferReader(readableBuffer); for (int i = 0; i < takes; i++) { reader.Take(); } - var expected = end ? new byte[] {} : readableBuffer.Slice(takes).ToArray(); + var expected = end ? new byte[] {} : readableBuffer.Slice((long)takes).ToArray(); Assert.Equal(expected, readableBuffer.Slice(reader.Cursor).ToArray()); } @@ -274,9 +275,9 @@ public void ReturnsCorrectCursor(int takes, bool end) public void SlicingBufferReturnsCorrectCursor() { var buffer = Factory.CreateWithContent(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }); - var sliced = buffer.Slice(2); + var sliced = buffer.Slice(2L); - var reader = new ReadOnlyBufferReader(sliced); + var reader = new BufferReader(sliced); Assert.Equal(sliced.ToArray(), buffer.Slice(reader.Cursor).ToArray()); Assert.Equal(2, reader.Peek()); Assert.Equal(0, reader.Index); @@ -286,7 +287,7 @@ public void SlicingBufferReturnsCorrectCursor() public void ReaderIndexIsCorrect() { var buffer = Factory.CreateWithContent(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }); - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); var counter = 1; while (!reader.End) diff --git a/tests/System.Collections.Sequences.Tests/SampleCollections/Hashtable.cs b/tests/System.Collections.Sequences.Tests/SampleCollections/Hashtable.cs index a8d90d7a376..1aebb813461 100644 --- a/tests/System.Collections.Sequences.Tests/SampleCollections/Hashtable.cs +++ b/tests/System.Collections.Sequences.Tests/SampleCollections/Hashtable.cs @@ -87,7 +87,7 @@ private int GetNextPrime(int value) public int Length => _count; - public Position First => default; + public Position Start => default; public bool TryGet(ref Position position, out KeyValuePair item, bool advance = true) { @@ -105,7 +105,7 @@ public bool TryGet(ref Position position, out KeyValuePair item, bool adva return false; } - position = firstOccupiedSlot; + position = new Position(null, firstOccupiedSlot); } var index = (int)position; @@ -116,7 +116,7 @@ public bool TryGet(ref Position position, out KeyValuePair item, bool adva if (advance) { var first = FindFirstStartingAt(index + 1); - position = first; + position = new Position(null, first); if (first == -1) { position = default; } diff --git a/tests/System.Collections.Sequences.Tests/SampleCollections/LinkedContainer.cs b/tests/System.Collections.Sequences.Tests/SampleCollections/LinkedContainer.cs index c5f8d6bec11..f0d3f8fd948 100644 --- a/tests/System.Collections.Sequences.Tests/SampleCollections/LinkedContainer.cs +++ b/tests/System.Collections.Sequences.Tests/SampleCollections/LinkedContainer.cs @@ -26,7 +26,7 @@ public void Add(T item) public int Length => _count; - public Position First => Position.Create(_head); + public Position Start => new Position(_head, 0); public bool TryGet(ref Position position, out T item, bool advance = true) { @@ -44,7 +44,7 @@ public bool TryGet(ref Position position, out T item, bool advance = true) } item = node._item; - if (advance) { position = Position.Create(node._next); } + if (advance) { position = new Position(node._next, 0); } return true; } diff --git a/tests/System.IO.Pipelines.Extensions.Tests/PipelineReaderWriterFacts.cs b/tests/System.IO.Pipelines.Extensions.Tests/PipelineReaderWriterFacts.cs index 34c6c2605bd..bd3f5805aef 100644 --- a/tests/System.IO.Pipelines.Extensions.Tests/PipelineReaderWriterFacts.cs +++ b/tests/System.IO.Pipelines.Extensions.Tests/PipelineReaderWriterFacts.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Buffers; +using System.Collections.Sequences; using System.Linq; using System.Text; using System.Threading.Tasks; diff --git a/tests/System.IO.Pipelines.Extensions.Tests/ReadableBufferFacts.cs b/tests/System.IO.Pipelines.Extensions.Tests/ReadableBufferFacts.cs index 842362b3fe1..c56014a004f 100644 --- a/tests/System.IO.Pipelines.Extensions.Tests/ReadableBufferFacts.cs +++ b/tests/System.IO.Pipelines.Extensions.Tests/ReadableBufferFacts.cs @@ -17,7 +17,6 @@ using Xunit; using static System.Buffers.Binary.BinaryPrimitives; -using Position = System.Buffers.Position; namespace System.IO.Pipelines.Tests { @@ -47,7 +46,7 @@ public void Dispose() public void ReadableBufferSequenceWorks() { var readable = BufferUtilities.CreateBuffer(new byte[] { 1 }, new byte[] { 2, 2 }, new byte[] { 3, 3, 3 }).AsSequence(); - Collections.Sequences.Position position = readable.First; + Position position = readable.Start; int spanCount = 0; while (readable.TryGet(ref position, out ReadOnlyMemory memory)) { diff --git a/tests/System.IO.Pipelines.Performance.Tests/ReadCursorOperationsThroughput.cs b/tests/System.IO.Pipelines.Performance.Tests/ReadCursorOperationsThroughput.cs index e208ae0e32e..ad623d08984 100644 --- a/tests/System.IO.Pipelines.Performance.Tests/ReadCursorOperationsThroughput.cs +++ b/tests/System.IO.Pipelines.Performance.Tests/ReadCursorOperationsThroughput.cs @@ -108,7 +108,7 @@ public void SeekLiveAspNetMultiBufferReadableBufferReader() private static void FindAllNewLinesReadableBufferReader(ReadOnlyBuffer buffer) { - var reader = new ReadOnlyBufferReader(buffer); + var reader = new BufferReader(buffer); var end = buffer.End; while (!reader.End) @@ -130,7 +130,7 @@ private static void FindAllNewLinesReadableBufferReader(ReadOnlyBuffer buffer) { var current = reader.Cursor; - if (ReadCursorOperations.Seek(current, end, out var found, (byte)'\n') == -1) + if (ReadOnlyBuffer.Seek(current, end, out var found, (byte)'\n') == -1) { // We're done return; @@ -158,7 +158,7 @@ private static void FindAllNewLines(ReadOnlyBuffer buffer) while (true) { - if (ReadCursorOperations.Seek(start, end, out var found, (byte)'\n') == -1) + if (ReadOnlyBuffer.Seek(start, end, out var found, (byte)'\n') == -1) { break; } diff --git a/tests/System.Buffers.Primitives.Tests/SeekTests.cs b/tests/System.IO.Pipelines.Tests/SeekTests.cs similarity index 85% rename from tests/System.Buffers.Primitives.Tests/SeekTests.cs rename to tests/System.IO.Pipelines.Tests/SeekTests.cs index 5e346799aaa..9ecc6736af1 100644 --- a/tests/System.Buffers.Primitives.Tests/SeekTests.cs +++ b/tests/System.IO.Pipelines.Tests/SeekTests.cs @@ -9,6 +9,7 @@ using System.IO.Pipelines.Testing; using System.Numerics; using Xunit; +using System.Collections.Sequences; namespace System.IO.Pipelines.Tests { @@ -16,30 +17,30 @@ public abstract class SeekTests { public class Array: SingleSegment { - public Array() : base(TestBufferFactory.Array) { } - internal Array(TestBufferFactory factory) : base(factory) { } + public Array() : base(ReadOnlyBufferFactory.Array) { } + internal Array(ReadOnlyBufferFactory factory) : base(factory) { } } public class OwnedMemory: SingleSegment { - public OwnedMemory() : base(TestBufferFactory.OwnedMemory) { } + public OwnedMemory() : base(ReadOnlyBufferFactory.OwnedMemory) { } } public class SingleSegment: SegmentPerByte { - public SingleSegment() : base(TestBufferFactory.SingleSegment) { } - internal SingleSegment(TestBufferFactory factory) : base(factory) { } + public SingleSegment() : base(ReadOnlyBufferFactory.SingleSegment) { } + internal SingleSegment(ReadOnlyBufferFactory factory) : base(factory) { } } public class SegmentPerByte: SeekTests { - public SegmentPerByte() : base(TestBufferFactory.SegmentPerByte) { } - internal SegmentPerByte(TestBufferFactory factory) : base(factory) { } + public SegmentPerByte() : base(ReadOnlyBufferFactory.SegmentPerByte) { } + internal SegmentPerByte(ReadOnlyBufferFactory factory) : base(factory) { } } - internal TestBufferFactory Factory { get; } + internal ReadOnlyBufferFactory Factory { get; } - internal SeekTests(TestBufferFactory factory) + internal SeekTests(ReadOnlyBufferFactory factory) { Factory = factory; } @@ -76,15 +77,15 @@ public void MemorySeek(string raw, string search, char expectResult, int expectI int found = -1; if (searchFor.Length == 1) { - found = ReadCursorOperations.Seek(start, end, out result, (byte)searchFor[0]); + found = ReadOnlyBuffer.Seek(start, end, out result, (byte)searchFor[0]); } else if (searchFor.Length == 2) { - found = ReadCursorOperations.Seek(start, end, out result, (byte)searchFor[0], (byte)searchFor[1]); + found = ReadOnlyBuffer.Seek(start, end, out result, (byte)searchFor[0], (byte)searchFor[1]); } else if (searchFor.Length == 3) { - found = ReadCursorOperations.Seek(start, end, out result, (byte)searchFor[0], (byte)searchFor[1], (byte)searchFor[2]); + found = ReadOnlyBuffer.Seek(start, end, out result, (byte)searchFor[0], (byte)searchFor[1], (byte)searchFor[2]); } else { @@ -104,9 +105,9 @@ public void TestSeekByteLimitWithinSameBlock(string input, char seek, int limit, // Act var end = limit > input.Length ? buffer.End : buffer.Slice(0, limit).End; - var returnValue = ReadCursorOperations.Seek(buffer.Start, end, out Position result, (byte)seek); - var returnValue_1 = ReadCursorOperations.Seek(buffer.Start, end, out result, (byte)seek, (byte)seek); - var returnValue_2 = ReadCursorOperations.Seek(buffer.Start, end, out result, (byte)seek, (byte)seek, (byte)seek); + var returnValue = ReadOnlyBuffer.Seek(buffer.Start, end, out Position result, (byte)seek); + var returnValue_1 = ReadOnlyBuffer.Seek(buffer.Start, end, out result, (byte)seek, (byte)seek); + var returnValue_2 = ReadOnlyBuffer.Seek(buffer.Start, end, out result, (byte)seek, (byte)seek, (byte)seek); // Assert Assert.Equal(expectedReturnValue, returnValue); @@ -140,17 +141,17 @@ public void TestSeekIteratorLimitWithinSameBlock(string input, char seek, char l var end = buffer.End; // Act - var endReturnValue = ReadCursorOperations.Seek(start, veryEnd, out end, (byte)limitAfter); + var endReturnValue = ReadOnlyBuffer.Seek(start, veryEnd, out end, (byte)limitAfter); if (endReturnValue != -1) { end = buffer.Slice(end, 1).End; } - var returnValue1 = ReadCursorOperations.Seek(start, end, out scan1, (byte)seek); - var returnValue2_1 = ReadCursorOperations.Seek(start, end, out scan2_1, (byte)seek, afterSeek); - var returnValue2_2 = ReadCursorOperations.Seek(start, end, out scan2_2, afterSeek, (byte)seek); - var returnValue3_1 = ReadCursorOperations.Seek(start, end, out scan3_1, (byte)seek, afterSeek, afterSeek); - var returnValue3_2 = ReadCursorOperations.Seek(start, end, out scan3_2, afterSeek, (byte)seek, afterSeek); - var returnValue3_3 = ReadCursorOperations.Seek(start, end, out scan3_3, afterSeek, afterSeek, (byte)seek); + var returnValue1 = ReadOnlyBuffer.Seek(start, end, out scan1, (byte)seek); + var returnValue2_1 = ReadOnlyBuffer.Seek(start, end, out scan2_1, (byte)seek, afterSeek); + var returnValue2_2 = ReadOnlyBuffer.Seek(start, end, out scan2_2, afterSeek, (byte)seek); + var returnValue3_1 = ReadOnlyBuffer.Seek(start, end, out scan3_1, (byte)seek, afterSeek, afterSeek); + var returnValue3_2 = ReadOnlyBuffer.Seek(start, end, out scan3_2, afterSeek, (byte)seek, afterSeek); + var returnValue3_3 = ReadOnlyBuffer.Seek(start, end, out scan3_3, afterSeek, afterSeek, (byte)seek); // Assert diff --git a/tests/System.Text.Http.Parser.Tests/HttpParserTests.cs b/tests/System.Text.Http.Parser.Tests/HttpParserTests.cs index b98b17af52d..1f3c9365ed3 100644 --- a/tests/System.Text.Http.Parser.Tests/HttpParserTests.cs +++ b/tests/System.Text.Http.Parser.Tests/HttpParserTests.cs @@ -4,6 +4,7 @@ using System.Buffers; using System.Buffers.Text; using System.Collections.Generic; +using System.Collections.Sequences; using System.IO.Pipelines; using System.IO.Pipelines.Testing; using System.Linq;