Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Commit

Permalink
Switch OutputWriter.Write to use ReadOnlySpan<byte> (#2035)
Browse files Browse the repository at this point in the history
* Switch OutputWriter.Write to use Span<>

* ReadOnlySpan
  • Loading branch information
pakrym authored Jan 9, 2018
1 parent 1fecfe7 commit c1286b4
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 58 deletions.
65 changes: 14 additions & 51 deletions src/System.Buffers.Primitives/System/Buffers/OutputWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,79 +35,42 @@ public void Advance(int count)
_output.Advance(count);
}

public void Write(byte[] source)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void Write(ReadOnlySpan<byte> source)
{
if (source.Length > 0 && _span.Length >= source.Length)
if (_span.Length >= source.Length)
{
ref byte pSource = ref source[0];
ref byte pDest = ref MemoryMarshal.GetReference(_span);

Unsafe.CopyBlockUnaligned(ref pDest, ref pSource, (uint)source.Length);

source.CopyTo(_span);
Advance(source.Length);
}
else
{
WriteMultiBuffer(source, 0, source.Length);
WriteMultiBuffer(source);
}
}

public void Write(byte[] source, int offset, int length)
[MethodImpl(MethodImplOptions.NoInlining)]
public void Ensure(int count = 1)
{
// If offset or length is negative the cast to uint will make them larger than int.MaxValue
// so each test both tests for negative values and greater than values. This pattern wil also
// elide the second bounds check that would occur at source[offset]; as is pre-checked
// https://github.com/dotnet/coreclr/pull/9773
if ((uint)offset > (uint)source.Length || (uint)length > (uint)(source.Length - offset))
{
ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset);
}

if (length > 0 && _span.Length >= length)
{
ref byte pSource = ref source[offset];
ref byte pDest = ref MemoryMarshal.GetReference(_span);

Unsafe.CopyBlockUnaligned(ref pDest, ref pSource, (uint)length);

Advance(length);
}
else
{
WriteMultiBuffer(source, offset, length);
}
_output.Enlarge(count);
_span = _output.GetSpan();
}

private void WriteMultiBuffer(byte[] source, int offset, int length)
private void WriteMultiBuffer(ReadOnlySpan<byte> source)
{
var remaining = length;

while (remaining > 0)
while (source.Length > 0)
{
if (_span.Length == 0)
{
Ensure();
}

var writable = Math.Min(remaining, _span.Length);

ref byte pSource = ref source[offset];
ref byte pDest = ref MemoryMarshal.GetReference(_span);

Unsafe.CopyBlockUnaligned(ref pDest, ref pSource, (uint)writable);

var writable = Math.Min(source.Length, _span.Length);
source.Slice(0, writable).CopyTo(_span);
source = source.Slice(writable);
Advance(writable);

remaining -= writable;
offset += writable;
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
public void Ensure(int count = 1)
{
_output.Enlarge(count);
_span = _output.GetSpan();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ public void WriteableBufferWriterWriteFastPlaintextResponse()

foreach (var write in _plaintextWrites)
{
writer.Write(write, 0, write.Length);
writer.Write(write);
}

writableBuffer.FlushAsync().GetResult();
Expand Down
12 changes: 6 additions & 6 deletions tests/System.IO.Pipelines.Tests/WritableBufferWriterFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,20 @@ public void ThrowsForInvalidParameters(int arrayLength, int offset, int length)
array[i] = (byte)(i + 1);
}

writer.Write(array, 0, 0);
writer.Write(array, array.Length, 0);
writer.Write(new Span<byte>(array, 0, 0));
writer.Write(new Span<byte>(array, array.Length, 0));

try
{
writer.Write(array, offset, length);
writer.Write(new Span<byte>(array, offset, length));
Assert.True(false);
}
catch(Exception ex)
{
Assert.True(ex is ArgumentOutOfRangeException);
}

writer.Write(array, 0, array.Length);
writer.Write(new Span<byte>(array, 0, array.Length));
Assert.Equal(array, Read());
}

Expand All @@ -111,7 +111,7 @@ public void CanWriteWithOffsetAndLenght(int alloc, int offset, int length)
var writer = OutputWriter.Create(_buffer);
var array = new byte[] { 1, 2, 3 };

writer.Write(array, offset, length);
writer.Write(new Span<byte>(array, offset, length));

Assert.Equal(array.Skip(offset).Take(length).ToArray(), Read());
}
Expand Down Expand Up @@ -147,7 +147,7 @@ public void CanWriteEmpty()
var array = new byte[] { };

writer.Write(array);
writer.Write(array, 0, array.Length);
writer.Write(new Span<byte>(array, 0, array.Length));

Assert.Equal(array, Read());
}
Expand Down

0 comments on commit c1286b4

Please sign in to comment.