-
Notifications
You must be signed in to change notification settings - Fork 344
Prepared System.Buffer.Primitives for API Review #1993
Prepared System.Buffer.Primitives for API Review #1993
Conversation
@@ -56,7 +56,7 @@ public static int CopyTo(this IMemoryList<byte> list, Span<byte> destination) | |||
{ | |||
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 Collections.Sequences.Position(list, index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
System.Collections.Sequences
is imported, is there a name clash?
i.e. can this be just Position
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, forgot about it. I will remove.
2f0d92d
to
3390b8b
Compare
@@ -180,5 +181,129 @@ public void Create_WorksWithOwnedMemory() | |||
b => b.Slice(0, 70).Slice(0, b.End), | |||
b => b.Slice(70, b.Start) | |||
}; | |||
|
|||
static bool TryGetBuffer(Position begin, Position end, out ReadOnlyMemory<byte> data, out Position next) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can move the tests that call Seek to Pipelines.Tests and then eliminate it. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These tests were testing internal implementations of ROB
why would we want to move them to Pipelines
? Or even worse duplicate code being tested inside the test itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you propose I do? Is there a way to test this without calling ROB's private APIs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make them internal. It has been done in other places to verify implementation details.
using System.Linq; | ||
using System.Text; | ||
|
||
namespace System.IO.Pipelines.Tests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is useful not on only for pipelines, why is it moved back?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's used just by pipelines tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why it builds but it's used by ROB and RBR tests that are in primitives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two copies. I will remove one of them (i.e. the one in pipelines)
return segment; | ||
} | ||
|
||
//ThrowHelper.ThrowInvalidOperationException(ExceptionResource.UnexpectedSegmentType); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why remove throwing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea. Good catch.
@@ -8,7 +8,7 @@ | |||
|
|||
namespace System.IO.Pipelines | |||
{ | |||
public static class ReadCursorOperations | |||
public static class PositionOperations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it moved back to pipelines?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, it's pipelines specific. It does not work with an arbitrary position. It only works with positions of IMemoryList, and possibly other things that ReadOnlyBuffer supports.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It works with everything that ReadOnlyBuffer
supports that's why it's in buffers. There is no need to have another copy in Pipelines.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Position is more general than Buffers. Look in System.Collections.Sequences. There is a Hashtable and ArrayList implementation that uses it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then move these methods to be on ROB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, I have done it initially and it did not work. But now it does. I will fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed it and added InternalsVisible from Pipelines.Tests to ReadOnlyBuffer. We need to design proper seek APIs though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wait, why do you need InternalsVisisbleTo
to Pipelines.Tests
? Just don't move SeekTests.cs
from primitives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too many copies of TryGetBuffer around.
public readonly partial struct ReadOnlyBuffer | ||
{ | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
static bool TryGetBuffer(Position begin, Position end, out ReadOnlyMemory<byte> data, out Position next) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why internal? It can be private
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same thing, there is a test in tests/System.Buffers.Primitives.Tests/ReadableBufferFacts.cs using it.
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
static Position Seek(Position begin, Position end, long bytes, bool checkEndReachable = true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
internal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same: why not private?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the tests from tests/System.Buffers.Primitives.Tests/ReadableBufferFacts.cs do not require copied code or being moved.
} | ||
|
||
[MethodImpl(MethodImplOptions.NoInlining)] | ||
static Position SeekMultiSegment(Position begin, Position end, long bytes, bool checkEndReachable) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private for everything else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do
public static explicit operator int(Position position) => position._index; | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public (T segment, int index) Get<T>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we expect consumers to check if the segment is non-null/default?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on what they use the position for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in most cases they either use it or not. If they don't use it, direct access to Index is enough. If they need both then I prefer throwing to returning default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, we can play with this. But I still want to do an experiment with changing the check to typeof(T) == typeof(Segment). I will try to do it after the new year. If if does not work, we can remove this method.
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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought we were going to limit the ability to modify positions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now have public ctors, Index, and Segment. The + operator is much more hidden than those.
Also, without the operator, code that uses position as index is very wacky. It does not care about the Segment, yet it has to deal with it (in the ctor, at least).
We can think about it more, but I would treat this as a separate PR.
@@ -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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have start at all if we treat default
as a Start
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont think we treat default as start. I remove this early this week.
@@ -10,8 +10,65 @@ namespace System.Buffers | |||
{ | |||
public readonly partial struct ReadOnlyBuffer | |||
{ | |||
public static int Seek(Position begin, Position end, out Position result, byte byte0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change them to be extension/instance methods on ReadOnlyBuffer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's do it separately. I think I have seen some code that calls the APIs with positions other that the buffer's start/end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think Seek
is the last one, but we can do it in a separate pass, just don't like moving things back and forth.
* Unified Positions * Removed fully qualified Position names * Added accidentally removed throw * Removed one copy of TestBufferFactory * Rearrange Seek Methods
@pakrym, @davidfowl, @joshfree, @terrajobst