public static ValueTask <int> ReadAsync(this PipeReader input, ArraySegment <byte> destination)
        {
            while (true)
            {
                var awaiter = input.ReadAsync();

                if (!awaiter.IsCompleted)
                {
                    break;
                }

                var result      = awaiter.GetResult();
                var inputBuffer = result.Buffer;

                var length = (int)Math.Min(inputBuffer.Length, destination.Count);

                var sliced = inputBuffer.Slice(0, length);
                sliced.CopyTo(destination);

                input.Advance(sliced.End);

                if (length != 0)
                {
                    return(new ValueTask <int>(length));
                }

                if (result.IsCompleted)
                {
                    return(new ValueTask <int>(0));
                }
            }

            return(new ValueTask <int>(input.ReadAsyncAwaited(destination)));
        }
        public static async Task CopyToAsync(this PipeReader input, PipeWriter output)
        {
            while (true)
            {
                var result = await input.ReadAsync();

                var inputBuffer = result.Buffer;

                try
                {
                    if (inputBuffer.IsEmpty && result.IsCompleted)
                    {
                        return;
                    }

                    var buffer = output;

                    foreach (var memory in inputBuffer)
                    {
                        buffer.Write(memory.Span);
                    }


                    await buffer.FlushAsync();
                }
                finally
                {
                    input.Advance(inputBuffer.End);
                }
            }
        }
        public static async Task <ReadOnlyBuffer <byte> > ReadToEndAsync(this PipeReader input)
        {
            while (true)
            {
                // Wait for more data
                var result = await input.ReadAsync();

                if (result.IsCompleted)
                {
                    // Read all the data, return it
                    return(result.Buffer);
                }

                // Don't advance the buffer so remains in buffer
                input.Advance(result.Buffer.Start, result.Buffer.End);
            }
        }
        public static async Task CopyToAsync(this PipeReader input, Stream stream, int bufferSize, CancellationToken cancellationToken)
        {
            // TODO: Use bufferSize argument
            while (!cancellationToken.IsCancellationRequested)
            {
                var result = await input.ReadAsync();

                var inputBuffer = result.Buffer;
                try
                {
                    if (inputBuffer.IsEmpty && result.IsCompleted)
                    {
                        return;
                    }

                    await inputBuffer.CopyToAsync(stream);
                }
                finally
                {
                    input.Advance(inputBuffer.End);
                }
            }
        }
        private static async Task <int> ReadAsyncAwaited(this PipeReader input, ArraySegment <byte> destination)
        {
            while (true)
            {
                var result = await input.ReadAsync();

                var inputBuffer = result.Buffer;

                var length = (int)Math.Min(inputBuffer.Length, destination.Count);
                var sliced = inputBuffer.Slice(0, length);
                sliced.CopyTo(destination);
                input.Advance(sliced.End);

                if (length != 0)
                {
                    return(length);
                }

                if (result.IsCompleted)
                {
                    return(0);
                }
            }
        }