-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New IBufferWriter<byte>.AsStream() extension #3522
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
12 commits merged into
CommunityToolkit:master
from
Sergio0694:feature/ibuffer-writer-stream2
Nov 14, 2020
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
ab73d61
Added IBufferWriterStream type
Sergio0694 bcadbd7
Added IBufferWriter<byte>.AsStream extension
Sergio0694 dc13fb9
Added unit tests for IBufferWriterStream
Sergio0694 23c8abb
Fixed a build error in a unit test
Sergio0694 25d291c
Fixed a bug in IBufferWriterStream.WriteByte
Sergio0694 62eaaa4
Removed callvirt-s in BufferWriterStream and AsStream cast
Sergio0694 38fe889
Merge branch 'master' into feature/ibuffer-writer-stream2
Sergio0694 b93f42f
Minor optimization to Stream.Read<T>
Sergio0694 7c3269a
Minor performance improvement
Sergio0694 ba19b76
Added comments to unit tests
Sergio0694 ae0e4c1
Merge branch 'master' into feature/ibuffer-writer-stream2
Rosuavio 4600e42
Fixed nullability warning due to missing annotation
Sergio0694 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
32 changes: 32 additions & 0 deletions
32
Microsoft.Toolkit.HighPerformance/Extensions/ArrayPoolBufferWriterExtensions.cs
This file contains hidden or 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,32 @@ | ||
| // 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.Diagnostics.Contracts; | ||
| using System.IO; | ||
| using System.Runtime.CompilerServices; | ||
| using Microsoft.Toolkit.HighPerformance.Buffers; | ||
| using Microsoft.Toolkit.HighPerformance.Streams; | ||
| using Microsoft.Toolkit.HighPerformance.Streams.Sources; | ||
|
|
||
| namespace Microsoft.Toolkit.HighPerformance.Extensions | ||
| { | ||
| /// <summary> | ||
| /// Helpers for working with the <see cref="ArrayPoolBufferWriter{T}"/> type. | ||
| /// </summary> | ||
| public static class ArrayPoolBufferWriterExtensions | ||
| { | ||
| /// <summary> | ||
| /// Returns a <see cref="Stream"/> that can be used to write to a target an <see cref="ArrayPoolBufferWriter{T}"/> of <see cref="byte"/> instance. | ||
| /// </summary> | ||
| /// <param name="writer">The target <see cref="ArrayPoolBufferWriter{T}"/> instance.</param> | ||
| /// <returns>A <see cref="Stream"/> wrapping <paramref name="writer"/> and writing data to its underlying buffer.</returns> | ||
| /// <remarks>The returned <see cref="Stream"/> can only be written to and does not support seeking.</remarks> | ||
| [Pure] | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public static Stream AsStream(this ArrayPoolBufferWriter<byte> writer) | ||
| { | ||
| return new IBufferWriterStream<ArrayBufferWriterOwner>(new ArrayBufferWriterOwner(writer)); | ||
| } | ||
| } | ||
| } |
This file contains hidden or 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 hidden or 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
76 changes: 76 additions & 0 deletions
76
Microsoft.Toolkit.HighPerformance/Streams/IBufferWriterStream{TWriter}.Memory.cs
This file contains hidden or 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,76 @@ | ||
| // 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. | ||
|
|
||
| #if SPAN_RUNTIME_SUPPORT | ||
|
|
||
| using System; | ||
| using System.IO; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Microsoft.Toolkit.HighPerformance.Streams | ||
| { | ||
| /// <inheritdoc cref="IBufferWriterStream{TWriter}"/> | ||
| internal sealed partial class IBufferWriterStream<TWriter> | ||
| { | ||
| /// <inheritdoc/> | ||
| public override void CopyTo(Stream destination, int bufferSize) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) | ||
| { | ||
| if (cancellationToken.IsCancellationRequested) | ||
| { | ||
| return new ValueTask(Task.FromCanceled(cancellationToken)); | ||
| } | ||
|
|
||
| try | ||
| { | ||
| Write(buffer.Span); | ||
|
|
||
| return default; | ||
| } | ||
| catch (OperationCanceledException e) | ||
| { | ||
| return new ValueTask(Task.FromCanceled(e.CancellationToken)); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| return new ValueTask(Task.FromException(e)); | ||
| } | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override int Read(Span<byte> buffer) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override void Write(ReadOnlySpan<byte> buffer) | ||
| { | ||
| MemoryStream.ValidateDisposed(this.disposed); | ||
|
|
||
| Span<byte> destination = this.bufferWriter.GetSpan(buffer.Length); | ||
|
|
||
| if (!buffer.TryCopyTo(destination)) | ||
| { | ||
| MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); | ||
| } | ||
|
|
||
| this.bufferWriter.Advance(buffer.Length); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #endif | ||
173 changes: 173 additions & 0 deletions
173
Microsoft.Toolkit.HighPerformance/Streams/IBufferWriterStream{TWriter}.cs
This file contains hidden or 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,173 @@ | ||
| // 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.IO; | ||
| using System.Runtime.CompilerServices; | ||
| using System.Threading; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Microsoft.Toolkit.HighPerformance.Streams | ||
| { | ||
| /// <summary> | ||
| /// A <see cref="Stream"/> implementation wrapping an <see cref="IBufferWriter{T}"/> instance. | ||
| /// </summary> | ||
| /// <typeparam name="TWriter">The type of buffer writer to use.</typeparam> | ||
| internal sealed partial class IBufferWriterStream<TWriter> : Stream | ||
| where TWriter : struct, IBufferWriter<byte> | ||
| { | ||
| /// <summary> | ||
| /// The target <typeparamref name="TWriter"/> instance to use. | ||
| /// </summary> | ||
| private readonly TWriter bufferWriter; | ||
|
|
||
| /// <summary> | ||
| /// Indicates whether or not the current instance has been disposed | ||
| /// </summary> | ||
| private bool disposed; | ||
|
|
||
| /// <summary> | ||
| /// Initializes a new instance of the <see cref="IBufferWriterStream{TWriter}"/> class. | ||
| /// </summary> | ||
| /// <param name="bufferWriter">The target <see cref="IBufferWriter{T}"/> instance to use.</param> | ||
| public IBufferWriterStream(TWriter bufferWriter) | ||
| { | ||
| this.bufferWriter = bufferWriter; | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override bool CanRead => false; | ||
|
|
||
| /// <inheritdoc/> | ||
| public override bool CanSeek => false; | ||
|
|
||
| /// <inheritdoc/> | ||
| public override bool CanWrite | ||
| { | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| get => !this.disposed; | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override long Length => throw MemoryStream.GetNotSupportedException(); | ||
|
|
||
| /// <inheritdoc/> | ||
| public override long Position | ||
| { | ||
| get => throw MemoryStream.GetNotSupportedException(); | ||
| set => throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override void Flush() | ||
| { | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override Task FlushAsync(CancellationToken cancellationToken) | ||
| { | ||
| if (cancellationToken.IsCancellationRequested) | ||
| { | ||
| return Task.FromCanceled(cancellationToken); | ||
| } | ||
|
|
||
| return Task.CompletedTask; | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override Task<int> ReadAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override Task WriteAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) | ||
| { | ||
| if (cancellationToken.IsCancellationRequested) | ||
| { | ||
| return Task.FromCanceled(cancellationToken); | ||
| } | ||
|
|
||
| try | ||
| { | ||
| Write(buffer, offset, count); | ||
|
|
||
| return Task.CompletedTask; | ||
| } | ||
| catch (OperationCanceledException e) | ||
| { | ||
| return Task.FromCanceled(e.CancellationToken); | ||
| } | ||
| catch (Exception e) | ||
| { | ||
| return Task.FromException(e); | ||
| } | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override long Seek(long offset, SeekOrigin origin) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override void SetLength(long value) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override int Read(byte[]? buffer, int offset, int count) | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override int ReadByte() | ||
| { | ||
| throw MemoryStream.GetNotSupportedException(); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override void Write(byte[]? buffer, int offset, int count) | ||
| { | ||
| MemoryStream.ValidateDisposed(this.disposed); | ||
| MemoryStream.ValidateBuffer(buffer, offset, count); | ||
|
|
||
| Span<byte> | ||
| source = buffer.AsSpan(offset, count), | ||
| destination = this.bufferWriter.GetSpan(count); | ||
|
|
||
| if (!source.TryCopyTo(destination)) | ||
| { | ||
| MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); | ||
| } | ||
|
|
||
| this.bufferWriter.Advance(count); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| public override void WriteByte(byte value) | ||
| { | ||
| MemoryStream.ValidateDisposed(this.disposed); | ||
|
|
||
| this.bufferWriter.GetSpan(1)[0] = value; | ||
|
|
||
| this.bufferWriter.Advance(1); | ||
| } | ||
|
|
||
| /// <inheritdoc/> | ||
| protected override void Dispose(bool disposing) | ||
| { | ||
| this.disposed = true; | ||
| } | ||
| } | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.