in src/RecyclableMemoryStream.cs [557:615]
public override Task CopyToAsync(Stream destination, int bufferSize, CancellationToken cancellationToken)
{
if (destination == null)
{
throw new ArgumentNullException(nameof(destination));
}
this.CheckDisposed();
if (this.length == 0)
{
return Task.CompletedTask;
}
long startPos = this.position;
var count = this.length - startPos;
this.position += count;
if (destination is MemoryStream destinationRMS)
{
this.WriteTo(destinationRMS, startPos, count);
return Task.CompletedTask;
}
else
{
if (this.largeBuffer == null)
{
if (this.blocks.Count == 1)
{
AssertLengthIsSmall();
return destination.WriteAsync(this.blocks[0], (int)startPos, (int)count, cancellationToken);
}
else
{
return CopyToAsyncImpl(destination, this.GetBlockAndRelativeOffset(startPos), count, this.blocks, cancellationToken);
}
}
else
{
AssertLengthIsSmall();
return destination.WriteAsync(this.largeBuffer, (int)startPos, (int)count, cancellationToken);
}
}
static async Task CopyToAsyncImpl(Stream destination, BlockAndOffset blockAndOffset, long count, List<byte[]> blocks, CancellationToken cancellationToken)
{
var bytesRemaining = count;
int currentBlock = blockAndOffset.Block;
var currentOffset = blockAndOffset.Offset;
while (bytesRemaining > 0)
{
int amountToCopy = (int)Math.Min(blocks[currentBlock].Length - currentOffset, bytesRemaining);
await destination.WriteAsync(blocks[currentBlock], currentOffset, amountToCopy, cancellationToken);
bytesRemaining -= amountToCopy;
++currentBlock;
currentOffset = 0;
}
}
}