// 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 CommunityToolkit.HighPerformance.Streams; /// /// A implementation wrapping an instance. /// /// The type of buffer writer to use. internal sealed partial class IBufferWriterStream : Stream where TWriter : struct, IBufferWriter { /// /// The target instance to use. /// private readonly TWriter bufferWriter; /// /// Indicates whether or not the current instance has been disposed /// private bool disposed; /// /// Initializes a new instance of the class. /// /// The target instance to use. public IBufferWriterStream(TWriter bufferWriter) { this.bufferWriter = bufferWriter; } /// public override bool CanRead => false; /// public override bool CanSeek => false; /// public override bool CanWrite { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => !this.disposed; } /// public override long Length => throw MemoryStream.GetNotSupportedException(); /// public override long Position { get => throw MemoryStream.GetNotSupportedException(); set => throw MemoryStream.GetNotSupportedException(); } /// public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken) { throw MemoryStream.GetNotSupportedException(); } /// public override void Flush() { } /// public override Task FlushAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { return Task.FromCanceled(cancellationToken); } return Task.CompletedTask; } /// public override Task ReadAsync(byte[]? buffer, int offset, int count, CancellationToken cancellationToken) { throw MemoryStream.GetNotSupportedException(); } /// 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); } } /// public override long Seek(long offset, SeekOrigin origin) { throw MemoryStream.GetNotSupportedException(); } /// public override void SetLength(long value) { throw MemoryStream.GetNotSupportedException(); } /// public override int Read(byte[]? buffer, int offset, int count) { throw MemoryStream.GetNotSupportedException(); } /// public override int ReadByte() { throw MemoryStream.GetNotSupportedException(); } /// public override void Write(byte[]? buffer, int offset, int count) { MemoryStream.ValidateDisposed(this.disposed); MemoryStream.ValidateBuffer(buffer, offset, count); Span source = buffer.AsSpan(offset, count); Span destination = this.bufferWriter.GetSpan(count); if (!source.TryCopyTo(destination)) { MemoryStream.ThrowArgumentExceptionForEndOfStreamOnWrite(); } this.bufferWriter.Advance(count); } /// public override void WriteByte(byte value) { MemoryStream.ValidateDisposed(this.disposed); this.bufferWriter.GetSpan(1)[0] = value; this.bufferWriter.Advance(1); } /// protected override void Dispose(bool disposing) { this.disposed = true; } }