private static async Task WaitWithConnectionCancellationAsync(ValueTask task, HttpConnection connection, CancellationToken cancellationToken)
        {
            CancellationTokenRegistration ctr = connection.RegisterCancellation(cancellationToken);

            try
            {
                await task.ConfigureAwait(false);
            }
            finally
            {
                ctr.Dispose();
            }
        }
        public override async ValueTask <int> ReadAsync(Memory <byte> buffer, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            HttpConnection connection = _connection;

            if (connection == null || buffer.Length == 0)
            {
                // Response body fully consumed or the caller didn't ask for any data
                return(0);
            }

            ValueTask <int> readTask = connection.ReadBufferedAsync(buffer);
            int             bytesRead;

            if (readTask.IsCompletedSuccessfully)
            {
                bytesRead = readTask.Result;
            }
            else
            {
                CancellationTokenRegistration ctr = connection.RegisterCancellation(cancellationToken);
                try
                {
                    bytesRead = await readTask.ConfigureAwait(false);
                }
                finally
                {
                    ctr.Dispose();
                }
            }

            if (bytesRead == 0)
            {
                // A cancellation request may have caused the EOF.
                cancellationToken.ThrowIfCancellationRequested();

                // We cannot reuse this connection, so close it.
                _connection = null;
                connection.Dispose();
            }

            return(bytesRead);
        }
        private async Task CompleteCopyToAsync(Task copyTask, HttpConnection connection, CancellationToken cancellationToken)
        {
            CancellationTokenRegistration ctr = connection.RegisterCancellation(cancellationToken);

            try
            {
                await copyTask.ConfigureAwait(false);
            }
            finally
            {
                ctr.Dispose();
            }

            // If cancellation is requested and tears down the connection, it could cause the copy
            // to end early but think it ended successfully. So we prioritize cancellation in this
            // race condition, and if we find after the copy has completed that cancellation has
            // been requested, we assume the copy completed due to cancellation and throw.
            cancellationToken.ThrowIfCancellationRequested();

            Finish(connection);
        }