This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added AsStream to PipeReader and PipeWriter (#35399)
- This adds a new virtual member to PipeReader and PipeWriter to get a read only or write only stream from the PipeReader and PipeWriter - This introduces a new field on the base types - Added tests
- Loading branch information
Showing
11 changed files
with
846 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
114 changes: 114 additions & 0 deletions
114
src/System.IO.Pipelines/src/System/IO/Pipelines/PipeReaderStream.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// 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. | ||
|
||
using System; | ||
using System.Buffers; | ||
using System.Diagnostics; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
|
||
namespace System.IO.Pipelines | ||
{ | ||
internal sealed class PipeReaderStream : Stream | ||
{ | ||
private readonly PipeReader _pipeReader; | ||
|
||
public PipeReaderStream(PipeReader pipeReader) | ||
{ | ||
Debug.Assert(pipeReader != null); | ||
_pipeReader = pipeReader; | ||
} | ||
|
||
public override bool CanRead => true; | ||
|
||
public override bool CanSeek => false; | ||
|
||
public override bool CanWrite => false; | ||
|
||
public override long Length => throw new NotSupportedException(); | ||
|
||
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); } | ||
|
||
public override void Flush() | ||
{ | ||
} | ||
|
||
public override int Read(byte[] buffer, int offset, int count) | ||
{ | ||
return ReadAsync(buffer, offset, count).GetAwaiter().GetResult(); | ||
} | ||
|
||
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); | ||
|
||
public override void SetLength(long value) => throw new NotSupportedException(); | ||
|
||
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); | ||
|
||
public sealed override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) => | ||
TaskToApm.Begin(ReadAsync(buffer, offset, count, default), callback, state); | ||
|
||
public sealed override int EndRead(IAsyncResult asyncResult) => | ||
TaskToApm.End<int>(asyncResult); | ||
|
||
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) | ||
{ | ||
return ReadAsyncInternal(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask(); | ||
} | ||
|
||
#if !netstandard | ||
public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) | ||
{ | ||
return ReadAsyncInternal(buffer, cancellationToken); | ||
} | ||
#endif | ||
|
||
private async ValueTask<int> ReadAsyncInternal(Memory<byte> buffer, CancellationToken cancellationToken) | ||
{ | ||
ReadResult result = await _pipeReader.ReadAsync(cancellationToken).ConfigureAwait(false); | ||
|
||
if (result.IsCanceled) | ||
{ | ||
ThrowHelper.ThrowOperationCanceledException_ReadCanceled(); | ||
} | ||
|
||
ReadOnlySequence<byte> sequence = result.Buffer; | ||
long bufferLength = sequence.Length; | ||
SequencePosition consumed = sequence.Start; | ||
|
||
try | ||
{ | ||
if (bufferLength != 0) | ||
{ | ||
int actual = (int)Math.Min(bufferLength, buffer.Length); | ||
|
||
ReadOnlySequence<byte> slice = actual == bufferLength ? sequence : sequence.Slice(0, actual); | ||
consumed = slice.End; | ||
slice.CopyTo(buffer.Span); | ||
|
||
return actual; | ||
} | ||
|
||
if (result.IsCompleted) | ||
{ | ||
return 0; | ||
} | ||
} | ||
finally | ||
{ | ||
_pipeReader.AdvanceTo(consumed); | ||
} | ||
|
||
// This is a buggy PipeReader implementation that returns 0 byte reads even though the PipeReader | ||
// isn't completed or canceled | ||
ThrowHelper.ThrowInvalidOperationException_InvalidZeroByteRead(); | ||
return 0; | ||
} | ||
|
||
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) | ||
{ | ||
// Delegate to CopyToAsync on the PipeReader | ||
return _pipeReader.CopyToAsync(destination, cancellationToken); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.