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);
}
}
}