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

Commit

Permalink
Added All Span APIs to Stream Polyfill (#2344)
Browse files Browse the repository at this point in the history
* Bug fix in BufferWriter

* Added Stream Async Methods
  • Loading branch information
KrzysztofCwalina authored Jun 5, 2018
1 parent 4924c29 commit 8933c9c
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/System.Memory.Polyfill/System.Memory.Polyfill.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
<PackageReference Include="System.Buffers" Version="$(SystemMemoryVersion)" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="$(SystemCompilerServicesUnsafeVersion)" />
<PackageReference Include="System.Threading.Tasks.Extensions" Version="$(SystemMemoryVersion)" />
</ItemGroup>
</Project>
75 changes: 75 additions & 0 deletions src/System.Memory.Polyfill/System/Stream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

using System.Buffers;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace System
{
Expand All @@ -26,6 +29,78 @@ public static int Read(this Stream stream, Span<byte> buffer)
{
if(pooled != null) ArrayPool<byte>.Shared.Return(pooled);
}
#endif
}

public static async ValueTask<int> ReadAsync(this Stream stream, Memory<byte> buffer, CancellationToken cancellationToken = default)
{
#if NETCOREAPP2_1
return await stream.ReadAsync(buffer, cancellationToken);
#else
if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
{
return await stream.ReadAsync(array.Array, array.Offset, array.Count, cancellationToken);
}
else
{
byte[] pooled = null;
try
{
pooled = ArrayPool<byte>.Shared.Rent(buffer.Length);
int read = await stream.ReadAsync(pooled, 0, pooled.Length, cancellationToken);
pooled.AsSpan(0, read).CopyTo(buffer.Span);
return read;
}
finally
{
if (pooled != null) ArrayPool<byte>.Shared.Return(pooled);
}
}
#endif
}

public static void Write(this Stream stream, ReadOnlySpan<byte> buffer)
{
#if NETCOREAPP2_1
stream.Write(buffer);
#else
byte[] pooled = null;
try
{
pooled = ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.CopyTo(pooled);
stream.Write(pooled, 0, pooled.Length);
}
finally
{
if(pooled != null) ArrayPool<byte>.Shared.Return(pooled);
}
#endif
}

public static Task WriteAsync(this Stream stream, ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default)
{
#if NETCOREAPP2_1
return stream.WriteAsync(buffer, cancellationToken).AsTask();
#else
if (MemoryMarshal.TryGetArray(buffer, out ArraySegment<byte> array))
{
return stream.WriteAsync(array.Array, array.Offset, array.Count, cancellationToken);
}
else
{
byte[] pooled = null;
try
{
pooled = ArrayPool<byte>.Shared.Rent(buffer.Length);
buffer.CopyTo(pooled);
return stream.WriteAsync(pooled, 0, pooled.Length, cancellationToken);
}
finally
{
if (pooled != null) ArrayPool<byte>.Shared.Return(pooled);
}
}
#endif
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/System.Memory.Polyfill.Tests/Int32.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class Int32Tests
[Fact]
public void Int32TryParse()
{
ReadOnlySpan<char> span = int.MaxValue.ToString().ToCharArray().AsSpan();
ReadOnlySpan<char> span = int.MaxValue.ToString().AsSpan();
Assert.True(Int32Polyfill.TryParse(span, out int value));
Assert.Equal(int.MaxValue, value);
}
Expand Down
51 changes: 51 additions & 0 deletions tests/System.Memory.Polyfill.Tests/StreamTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,56 @@ public void StreamRead()
Assert.Equal(i, span[i]);
}
}

[Fact]
public async void StreamReadAsync()
{
var buffer = new byte[100];
for (int i = 0; i < buffer.Length; i++) buffer[i] = (byte)i;
var stream = new MemoryStream(buffer);

buffer = new byte[100];
var memory = new Memory<byte>(buffer);
int read = await stream.ReadAsync(memory);

Assert.Equal(buffer.Length, read);
for (int i = 0; i < buffer.Length; i++)
{
Assert.Equal(i, buffer[i]);
}
}

[Fact]
public void StreamWrite()
{
var span = new Span<byte>(new byte[100]);
for (int i = 0; i < span.Length; i++) span[i] = (byte)i;

var buffer = new byte[1000];
var stream = new MemoryStream(buffer);

stream.Write(span);
for (int i = 0; i < span.Length; i++)
{
Assert.Equal(i, buffer[i]);
}
}

[Fact]
public async void StreamWriteAsync()
{
var array = new byte[100];
var memory = new Memory<byte>(array);
for (int i = 0; i < array.Length; i++) array[i] = (byte)i;

var buffer = new byte[100];
var stream = new MemoryStream(buffer);
await stream.WriteAsync(memory);

for (int i = 0; i < buffer.Length; i++)
{
Assert.Equal(i, buffer[i]);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\tools\common.props" />
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetsWindows)' == 'true'">
<TargetFrameworks>net46;netcoreapp2.1</TargetFrameworks>
<TargetFrameworks>netcoreapp2.0;netcoreapp2.1</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="xunit" Version="2.3.1" />
Expand Down

0 comments on commit 8933c9c

Please sign in to comment.