summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/IO/Stream.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/IO/Stream.cs')
-rw-r--r--src/mscorlib/src/System/IO/Stream.cs123
1 files changed, 114 insertions, 9 deletions
diff --git a/src/mscorlib/src/System/IO/Stream.cs b/src/mscorlib/src/System/IO/Stream.cs
index 786dfedef9..82fad24c6d 100644
--- a/src/mscorlib/src/System/IO/Stream.cs
+++ b/src/mscorlib/src/System/IO/Stream.cs
@@ -41,9 +41,7 @@ namespace System.IO
// To implement Async IO operations on streams that don't support async IO
- [NonSerialized]
private ReadWriteTask _activeReadWriteTask;
- [NonSerialized]
private SemaphoreSlim _asyncActiveSemaphore;
internal SemaphoreSlim EnsureAsyncActiveSemaphoreInitialized()
@@ -416,6 +414,33 @@ namespace System.IO
: BeginEndReadAsync(buffer, offset, count);
}
+ public virtual ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (destination.TryGetArray(out ArraySegment<byte> array))
+ {
+ return new ValueTask<int>(ReadAsync(array.Array, array.Offset, array.Count, cancellationToken));
+ }
+ else
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(destination.Length);
+ return FinishReadAsync(ReadAsync(buffer, 0, destination.Length, cancellationToken), buffer, destination);
+
+ async ValueTask<int> FinishReadAsync(Task<int> readTask, byte[] localBuffer, Memory<byte> localDestination)
+ {
+ try
+ {
+ int result = await readTask.ConfigureAwait(false);
+ new Span<byte>(localBuffer, 0, result).CopyTo(localDestination.Span);
+ return result;
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(localBuffer);
+ }
+ }
+ }
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern bool HasOverriddenBeginEndRead();
@@ -694,8 +719,6 @@ namespace System.IO
return WriteAsync(buffer, offset, count, CancellationToken.None);
}
-
-
public virtual Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
// If cancellation was requested, bail early with an already completed task.
@@ -705,6 +728,32 @@ namespace System.IO
: BeginEndWriteAsync(buffer, offset, count);
}
+ public virtual Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ if (source.DangerousTryGetArray(out ArraySegment<byte> array))
+ {
+ return WriteAsync(array.Array, array.Offset, array.Count, cancellationToken);
+ }
+ else
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(source.Length);
+ source.Span.CopyTo(buffer);
+ return FinishWriteAsync(WriteAsync(buffer, 0, source.Length, cancellationToken), buffer);
+
+ async Task FinishWriteAsync(Task writeTask, byte[] localBuffer)
+ {
+ try
+ {
+ await writeTask.ConfigureAwait(false);
+ }
+ finally
+ {
+ ArrayPool<byte>.Shared.Return(localBuffer);
+ }
+ }
+ }
+ }
+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern bool HasOverriddenBeginEndWrite();
@@ -734,6 +783,22 @@ namespace System.IO
public abstract int Read([In, Out] byte[] buffer, int offset, int count);
+ public virtual int Read(Span<byte> destination)
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(destination.Length);
+ try
+ {
+ int numRead = Read(buffer, 0, destination.Length);
+ if ((uint)numRead > destination.Length)
+ {
+ throw new IOException(SR.IO_StreamTooLong);
+ }
+ new Span<byte>(buffer, 0, numRead).CopyTo(destination);
+ return numRead;
+ }
+ finally { ArrayPool<byte>.Shared.Return(buffer); }
+ }
+
// Reads one byte from the stream by calling Read(byte[], int, int).
// Will return an unsigned byte cast to an int or -1 on end of stream.
// This implementation does not perform well because it allocates a new
@@ -754,6 +819,17 @@ namespace System.IO
public abstract void Write(byte[] buffer, int offset, int count);
+ public virtual void Write(ReadOnlySpan<byte> source)
+ {
+ byte[] buffer = ArrayPool<byte>.Shared.Rent(source.Length);
+ try
+ {
+ source.CopyTo(buffer);
+ Write(buffer, 0, source.Length);
+ }
+ finally { ArrayPool<byte>.Shared.Return(buffer); }
+ }
+
// Writes one byte from the stream by calling Write(byte[], int, int).
// This implementation does not perform well because it allocates a new
// byte[] each time you call it, and should be overridden by any
@@ -957,14 +1033,20 @@ namespace System.IO
return 0;
}
+ public override int Read(Span<byte> destination)
+ {
+ return 0;
+ }
+
public override Task<int> ReadAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
- var nullReadTask = s_nullReadTask;
- if (nullReadTask == null)
- s_nullReadTask = nullReadTask = new Task<int>(false, 0, (TaskCreationOptions)InternalTaskOptions.DoNotDispose, CancellationToken.None); // benign race condition
- return nullReadTask;
+ return AsyncTaskMethodBuilder<int>.s_defaultResultTask;
+ }
+
+ public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return new ValueTask<int>(0);
}
- private static Task<int> s_nullReadTask;
public override int ReadByte()
{
@@ -975,6 +1057,10 @@ namespace System.IO
{
}
+ public override void Write(ReadOnlySpan<byte> source)
+ {
+ }
+
public override Task WriteAsync(Byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return cancellationToken.IsCancellationRequested ?
@@ -982,6 +1068,13 @@ namespace System.IO
Task.CompletedTask;
}
+ public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
+ {
+ return cancellationToken.IsCancellationRequested ?
+ Task.FromCanceled(cancellationToken) :
+ Task.CompletedTask;
+ }
+
public override void WriteByte(byte value)
{
}
@@ -1229,6 +1322,12 @@ namespace System.IO
return _stream.Read(bytes, offset, count);
}
+ public override int Read(Span<byte> destination)
+ {
+ lock (_stream)
+ return _stream.Read(destination);
+ }
+
public override int ReadByte()
{
lock (_stream)
@@ -1282,6 +1381,12 @@ namespace System.IO
_stream.Write(bytes, offset, count);
}
+ public override void Write(ReadOnlySpan<byte> source)
+ {
+ lock (_stream)
+ _stream.Write(source);
+ }
+
public override void WriteByte(byte b)
{
lock (_stream)