DotNext by .NET Foundation and Contributors

<PackageReference Include="DotNext" Version="4.1.1" />

 SparseMemoryStream

using DotNext.Buffers; using System; using System.IO; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace DotNext.IO { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal sealed class SparseMemoryStream : ReadOnlyStream { [System.Runtime.CompilerServices.Nullable(2)] private SparseBufferWriter<byte>.MemoryChunk current; private long position; private int offset; public override long Length { get; } public override bool CanSeek => false; public override long Position { get { return position; } set { throw new NotSupportedException(); } } internal SparseMemoryStream(SparseBufferWriter<byte> writer) { current = writer.FirstChunk; Length = writer.WrittenCount; } public override void SetLength(long value) { throw new NotSupportedException(); } public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } [System.Runtime.CompilerServices.NullableContext(0)] public override int Read(Span<byte> output) { if (output.IsEmpty || current == null) return 0; ReadOnlySpan<byte> span = current.WrittenMemory.Span; span.Slice(offset).CopyTo(output, out int writtenCount); offset += writtenCount; position += writtenCount; if (offset == span.Length) { offset = 0; current = current.Next; } return writtenCount; } public override void CopyTo(Stream destination, int bufferSize) { Stream.ValidateCopyToArguments(destination, bufferSize); while (current != null) { ReadOnlySpan<byte> readOnlySpan; destination.Write(readOnlySpan = current.WrittenMemory.Span.Slice(offset)); offset = 0; current = current.Next; position += readOnlySpan.Length; } } [AsyncStateMachine(typeof(<CopyToAsync>d__16))] public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken token) { <CopyToAsync>d__16 stateMachine = default(<CopyToAsync>d__16); stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create(); stateMachine.<>4__this = this; stateMachine.destination = destination; stateMachine.bufferSize = bufferSize; stateMachine.token = token; stateMachine.<>1__state = -1; stateMachine.<>t__builder.Start(ref stateMachine); return stateMachine.<>t__builder.Task; } protected override void Dispose(bool disposing) { if (disposing) current = null; offset = 0; position = 0; base.Dispose(disposing); } } }