public static async Task <IEnumerable <T> > AsEnumerableAsync <T>(this AsyncStream <T> source)
        {
            var items = new ConcurrentBag <T>();

            while (await source.ChannelReader.WaitToReadAsync(source.CancellationToken))
            {
                var item = await source.ChannelReader.ReadAsync(source.CancellationToken);

                items.Add(item.Item);
            }
            return(items);
        }
        public static AsyncStream <TResult> SelectAsync <TSource, TResult>(this AsyncStream <TSource> source, Func <StreamedValue <TSource>, CancellationToken, Task <TResult> > action)
        {
            var channel = Channel.CreateUnbounded <StreamedValue <TResult> >();
            var writer  = channel.Writer;
            var task    = Task.Run(async() =>
            {
                while (await source.ChannelReader.WaitToReadAsync(source.CancellationToken))
                {
                    var sourceValue = await source.ChannelReader.ReadAsync(source.CancellationToken);
                    await sourceValue.ExecuteAndStreamAsync(action, writer, source.CancellationToken);
                }
                channel.Writer.Complete();
            });

            return(new AsyncStream <TResult>(channel, task, source.CancellationToken));
        }
        public static AsyncStream <T> ForEachAsync <T>(this AsyncStream <T> source, Func <StreamedValue <T>, CancellationToken, Task> action)
        {
            var channel = Channel.CreateUnbounded <StreamedValue <T> >(new UnboundedChannelOptions
            {
                SingleWriter = false,
                SingleReader = false,
                AllowSynchronousContinuations = true
            });
            var task = Task.Run(async() =>
            {
                while (await source.ChannelReader.WaitToReadAsync(source.CancellationToken))
                {
                    var item = await source.ChannelReader.ReadAsync(source.CancellationToken);
                    await action(item, source.CancellationToken);
                    await channel.Writer.WriteAsync(item, source.CancellationToken);
                }
                channel.Writer.Complete();
            });

            return(new AsyncStream <T>(channel, task, source.CancellationToken));
        }
        public static AsyncStream <T> CountAsync <T>(this AsyncStream <T> source, out Counter counter)
        {
            var localCounter = new Counter();

            counter = localCounter;
            var channel = Channel.CreateUnbounded <StreamedValue <T> >(new UnboundedChannelOptions
            {
                SingleWriter = false,
                SingleReader = false,
                AllowSynchronousContinuations = true
            });
            var task = Task.Run(async() =>
            {
                while (await source.ChannelReader.WaitToReadAsync(source.CancellationToken))
                {
                    var item = await source.ChannelReader.ReadAsync(source.CancellationToken);
                    localCounter.Increment();
                    await channel.Writer.WriteAsync(item, source.CancellationToken);
                }
                channel.Writer.Complete();
            });

            return(new AsyncStream <T>(channel, task, source.CancellationToken));
        }