Summary

Class:AsyncEnumeration.Implementation.Provider.DefaultAsyncProvider
Assembly:AsyncEnumeration.Implementation.Provider
File(s):/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Aggregate.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/AnyAll.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/AsyncProvider.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/First.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/OfType.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Select.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/SelectMany.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Skip.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Take.cs
/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Where.cs
Covered lines:229
Uncovered lines:1
Coverable lines:230
Total lines:1657
Line coverage:99.5%
Branch coverage:68.7%
Tag:7d9974899246b95481b7aa9cd3a1462ae2a67c91

Coverage History

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
AggregateAsync()601%0.5%
AggregateAsync()601%0.5%
>c__DisplayClass3_0`1/<<AggregateAsync()601%0.667%
AggregateAsync()401%0.5%
AggregateAsync()401%0.5%
>c__DisplayClass5_0`2/<<AggregateAsync()401%0.5%
AnyAsync()401%0.5%
AnyAsync(...)201%0.5%
AnyAsync(...)201%0.5%
AllAsync()401%0.5%
AllAsync()401%0.5%
>c__DisplayClass10_0`1/<<AllAsync()601%0.667%
AnyAsync_NotNull()401%0.5%
AnyAsync_NotNull()401%0.5%
>c__DisplayClass12_0`1/<<AnyAsync_NotNull()601%0.667%
.ctor()101%0%
FromTransformCallback(...)101%0%
FromTransformCallback(...)101%0%
.ctor(...)101%0%
System.Collections.Generic.IAsyncEnumerable<U>.GetAsyncEnumerator()101%0%
.ctor(...)101%0%
System.Collections.Generic.IAsyncEnumerable<U>.GetAsyncEnumerator()101%0%
FirstAsync(...)101%0%
FirstOrDefaultAsync(...)101%0%
FirstAsync()2001%0.75%
OfType(...)401%1%
Select(...)201%1%
Select(...)201%1%
SelectMany(...)201%1%
SelectMany(...)201%1%
SelectMany(...)201%1%
SelectMany(...)201%1%
Skip(...)201%0.5%
Skip(...)201%0.5%
SkipWhile(...)101%0%
SkipWhile(...)101%0%
Take(...)401%0.75%
Take(...)401%0.75%
TakeWhile(...)201%1%
TakeWhile(...)201%1%
Where(...)201%1%
Where(...)201%1%

File(s)

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Aggregate.cs

#LineLine coverage
 1/*
 2 * Copyright 2018 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading;
 23using System.Threading.Tasks;
 24using UtilPack;
 25
 26namespace AsyncEnumeration.Implementation.Provider
 27{
 28
 29   public partial class DefaultAsyncProvider
 30   {
 31      private const Int32 INITIAL = 0;
 32      private const Int32 FIRST_SEEN = 1;
 33
 34      /// <summary>
 35      /// Similarly to <see cref="System.Linq.Enumerable.Aggregate{TSource}(IEnumerable{TSource}, Func{TSource, TSource,
 36      /// </summary>
 37      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 38      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 39      /// <param name="func">The synchronous callback function to perform aggregation. First argument is previous elemen
 40      /// <returns>An aggregated value.</returns>
 41      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 42      /// <exception cref="ArgumentNullException">If <paramref name="func"/> is <c>null</c>.</exception>
 43      /// <exception cref="InvalidOperationException">If this <see cref="IAsyncEnumerable{T}"/> does not contain at leas
 44      public async Task<T> AggregateAsync<T>( IAsyncEnumerable<T> source, Func<T, T, T> func )
 45      {
 146         ArgumentValidator.ValidateNotNullReference( source );
 147         ArgumentValidator.ValidateNotNull( nameof( func ), func );
 48
 149         var state = INITIAL;
 150         T prev = default;
 151         await source.EnumerateAsync( item =>
 152         {
 1153            if ( state == INITIAL )
 154            {
 255               prev = item;
 256               Interlocked.Exchange( ref state, FIRST_SEEN );
 257            }
 158            else
 159            {
 1060               prev = func( prev, item );
 161            }
 1062         } );
 63
 164         return state == FIRST_SEEN ? prev : throw AsyncProviderUtilities.EmptySequenceException();
 165      }
 66
 67      /// <summary>
 68      /// Similarly to <see cref="System.Linq.Enumerable.Aggregate{TSource}(IEnumerable{TSource}, Func{TSource, TSource,
 69      /// </summary>
 70      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 71      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 72      /// <param name="asyncFunc">The potentially asynchronous callback function to perform aggregation. First argument 
 73      /// <returns>An aggregated value.</returns>
 74      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 75      /// <exception cref="ArgumentNullException">If <paramref name="asyncFunc"/> is <c>null</c>.</exception>
 76      /// <exception cref="InvalidOperationException">If this <see cref="IAsyncEnumerable{T}"/> does not contain at leas
 77      public async Task<T> AggregateAsync<T>( IAsyncEnumerable<T> source, Func<T, T, ValueTask<T>> asyncFunc )
 78      {
 179         ArgumentValidator.ValidateNotNullReference( source );
 180         ArgumentValidator.ValidateNotNull( nameof( asyncFunc ), asyncFunc );
 81
 182         var state = INITIAL;
 183         T prev = default;
 184         await source.EnumerateAsync( async item =>
 185         {
 1186            if ( state == INITIAL )
 187            {
 288               prev = item;
 289               Interlocked.Exchange( ref state, FIRST_SEEN );
 290            }
 191            else
 192            {
 1093               prev = await asyncFunc( prev, item );
 194            }
 1195         } );
 96
 197         return state == FIRST_SEEN ? prev : throw AsyncProviderUtilities.EmptySequenceException();
 198      }
 99
 100      /// <summary>
 101      /// Similarly to <see cref="System.Linq.Enumerable.Aggregate{TSource, TAccumulate}(IEnumerable{TSource}, TAccumula
 102      /// The type of the intermediate and return value is different than the type of elements in this <see cref="IAsync
 103      /// </summary>
 104      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 105      /// <typeparam name="TResult">The type of intermediate and result values.</typeparam>
 106      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 107      /// <param name="func">The synchronous calllback function to perform aggregation. First argument is intermediate v
 108      /// <param name="seed">The optional initial value for first argument of <paramref name="func"/> callback.</param>
 109      /// <returns>An aggregated value.</returns>
 110      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 111      /// <exception cref="ArgumentNullException">If <paramref name="func"/> is <c>null</c>.</exception>
 112      public async Task<TResult> AggregateAsync<T, TResult>( IAsyncEnumerable<T> source, Func<TResult, T, TResult> func,
 113      {
 1114         ArgumentValidator.ValidateNotNullReference( source );
 1115         ArgumentValidator.ValidateNotNull( nameof( func ), func );
 1116         await source.EnumerateAsync( item =>
 1117         {
 11118            seed = func( seed, item );
 11119         } );
 120
 1121         return seed;
 1122      }
 123
 124      /// <summary>
 125      /// Similarly to <see cref="System.Linq.Enumerable.Aggregate{TSource, TAccumulate}(IEnumerable{TSource}, TAccumula
 126      /// The type of the intermediate and return value is different than the type of elements in this <see cref="IAsync
 127      /// </summary>
 128      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 129      /// <typeparam name="TResult">The type of intermediate and result values.</typeparam>
 130      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 131      /// <param name="asyncFunc">The potentially asynchronous calllback function to perform aggregation. First argument
 132      /// <param name="seed">The optional initial value for first argument of <paramref name="asyncFunc"/> callback.</pa
 133      /// <returns>An aggregated value.</returns>
 134      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 135      /// <exception cref="ArgumentNullException">If <paramref name="asyncFunc"/> is <c>null</c>.</exception>
 136      public async Task<TResult> AggregateAsync<T, TResult>( IAsyncEnumerable<T> source, Func<TResult, T, ValueTask<TRes
 137      {
 1138         ArgumentValidator.ValidateNotNullReference( source );
 1139         ArgumentValidator.ValidateNotNull( nameof( asyncFunc ), asyncFunc );
 1140         await source.EnumerateAsync( async item =>
 1141         {
 11142            seed = await asyncFunc( seed, item );
 11143         } );
 144
 1145         return seed;
 1146      }
 147   }
 148}
 149
 150

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/AnyAll.cs

#LineLine coverage
 1/*
 2 * Copyright 2018 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading.Tasks;
 23using UtilPack;
 24
 25namespace AsyncEnumeration.Implementation.Provider
 26{
 27   public partial class DefaultAsyncProvider
 28   {
 29      /// <summary>
 30      /// Similarly to <see cref="System.Linq.Enumerable.Any{TSource}(IEnumerable{TSource})"/>, this method checks wheth
 31      /// </summary>
 32      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 33      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 34      /// <returns>Potentially asynchronously returns <c>true</c> if this <see cref="IAsyncEnumerable{T}"/> has at least
 35      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 36      /// <seealso cref="System.Linq.Enumerable.Any{TSource}(IEnumerable{TSource})"/>
 37      public async Task<Boolean> AnyAsync<T>( IAsyncEnumerable<T> source )
 38      {
 239         var retVal = false;
 240         await source.EnumerateAsync( item =>
 241         {
 342            retVal = true;
 343            return false;
 244         } );
 245         return retVal;
 246      }
 47
 48      /// <summary>
 49      /// Similarly to <see cref="System.Linq.Enumerable.Any{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>, 
 50      /// </summary>
 51      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 52      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 53      /// <param name="predicate">The synchronous callback to check whether an element satifies some condition. If <c>nu
 54      /// <returns>Potentially asynchronously returns <c>true</c> if this <see cref="IAsyncEnumerable{T}"/> has at least
 55      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 56      /// <seealso cref="System.Linq.Enumerable.Any{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 57      public Task<Boolean> AnyAsync<T>( IAsyncEnumerable<T> source, Func<T, Boolean> predicate )
 58      {
 259         return predicate == null ? this.AnyAsync( source ) : AnyAsync_NotNull( source, predicate );
 60      }
 61
 62      /// <summary>
 63      /// Similarly to <see cref="System.Linq.Enumerable.Any{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>, 
 64      /// </summary>
 65      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 66      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 67      /// <param name="asyncPredicate">The potentially asynchronous callback to check whether an element satifies some c
 68      /// <returns>Potentially asynchronously returns <c>true</c> if this <see cref="IAsyncEnumerable{T}"/> has at least
 69      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 70      /// <seealso cref="System.Linq.Enumerable.Any{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 71      public Task<Boolean> AnyAsync<T>( IAsyncEnumerable<T> source, Func<T, ValueTask<Boolean>> asyncPredicate )
 72      {
 273         return asyncPredicate == null ? this.AnyAsync( source ) : AnyAsync_NotNull( source, asyncPredicate );
 74      }
 75
 76      /// <summary>
 77      /// Checks that all items in this <see cref="IAsyncEnumerable{T}"/> adher to condition checked by given synchronou
 78      /// </summary>
 79      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 80      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 81      /// <param name="predicate">The synchronous callback to check whether an element satifies some condition.</param>
 82      /// <returns>Potentially asynchronously returns <c>true</c> if this <see cref="IAsyncEnumerable{T}"/> is empty, or
 83      /// <seealso cref="System.Linq.Enumerable.All{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 84      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 85      /// <exception cref="ArgumentNullException">If <paramref name="predicate"/> is <c>null</c>.</exception>
 86      public async Task<Boolean> AllAsync<T>( IAsyncEnumerable<T> source, Func<T, Boolean> predicate )
 87      {
 288         ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 289         var retVal = true;
 290         await source.EnumerateAsync( item =>
 291         {
 492            var isMatch = predicate( item );
 493            if ( !isMatch )
 294            {
 295               retVal = false;
 296            }
 497            return isMatch;
 298         } );
 299         return retVal;
 2100      }
 101
 102      /// <summary>
 103      /// Checks that all items in this <see cref="IAsyncEnumerable{T}"/> adher to condition checked by given potentiall
 104      /// </summary>
 105      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 106      /// <param name="source">This <see cref="IAsyncEnumerable{T}"/>.</param>
 107      /// <param name="asyncPredicate">The potentially asynchronous callback to check whether an element satifies some c
 108      /// <returns>Potentially asynchronously returns <c>true</c> if this <see cref="IAsyncEnumerable{T}"/> is empty, or
 109      /// <seealso cref="System.Linq.Enumerable.All{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 110      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 111      /// <exception cref="ArgumentNullException">If <paramref name="asyncPredicate"/> is <c>null</c>.</exception>
 112      public async Task<Boolean> AllAsync<T>( IAsyncEnumerable<T> source, Func<T, ValueTask<Boolean>> asyncPredicate )
 113      {
 2114         ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 2115         var retVal = true;
 2116         await source.EnumerateAsync( async item =>
 2117         {
 4118            var isMatch = await asyncPredicate( item );
 4119            if ( !isMatch )
 2120            {
 3121               retVal = false;
 2122            }
 4123            return isMatch;
 4124         } );
 2125         return retVal;
 2126      }
 127
 128      private static async Task<Boolean> AnyAsync_NotNull<T>( IAsyncEnumerable<T> source, Func<T, Boolean> predicate )
 129      {
 2130         var retVal = false;
 2131         await source.EnumerateAsync( item =>
 2132         {
 4133            var isMatch = predicate( item );
 4134            if ( isMatch )
 2135            {
 3136               retVal = true;
 2137            }
 4138            return !isMatch;
 2139         } );
 2140         return retVal;
 2141      }
 142
 143      private static async Task<Boolean> AnyAsync_NotNull<T>( IAsyncEnumerable<T> source, Func<T, ValueTask<Boolean>> as
 144      {
 2145         var retVal = false;
 2146         await source.EnumerateAsync( async item =>
 2147         {
 4148            var isMatch = await asyncPredicate( item );
 4149            if ( isMatch )
 2150            {
 3151               retVal = true;
 2152            }
 4153            return !isMatch;
 4154         } );
 2155         return retVal;
 2156      }
 157   }
 158}
 159

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/AsyncProvider.cs

#LineLine coverage
 1using AsyncEnumeration.Abstractions;
 2using System;
 3using System.Collections.Generic;
 4using System.Text;
 5using UtilPack;
 6
 7namespace AsyncEnumeration.Implementation.Provider
 8{
 9   /// <summary>
 10   /// This class implements <see cref="IAsyncProvider"/> in such way that all returned <see cref="IAsyncEnumerable{T}"/
 11   /// Instead of using constructor to create new instances of this class, use the <see cref="Instance"/> static propert
 12   /// </summary>
 13   public sealed partial class DefaultAsyncProvider : IAsyncProvider
 14   {
 15      /// <summary>
 16      /// Gets the default, stateless, instance of this <see cref="DefaultAsyncProvider"/>.
 17      /// </summary>
 7418      public static IAsyncProvider Instance { get; } = new DefaultAsyncProvider();
 19
 220      private DefaultAsyncProvider()
 21      {
 22
 223      }
 24
 25      private static IAsyncEnumerable<U> FromTransformCallback<T, U>(
 26         IAsyncEnumerable<T> enumerable,
 27         Func<IAsyncEnumerator<T>, IAsyncEnumerator<U>> transform
 28         )
 29      {
 430         return new EnumerableWrapper<T, U>( enumerable, transform );
 31      }
 32
 33      private static IAsyncEnumerable<U> FromTransformCallback<T, U, TArg>(
 34         IAsyncEnumerable<T> enumerable,
 35         TArg arg,
 36         Func<IAsyncEnumerator<T>, TArg, IAsyncEnumerator<U>> transform
 37         )
 38      {
 3939         return new EnumerableWrapper<T, U, TArg>( enumerable, transform, arg );
 40      }
 41
 42
 43      private sealed class EnumerableWrapper<T, U> : IAsyncEnumerable<U>
 44      {
 45         private readonly IAsyncEnumerable<T> _enumerable;
 46         private readonly Func<IAsyncEnumerator<T>, IAsyncEnumerator<U>> _getEnumerator;
 47
 448         public EnumerableWrapper(
 449            IAsyncEnumerable<T> enumerable,
 450            Func<IAsyncEnumerator<T>, IAsyncEnumerator<U>> getEnumerator
 451            )
 52         {
 453            this._enumerable = ArgumentValidator.ValidateNotNull( nameof( enumerable ), enumerable );
 454            this._getEnumerator = ArgumentValidator.ValidateNotNull( nameof( getEnumerator ), getEnumerator );
 455         }
 56
 057         IAsyncProvider IAsyncEnumerable.AsyncProvider => this._enumerable.AsyncProvider;
 58
 459         IAsyncEnumerator<U> IAsyncEnumerable<U>.GetAsyncEnumerator() => this._getEnumerator( this._enumerable.GetAsyncE
 60      }
 61
 62      private sealed class EnumerableWrapper<T, U, TArg> : IAsyncEnumerable<U>
 63      {
 64         private readonly IAsyncEnumerable<T> _enumerable;
 65         private readonly Func<IAsyncEnumerator<T>, TArg, IAsyncEnumerator<U>> _getEnumerator;
 66         private readonly TArg _arg;
 67
 3968         public EnumerableWrapper(
 3969            IAsyncEnumerable<T> enumerable,
 3970            Func<IAsyncEnumerator<T>, TArg, IAsyncEnumerator<U>> getEnumerator,
 3971            TArg arg
 3972            )
 73         {
 3974            this._enumerable = ArgumentValidator.ValidateNotNull( nameof( enumerable ), enumerable );
 3975            this._getEnumerator = ArgumentValidator.ValidateNotNull( nameof( getEnumerator ), getEnumerator );
 3976            this._arg = arg;
 3977         }
 78
 279         IAsyncProvider IAsyncEnumerable.AsyncProvider => this._enumerable.AsyncProvider;
 80
 3981         IAsyncEnumerator<U> IAsyncEnumerable<U>.GetAsyncEnumerator() => this._getEnumerator( this._enumerable.GetAsyncE
 82      }
 83
 84   }
 85}

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/First.cs

#LineLine coverage
 1/*
 2 * Copyright 2017 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading.Tasks;
 23
 24namespace AsyncEnumeration.Implementation.Provider
 25{
 26
 27   public partial class DefaultAsyncProvider
 28   {
 29      /// <summary>
 30      /// Asynchronously fetches the first item in this <see cref="IAsyncEnumerable{T}"/> and discards any other items.
 31      /// </summary>
 32      /// <typeparam name="T">The type of items being enumerated.</typeparam>
 33      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 34      /// <returns>The first item returned by <see cref="IAsyncEnumerator{T}"/> of this <see cref="IAsyncEnumerable{T}"/
 35      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 36      /// <exception cref="InvalidOperationException">If this <see cref="IAsyncEnumerable{T}"/> has no elements.</except
 37      /// <seealso cref="System.Linq.Enumerable.First{TSource}(IEnumerable{TSource})"/>
 838      public Task<T> FirstAsync<T>( IAsyncEnumerable<T> enumerable ) => FirstAsync( enumerable, true );
 39
 40      /// <summary>
 41      /// Asynchronously fetches the first item in this <see cref="IAsyncEnumerable{T}"/> and discards any other items.
 42      /// If there are no items, the the default is returned for type <typeparamref name="T"/>.
 43      /// </summary>
 44      /// <typeparam name="T">The type of items being enumerated.</typeparam>
 45      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 46      /// <returns>The first item returned by <see cref="IAsyncEnumerator{T}"/> of this <see cref="IAsyncEnumerable{T}"/
 47      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 48      /// <seealso cref="System.Linq.Enumerable.FirstOrDefault{TSource}(IEnumerable{TSource})"/>
 249      public Task<T> FirstOrDefaultAsync<T>( IAsyncEnumerable<T> enumerable ) => FirstAsync( enumerable, false );
 50
 51      private static async Task<T> FirstAsync<T>( IAsyncEnumerable<T> source, Boolean throwIfNone )
 52      {
 53         T retVal;
 1054         var enumerator = source.GetAsyncEnumerator();
 55         try
 56         {
 1057            var success = await enumerator.WaitForNextAsync();
 1058            retVal = success ? enumerator.TryGetNext( out success ) : default;
 1059            if ( !success )
 60            {
 261               if ( throwIfNone )
 62               {
 163                  throw AsyncProviderUtilities.EmptySequenceException();
 64               }
 65               else
 66               {
 167                  retVal = default;
 68               }
 69            }
 70         }
 71         finally
 72         {
 1073            await enumerator.DisposeAsync();
 74         }
 75
 976         return retVal;
 77
 978      }
 79   }
 80}

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/OfType.cs

#LineLine coverage
 1/*
 2 * Copyright 2017 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Reflection;
 22using System.Text;
 23using System.Threading;
 24using System.Threading.Tasks;
 25using UtilPack;
 26
 27namespace AsyncEnumeration.Implementation.Provider
 28{
 29
 30   public partial class DefaultAsyncProvider
 31   {
 32      /// <summary>
 33      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return only those items which a
 34      /// </summary>
 35      /// <typeparam name="T">The type of source enumerable items.</typeparam>
 36      /// <typeparam name="U">The type of target items.</typeparam>
 37      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 38      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return only those items which are of given type.</return
 39      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 40      /// <seealso cref="System.Linq.Enumerable.OfType{TResult}(System.Collections.IEnumerable)"/>
 41      public IAsyncEnumerable<U> OfType<T, U>( IAsyncEnumerable<T> enumerable )
 42      {
 543         ArgumentValidator.ValidateNotNullReference( enumerable );
 544         return AsyncProviderUtilities.IsOfType(
 545            typeof( T )
 546#if !NET40
 547         .GetTypeInfo()
 548#endif
 549         , typeof( U )
 550#if !NET40
 551         .GetTypeInfo()
 552#endif
 553         ) ?
 554            (IAsyncEnumerable<U>) enumerable :
 955            FromTransformCallback( enumerable, e => new OfTypeEnumerator<T, U>( e ) );
 56      }
 57   }
 58
 59
 60   internal sealed class OfTypeEnumerator<T, U> : IAsyncEnumerator<U>
 61   {
 62      private readonly IAsyncEnumerator<T> _source;
 63
 64      public OfTypeEnumerator(
 65         IAsyncEnumerator<T> source
 66         )
 67      {
 68         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 69      }
 70
 71      public Task<Boolean> WaitForNextAsync()
 72         => this._source.WaitForNextAsync();
 73
 74      public U TryGetNext( out Boolean success )
 75      {
 76         var encountered = false;
 77         T item;
 78         U returnedItem = default;
 79         do
 80         {
 81            item = this._source.TryGetNext( out success );
 82            if ( success && item is U tmp )
 83            {
 84               encountered = true;
 85               returnedItem = tmp;
 86            }
 87         } while ( success && !encountered );
 88
 89         success = encountered;
 90         return returnedItem;
 91      }
 92
 93      public Task DisposeAsync()
 94         => this._source.DisposeAsync();
 95   }
 96
 97
 98}

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Select.cs

#LineLine coverage
 1/*
 2 * Copyright 2017 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Linq;
 22using System.Text;
 23using System.Threading.Tasks;
 24using UtilPack;
 25
 26namespace AsyncEnumeration.Implementation.Provider
 27{
 28
 29   public partial class DefaultAsyncProvider
 30   {
 31      /// <summary>
 32      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return items as transformed by 
 33      /// </summary>
 34      /// <typeparam name="T">The type of source items.</typeparam>
 35      /// <typeparam name="U">The type of target items.</typeparam>
 36      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 37      /// <param name="selector">The callback to transform a single item into <typeparamref name="U"/>.</param>
 38      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return items as transformed by given selector callback.<
 39      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 40      /// <exception cref="ArgumentNullException">If <paramref name="selector"/> is <c>null</c>.</exception>
 41      /// <seealso cref="Enumerable.Select{TSource, TResult}(IEnumerable{TSource}, Func{TSource, TResult})"/>
 42      public IAsyncEnumerable<U> Select<T, U>( IAsyncEnumerable<T> enumerable, Func<T, U> selector )
 43      {
 344         ArgumentValidator.ValidateNotNullReference( enumerable );
 345         ArgumentValidator.ValidateNotNull( nameof( selector ), selector );
 646         return FromTransformCallback( enumerable, selector, ( e, s ) => new SelectEnumerator<T, U>( e, s ) );
 47      }
 48
 49      /// <summary>
 50      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return items as transformed by 
 51      /// </summary>
 52      /// <typeparam name="T">The type of source items.</typeparam>
 53      /// <typeparam name="U">The type of target items.</typeparam>
 54      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 55      /// <param name="asyncSelector">The callback to asynchronously transform a single item into <typeparamref name="U"
 56      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return items as transformed by given selector callback.<
 57      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 58      /// <exception cref="ArgumentNullException">If <paramref name="asyncSelector"/> is <c>null</c>.</exception>
 59      /// <seealso cref="Enumerable.Select{TSource, TResult}(IEnumerable{TSource}, Func{TSource, TResult})"/>
 60      public IAsyncEnumerable<U> Select<T, U>( IAsyncEnumerable<T> enumerable, Func<T, ValueTask<U>> asyncSelector )
 61      {
 162         ArgumentValidator.ValidateNotNullReference( enumerable );
 163         ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 264         return FromTransformCallback( enumerable, asyncSelector, ( e, s ) => new AsyncSelectEnumerator<T, U>( e, s ) );
 65      }
 66   }
 67
 68   internal class SelectEnumerator<T, U> : IAsyncEnumerator<U>
 69   {
 70      private readonly IAsyncEnumerator<T> _source;
 71      private readonly Func<T, U> _selector;
 72
 73      public SelectEnumerator(
 74         IAsyncEnumerator<T> source,
 75         Func<T, U> syncSelector
 76         )
 77      {
 78         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 79         this._selector = ArgumentValidator.ValidateNotNull( nameof( syncSelector ), syncSelector );
 80      }
 81
 82      public Task<Boolean> WaitForNextAsync() => this._source.WaitForNextAsync();
 83
 84      public U TryGetNext( out Boolean success )
 85      {
 86         var item = this._source.TryGetNext( out success );
 87         return success ? this._selector( item ) : default;
 88      }
 89
 90      public Task DisposeAsync() => this._source.DisposeAsync();
 91   }
 92
 93   internal sealed class AsyncSelectEnumerator<T, U> : IAsyncEnumerator<U>
 94   {
 95      private readonly IAsyncEnumerator<T> _source;
 96      private readonly Func<T, ValueTask<U>> _selector;
 97      private readonly LinkedList<U> _list;
 98
 99      public AsyncSelectEnumerator(
 100         IAsyncEnumerator<T> source,
 101         Func<T, ValueTask<U>> asyncSelector
 102         )
 103      {
 104         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 105         this._selector = ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 106         this._list = new LinkedList<U>();
 107      }
 108
 109      public async Task<Boolean> WaitForNextAsync()
 110      {
 111         var list = this._list;
 112         // Discard any previous items
 113         list.Clear();
 114         // We must use the selector in this method, since this is our only asynchronous method while enumerating
 115         while ( list.Count == 0 && await this._source.WaitForNextAsync() )
 116         {
 117            Boolean success;
 118            do
 119            {
 120               var item = this._source.TryGetNext( out success );
 121               if ( success )
 122               {
 123                  list.AddLast( await this._selector( item ) );
 124               }
 125            } while ( success );
 126         }
 127
 128         return list.Count > 0;
 129      }
 130
 131
 132      public U TryGetNext( out Boolean success )
 133      {
 134         success = this._list.Count > 0;
 135         U retVal;
 136         if ( success )
 137         {
 138            retVal = this._list.First.Value;
 139            this._list.RemoveFirst();
 140         }
 141         else
 142         {
 143            retVal = default;
 144         }
 145         return retVal;
 146      }
 147
 148      public Task DisposeAsync() => this._source.DisposeAsync();
 149   }
 150
 151}

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/SelectMany.cs

#LineLine coverage
 1/*
 2 * Copyright 2018 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading;
 23using System.Threading.Tasks;
 24using UtilPack;
 25
 26namespace AsyncEnumeration.Implementation.Provider
 27{
 28
 29   public partial class DefaultAsyncProvider
 30   {
 31      /// <summary>
 32      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will flatten the items returned by g
 33      /// </summary>
 34      /// <typeparam name="T">The type of source items.</typeparam>
 35      /// <typeparam name="U">The type of target items.</typeparam>
 36      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 37      /// <param name="selector">The callback to transform a single item into enumerable of items of type <typeparamref 
 38      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return items as flattened asynchronous enumerable.</retu
 39      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 40      /// <exception cref="ArgumentNullException">If <paramref name="selector"/> is <c>null</c>.</exception>
 41      /// <seealso cref="System.Linq.Enumerable.SelectMany{TSource, TResult}(IEnumerable{TSource}, Func{TSource, IEnumer
 42      public IAsyncEnumerable<U> SelectMany<T, U>( IAsyncEnumerable<T> enumerable, Func<T, IEnumerable<U>> selector )
 43      {
 144         ArgumentValidator.ValidateNotNullReference( enumerable );
 145         ArgumentValidator.ValidateNotNull( nameof( selector ), selector );
 246         return FromTransformCallback( enumerable, selector, ( e, s ) => new SelectManyEnumeratorSync<T, U>( e, s ) );
 47      }
 48
 49      /// <summary>
 50      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will asynchronously flatten the item
 51      /// </summary>
 52      /// <typeparam name="T">The type of source items.</typeparam>
 53      /// <typeparam name="U">The type of target items.</typeparam>
 54      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 55      /// <param name="asyncSelector">The callback to transform a single item into asynchronous enumerable of items of t
 56      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return items as flattened asynchronous enumerable.</retu
 57      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 58      /// <exception cref="ArgumentNullException">If <paramref name="asyncSelector"/> is <c>null</c>.</exception>
 59      /// <seealso cref="System.Linq.Enumerable.SelectMany{TSource, TResult}(IEnumerable{TSource}, Func{TSource, IEnumer
 60      public IAsyncEnumerable<U> SelectMany<T, U>( IAsyncEnumerable<T> enumerable, Func<T, IAsyncEnumerable<U>> asyncSel
 61      {
 162         ArgumentValidator.ValidateNotNullReference( enumerable );
 163         ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 264         return FromTransformCallback( enumerable, asyncSelector, ( e, s ) => new SelectManyEnumeratorAsync<T, U>( e, s 
 65      }
 66
 67      /// <summary>
 68      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will asynchronously flatten the item
 69      /// </summary>
 70      /// <typeparam name="T">The type of source items.</typeparam>
 71      /// <typeparam name="U">The type of target items.</typeparam>
 72      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 73      /// <param name="asyncSelector">The callback to asynchronously transform a single item into enumerable of items of
 74      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return items as flattened asynchronous enumerable.</retu
 75      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 76      /// <exception cref="ArgumentNullException">If <paramref name="asyncSelector"/> is <c>null</c>.</exception>
 77      /// <seealso cref="System.Linq.Enumerable.SelectMany{TSource, TResult}(IEnumerable{TSource}, Func{TSource, IEnumer
 78      public IAsyncEnumerable<U> SelectMany<T, U>( IAsyncEnumerable<T> enumerable, Func<T, Task<IEnumerable<U>>> asyncSe
 79      {
 180         ArgumentValidator.ValidateNotNullReference( enumerable );
 181         ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 282         return FromTransformCallback( enumerable, asyncSelector, ( e, s ) => new SelectManyAsyncEnumerator<T, U>( e, s 
 83      }
 84
 85      /// <summary>
 86      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will asynchronously flatten the item
 87      /// </summary>
 88      /// <typeparam name="T">The type of source items.</typeparam>
 89      /// <typeparam name="U">The type of target items.</typeparam>
 90      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 91      /// <param name="asyncSelector">The callback to asynchronously transform a single item into asynchronous enumerabl
 92      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return items as flattened asynchronous enumerable.</retu
 93      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 94      /// <exception cref="ArgumentNullException">If <paramref name="asyncSelector"/> is <c>null</c>.</exception>
 95      /// <seealso cref="System.Linq.Enumerable.SelectMany{TSource, TResult}(IEnumerable{TSource}, Func{TSource, IEnumer
 96      public IAsyncEnumerable<U> SelectMany<T, U>( IAsyncEnumerable<T> enumerable, Func<T, Task<IAsyncEnumerable<U>>> as
 97      {
 198         ArgumentValidator.ValidateNotNullReference( enumerable );
 199         ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 2100         return FromTransformCallback( enumerable, asyncSelector, ( e, s ) => new SelectManyAsyncEnumeratorAsync<T, U>( 
 101      }
 102
 103   }
 104
 105   internal sealed class SelectManyEnumeratorSync<TSource, TResult> : IAsyncEnumerator<TResult>
 106   {
 107
 108      private readonly IAsyncEnumerator<TSource> _source;
 109      private readonly Func<TSource, IEnumerable<TResult>> _selector;
 110
 111      private IEnumerator<TResult> _current;
 112
 113      public SelectManyEnumeratorSync(
 114         IAsyncEnumerator<TSource> source,
 115          Func<TSource, IEnumerable<TResult>> selector
 116         )
 117      {
 118         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 119         this._selector = ArgumentValidator.ValidateNotNull( nameof( selector ), selector );
 120      }
 121
 122      public Task<Boolean> WaitForNextAsync()
 123      {
 124         var current = this._current;
 125         current?.Dispose();
 126         this._current = null;
 127         return this._source.WaitForNextAsync();
 128      }
 129
 130      public TResult TryGetNext( out Boolean success )
 131      {
 132         var current = this._current;
 133         if ( current == null || !current.MoveNext() )
 134         {
 135            current?.Dispose();
 136            current = null;
 137            do
 138            {
 139               var item = this._source.TryGetNext( out success );
 140               if ( success )
 141               {
 142                  var enumerator = this._selector( item )?.GetEnumerator();
 143                  if ( enumerator != null )
 144                  {
 145                     if ( enumerator.MoveNext() )
 146                     {
 147                        this._current = current = enumerator;
 148                     }
 149                     else
 150                     {
 151                        enumerator.Dispose();
 152                     }
 153                  }
 154
 155               }
 156            } while ( current == null && success );
 157            success = success && current != null;
 158         }
 159         else
 160         {
 161            success = true;
 162         }
 163
 164         return current == null ? default : current.Current;
 165      }
 166
 167      public Task DisposeAsync()
 168      {
 169         return this._source.DisposeAsync();
 170      }
 171   }
 172
 173   internal sealed class SelectManyEnumeratorAsync<TSource, TResult> : IAsyncEnumerator<TResult>
 174   {
 175      private const Int32 CALL_WAIT = 0;
 176      private const Int32 CALL_TRYGET = 1;
 177      private const Int32 ENDED = 2;
 178
 179      private readonly IAsyncEnumerator<TSource> _source;
 180      private readonly Func<TSource, IAsyncEnumerable<TResult>> _selector;
 181
 182      private IAsyncEnumerator<TResult> _current;
 183      private Int32 _state;
 184
 185      public SelectManyEnumeratorAsync(
 186         IAsyncEnumerator<TSource> source,
 187         Func<TSource, IAsyncEnumerable<TResult>> selector
 188         )
 189      {
 190         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 191         this._selector = ArgumentValidator.ValidateNotNull( nameof( selector ), selector );
 192      }
 193
 194      public Task<Boolean> WaitForNextAsync()
 195      {
 196         return this._state == ENDED ?
 197            TaskUtils.False :
 198            this.PerformWaitForNextAsync();
 199      }
 200
 201      public TResult TryGetNext( out Boolean success )
 202      {
 203         return this._current.TryGetNext( out success );
 204      }
 205
 206      public Task DisposeAsync()
 207      {
 208         return this._source.DisposeAsync();
 209      }
 210
 211      private async Task<Boolean> PerformWaitForNextAsync()
 212      {
 213         var current = this._current;
 214         Boolean retVal;
 215         if ( current == null || !( await current.WaitForNextAsync() ) )
 216         {
 217            if ( current != null )
 218            {
 219               await current.DisposeAsync();
 220            }
 221            current = null;
 222
 223            var state = this._state;
 224            do
 225            {
 226               if ( state == CALL_WAIT )
 227               {
 228                  retVal = await this._source.WaitForNextAsync();
 229                  if ( retVal )
 230                  {
 231                     state = CALL_TRYGET;
 232                  }
 233               }
 234               if ( state == CALL_TRYGET )
 235               {
 236                  var item = this._source.TryGetNext( out retVal );
 237                  if ( retVal )
 238                  {
 239                     current = this._selector( item )?.GetAsyncEnumerator();
 240                  }
 241                  else
 242                  {
 243                     state = CALL_WAIT;
 244                  }
 245               }
 246               else
 247               {
 248                  state = ENDED;
 249               }
 250            } while ( state == CALL_WAIT || ( state == CALL_TRYGET && current == null ) );
 251
 252            Interlocked.Exchange( ref this._state, state );
 253            Interlocked.Exchange( ref this._current, current );
 254         }
 255
 256         return this._state != ENDED;
 257      }
 258   }
 259
 260   internal sealed class SelectManyAsyncEnumerator<TSource, TResult> : IAsyncEnumerator<TResult>
 261   {
 262      private readonly IAsyncEnumerator<TSource> _source;
 263      private readonly Func<TSource, Task<IEnumerable<TResult>>> _selector;
 264      private readonly LinkedList<TResult> _list;
 265
 266      public SelectManyAsyncEnumerator(
 267         IAsyncEnumerator<TSource> source,
 268         Func<TSource, Task<IEnumerable<TResult>>> selector
 269         )
 270      {
 271         this._source = source;
 272         this._selector = selector;
 273         this._list = new LinkedList<TResult>();
 274      }
 275
 276
 277      public async Task<Boolean> WaitForNextAsync()
 278      {
 279         var stack = this._list;
 280         // Discard any previous items
 281         stack.Clear();
 282         // We must use the predicate in this method, since this is our only asynchronous method while enumerating
 283         while ( stack.Count == 0 && await this._source.WaitForNextAsync() )
 284         {
 285            Boolean success;
 286            do
 287            {
 288               var next = this._source.TryGetNext( out success );
 289               IEnumerable<TResult> items;
 290               if ( success && ( items = await this._selector( next ) ) != null )
 291               {
 292                  foreach ( var item in items )
 293                  {
 294                     stack.AddLast( item );
 295                  }
 296
 297               }
 298            } while ( success );
 299         }
 300
 301         return stack.Count > 0;
 302
 303      }
 304
 305      public TResult TryGetNext( out Boolean success )
 306      {
 307         success = this._list.Count > 0;
 308         TResult retVal;
 309         if ( success )
 310         {
 311            retVal = this._list.First.Value;
 312            this._list.RemoveFirst();
 313         }
 314         else
 315         {
 316            retVal = default;
 317         }
 318         return retVal;
 319      }
 320
 321      public Task DisposeAsync()
 322         => this._source.DisposeAsync();
 323
 324   }
 325
 326   internal sealed class SelectManyAsyncEnumeratorAsync<TSource, TResult> : IAsyncEnumerator<TResult>
 327   {
 328      private readonly IAsyncEnumerator<TSource> _source;
 329      private readonly Func<TSource, Task<IAsyncEnumerable<TResult>>> _selector;
 330      private readonly LinkedList<TResult> _list;
 331
 332      public SelectManyAsyncEnumeratorAsync(
 333         IAsyncEnumerator<TSource> source,
 334         Func<TSource, Task<IAsyncEnumerable<TResult>>> selector
 335         )
 336      {
 337         this._source = source;
 338         this._selector = selector;
 339         this._list = new LinkedList<TResult>();
 340      }
 341
 342
 343      public async Task<Boolean> WaitForNextAsync()
 344      {
 345         var list = this._list;
 346         // Discard any previous items
 347         list.Clear();
 348         // We must use the predicate in this method, since this is our only asynchronous method while enumerating
 349         while ( list.Count == 0 && await this._source.WaitForNextAsync() )
 350         {
 351            Boolean success;
 352            do
 353            {
 354               var next = this._source.TryGetNext( out success );
 355               IAsyncEnumerable<TResult> items;
 356               if ( success && ( items = await this._selector( next ) ) != null )
 357               {
 358                  await items.EnumerateAsync( item => list.AddLast( item ) );
 359               }
 360            } while ( success );
 361         }
 362
 363         return list.Count > 0;
 364
 365      }
 366
 367      public TResult TryGetNext( out Boolean success )
 368      {
 369         success = this._list.Count > 0;
 370         TResult retVal;
 371         if ( success )
 372         {
 373            retVal = this._list.First.Value;
 374            this._list.RemoveFirst();
 375         }
 376         else
 377         {
 378            retVal = default;
 379         }
 380         return retVal;
 381      }
 382
 383      public Task DisposeAsync()
 384         => this._source.DisposeAsync();
 385
 386   }
 387
 388}
 389

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Skip.cs

#LineLine coverage
 1/*
 2 * Copyright 2018 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading;
 23using System.Threading.Tasks;
 24using UtilPack;
 25
 26namespace AsyncEnumeration.Implementation.Provider
 27{
 28
 29   public partial class DefaultAsyncProvider
 30   {
 31      /// <summary>
 32      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return at most given amount of 
 33      /// </summary>
 34      /// <typeparam name="T">The type of items.</typeparam>
 35      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 36      /// <param name="amount">The maximum amount of items to return. If zero or less, will return empty enumerable.</pa
 37      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return at most given amount of items.</returns>
 38      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 39      /// <seealso cref="System.Linq.Enumerable.Skip{TSource}(IEnumerable{TSource}, Int32)"/>
 40      public IAsyncEnumerable<T> Skip<T>( IAsyncEnumerable<T> enumerable, Int32 amount )
 41      {
 142         ArgumentValidator.ValidateNotNullReference( enumerable );
 143         return amount <= 0 ?
 144            enumerable :
 1145            this.Where( enumerable, item => amount <= 0 || Interlocked.Decrement( ref amount ) < 0 );
 46      }
 47
 48      /// <summary>
 49      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return at most given amount of 
 50      /// </summary>
 51      /// <typeparam name="T">The type of items.</typeparam>
 52      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 53      /// <param name="amount">The maximum amount of items to return. If zero or less, will return empty enumerable.</pa
 54      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return at most given amount of items.</returns>
 55      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 56      /// <seealso cref="System.Linq.Enumerable.Skip{TSource}(IEnumerable{TSource}, Int32)"/>
 57      public IAsyncEnumerable<T> Skip<T>( IAsyncEnumerable<T> enumerable, Int64 amount )
 58      {
 159         ArgumentValidator.ValidateNotNullReference( enumerable );
 160         return amount <= 0 ?
 161            enumerable :
 1162            this.Where( enumerable, item => amount <= 0 || Interlocked.Decrement( ref amount ) < 0 );
 63      }
 64
 65
 66      /// <summary>
 67      /// This extension
 68      /// </summary>
 69      /// <typeparam name="T"></typeparam>
 70      /// <param name="enumerable"></param>
 71      /// <param name="predicate"></param>
 72      /// <returns></returns>
 73      /// <seealso cref="System.Linq.Enumerable.SkipWhile{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 74      public IAsyncEnumerable<T> SkipWhile<T>( IAsyncEnumerable<T> enumerable, Func<T, Boolean> predicate )
 75      {
 176         ArgumentValidator.ValidateNotNullReference( enumerable );
 177         ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 178         var falseSeen = 0;
 179         return this.Where( enumerable, item =>
 180         {
 1181            if ( falseSeen == 0 && !predicate( item ) )
 182            {
 283               Interlocked.Exchange( ref falseSeen, 1 );
 184            }
 1185            return falseSeen == 1;
 186         } );
 87      }
 88
 89      /// <summary>
 90      ///
 91      /// </summary>
 92      /// <typeparam name="T"></typeparam>
 93      /// <param name="enumerable"></param>
 94      /// <param name="asyncPredicate"></param>
 95      /// <returns></returns>
 96      /// <seealso cref="System.Linq.Enumerable.SkipWhile{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 97      public IAsyncEnumerable<T> SkipWhile<T>( IAsyncEnumerable<T> enumerable, Func<T, ValueTask<Boolean>> asyncPredicat
 98      {
 199         ArgumentValidator.ValidateNotNullReference( enumerable );
 1100         ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 1101         var falseSeen = 0;
 1102         return this.Where( enumerable, async item =>
 1103         {
 11104            if ( falseSeen == 0 && !( await asyncPredicate( item ) ) )
 1105            {
 2106               Interlocked.Exchange( ref falseSeen, 1 );
 1107            }
 11108            return falseSeen == 1;
 11109         } );
 110      }
 111   }
 112}

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Take.cs

#LineLine coverage
 1/*
 2 * Copyright 2018 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading;
 23using System.Threading.Tasks;
 24using UtilPack;
 25
 26namespace AsyncEnumeration.Implementation.Provider
 27{
 28   public partial class DefaultAsyncProvider
 29   {
 30      /// <summary>
 31      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return at most given amount of 
 32      /// </summary>
 33      /// <typeparam name="T">The type of items.</typeparam>
 34      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 35      /// <param name="amount">The maximum amount of items to return. If zero or less, will return empty enumerable.</pa
 36      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return at most given amount of items.</returns>
 37      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 38      /// <seealso cref="System.Linq.Enumerable.Take{TSource}(IEnumerable{TSource}, Int32)"/>
 39      public IAsyncEnumerable<T> Take<T>( IAsyncEnumerable<T> enumerable, Int32 amount )
 40      {
 841         ArgumentValidator.ValidateNotNullReference( enumerable );
 842         return amount <= 0 ?
 843            EmptyAsync<T>.Enumerable :
 1644            FromTransformCallback( enumerable, amount, ( e, a ) => new TakeEnumerator32<T>( e, a ) );
 45      }
 46
 47      /// <summary>
 48      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will return at most given amount of 
 49      /// </summary>
 50      /// <typeparam name="T">The type of items.</typeparam>
 51      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 52      /// <param name="amount">The maximum amount of items to return. If zero or less, will return empty enumerable.</pa
 53      /// <returns><see cref="IAsyncEnumerable{T}"/> which will return at most given amount of items.</returns>
 54      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 55      /// <seealso cref="System.Linq.Enumerable.Take{TSource}(IEnumerable{TSource}, Int32)"/>
 56      public IAsyncEnumerable<T> Take<T>( IAsyncEnumerable<T> enumerable, Int64 amount )
 57      {
 458         ArgumentValidator.ValidateNotNullReference( enumerable );
 459         return amount <= 0 ?
 460            EmptyAsync<T>.Enumerable :
 861            FromTransformCallback( enumerable, amount, ( e, a ) => new TakeEnumerator64<T>( e, a ) );
 62      }
 63
 64      /// <summary>
 65      /// This method returns new <see cref="IAsyncEnumerable{T}"/> that will include only the first elements of this <s
 66      /// </summary>
 67      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 68      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 69      /// <param name="predicate">The synchronous callback to check whether element satisfies condition.</param>
 70      /// <returns><see cref="IAsyncEnumerable{T}"/> which will include only the first elements of this <see cref="IAsyn
 71      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 72      /// <exception cref="ArgumentNullException">If <paramref name="predicate"/> is <c>null</c>.</exception>
 73      /// <seealso cref="System.Linq.Enumerable.TakeWhile{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 74      public IAsyncEnumerable<T> TakeWhile<T>( IAsyncEnumerable<T> enumerable, Func<T, Boolean> predicate )
 75      {
 776         ArgumentValidator.ValidateNotNullReference( enumerable );
 777         ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 1478         return FromTransformCallback( enumerable, predicate, ( e, p ) => new TakeWhileEnumeratorSync<T>( e, p ) );
 79      }
 80
 81      /// <summary>
 82      /// This method returns new <see cref="IAsyncEnumerable{T}"/> that will include only the first elements of this <s
 83      /// </summary>
 84      /// <typeparam name="T">The type of elements being enumerated.</typeparam>
 85      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 86      /// <param name="asyncPredicate">The potentially asynchronous callback to check whether element satisfies conditio
 87      /// <returns><see cref="IAsyncEnumerable{T}"/> which will include only the first elements of this <see cref="IAsyn
 88      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 89      /// <exception cref="ArgumentNullException">If <paramref name="asyncPredicate"/> is <c>null</c>.</exception>
 90      /// <seealso cref="System.Linq.Enumerable.TakeWhile{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 91      public IAsyncEnumerable<T> TakeWhile<T>( IAsyncEnumerable<T> enumerable, Func<T, Task<Boolean>> asyncPredicate )
 92      {
 593         ArgumentValidator.ValidateNotNullReference( enumerable );
 594         ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 1095         return FromTransformCallback( enumerable, asyncPredicate, ( e, p ) => new TakeWhileEnumeratorAsync<T>( e, p ) )
 96      }
 97   }
 98
 99   internal sealed class TakeEnumerator32<T> : IAsyncEnumerator<T>
 100   {
 101      private readonly IAsyncEnumerator<T> _source;
 102      private Int32 _amount;
 103
 104      public TakeEnumerator32(
 105         IAsyncEnumerator<T> source,
 106         Int32 amount
 107         )
 108      {
 109         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 110         this._amount = Math.Max( amount, 0 );
 111      }
 112
 113      public Task<Boolean> WaitForNextAsync() => this._amount <= 0 ? TaskUtils.False : this._source.WaitForNextAsync();
 114
 115      public T TryGetNext( out Boolean success )
 116      {
 117         success = this._amount > 0;
 118         var retVal = success ? this._source.TryGetNext( out success ) : default;
 119         if ( success )
 120         {
 121            --this._amount;
 122         }
 123         return retVal;
 124      }
 125
 126      public Task DisposeAsync() => this._source.DisposeAsync();
 127   }
 128
 129   internal sealed class TakeEnumerator64<T> : IAsyncEnumerator<T>
 130   {
 131      private readonly IAsyncEnumerator<T> _source;
 132      private Int64 _amount;
 133
 134      public TakeEnumerator64(
 135         IAsyncEnumerator<T> source,
 136         Int64 amount
 137         )
 138      {
 139         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 140         this._amount = Math.Max( amount, 0 );
 141      }
 142
 143      public Task<Boolean> WaitForNextAsync() => this._amount <= 0 ? TaskUtils.False : this._source.WaitForNextAsync();
 144
 145      public T TryGetNext( out Boolean success )
 146      {
 147         success = this._amount > 0;
 148         var retVal = success ? this._source.TryGetNext( out success ) : default;
 149         if ( success )
 150         {
 151            --this._amount;
 152         }
 153         return retVal;
 154      }
 155
 156      public Task DisposeAsync() => this._source.DisposeAsync();
 157   }
 158
 159   internal sealed class TakeWhileEnumeratorSync<T> : IAsyncEnumerator<T>
 160   {
 161      private const Int32 FALSE_NOT_SEEN = 0;
 162      private const Int32 FALSE_SEEN = 1;
 163
 164      private readonly IAsyncEnumerator<T> _source;
 165      private readonly Func<T, Boolean> _predicate;
 166      private Int32 _state;
 167
 168      public TakeWhileEnumeratorSync(
 169         IAsyncEnumerator<T> source,
 170         Func<T, Boolean> predicate
 171         )
 172      {
 173         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 174         this._predicate = ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 175      }
 176
 177      public Task<Boolean> WaitForNextAsync() => this._state == FALSE_NOT_SEEN ? this._source.WaitForNextAsync() : TaskU
 178
 179      public T TryGetNext( out Boolean success )
 180      {
 181         success = this._state == FALSE_NOT_SEEN;
 182         T retVal;
 183         if ( success )
 184         {
 185            retVal = this._source.TryGetNext( out success );
 186            if ( success )
 187            {
 188               success = this._predicate( retVal );
 189               if ( !success )
 190               {
 191                  this._state = FALSE_SEEN;
 192                  retVal = default;
 193               }
 194            }
 195         }
 196         else
 197         {
 198            retVal = default;
 199         }
 200         return retVal;
 201      }
 202
 203      public Task DisposeAsync() => this._source.DisposeAsync();
 204   }
 205
 206   internal sealed class TakeWhileEnumeratorAsync<T> : IAsyncEnumerator<T>
 207   {
 208      private const Int32 FALSE_NOT_SEEN = 0;
 209      private const Int32 FALSE_SEEN = 1;
 210
 211      private readonly IAsyncEnumerator<T> _source;
 212      private readonly Func<T, Task<Boolean>> _predicate;
 213      private readonly Stack<T> _stack;
 214      private Int32 _state;
 215
 216      public TakeWhileEnumeratorAsync(
 217         IAsyncEnumerator<T> source,
 218         Func<T, Task<Boolean>> asyncPredicate
 219         )
 220      {
 221         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 222         this._predicate = ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 223         this._stack = new Stack<T>();
 224      }
 225
 226      public Task<Boolean> WaitForNextAsync()
 227      {
 228         return this._state == FALSE_NOT_SEEN ?
 229            this.PeekNextAsync() :
 230            TaskUtils.False;
 231      }
 232
 233      public T TryGetNext( out Boolean success )
 234      {
 235         success = this._stack.Count > 0;
 236         return success ? this._stack.Pop() : default;
 237      }
 238
 239      public Task DisposeAsync() => this._source.DisposeAsync();
 240
 241      private async Task<Boolean> PeekNextAsync()
 242      {
 243         var stack = this._stack;
 244         // Discard any previous items
 245         stack.Clear();
 246         var falseNotSeen = true;
 247         while ( falseNotSeen && stack.Count == 0 && await this._source.WaitForNextAsync() )
 248         {
 249            Boolean success;
 250            do
 251            {
 252               var item = this._source.TryGetNext( out success );
 253               if ( success )
 254               {
 255                  if ( await this._predicate( item ) )
 256                  {
 257                     stack.Push( item );
 258                  }
 259                  else
 260                  {
 261                     this._state = FALSE_SEEN;
 262                     success = false;
 263                     falseNotSeen = false;
 264                  }
 265               }
 266            } while ( success );
 267         }
 268
 269         return stack.Count > 0;
 270      }
 271   }
 272
 273
 274}

/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Where.cs

#LineLine coverage
 1/*
 2 * Copyright 2017 Stanislav Muhametsin. All rights Reserved.
 3 *
 4 * Licensed  under the  Apache License,  Version 2.0  (the "License");
 5 * you may not use  this file  except in  compliance with the License.
 6 * You may obtain a copy of the License at
 7 *
 8 *   http://www.apache.org/licenses/LICENSE-2.0
 9 *
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed  under the  License is distributed on an "AS IS" BASIS,
 12 * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
 13 * implied.
 14 *
 15 * See the License for the specific language governing permissions and
 16 * limitations under the License.
 17 */
 18using AsyncEnumeration.Abstractions;
 19using System;
 20using System.Collections.Generic;
 21using System.Text;
 22using System.Threading;
 23using System.Threading.Tasks;
 24using UtilPack;
 25
 26namespace AsyncEnumeration.Implementation.Provider
 27{
 28
 29   public partial class DefaultAsyncProvider
 30   {
 31      /// <summary>
 32      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will filter items based on given pre
 33      /// </summary>
 34      /// <typeparam name="T">The type of items.</typeparam>
 35      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 36      /// <param name="predicate">The callback which will filter the results. By returning <c>true</c>, the result will 
 37      /// <returns><see cref="IAsyncEnumerable{T}"/> which will filter items based on given predicate callback.</returns
 38      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 39      /// <exception cref="ArgumentNullException">If <paramref name="predicate"/> is <c>null</c>.</exception>
 40      /// <seealso cref="System.Linq.Enumerable.Where{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 41      public IAsyncEnumerable<T> Where<T>( IAsyncEnumerable<T> enumerable, Func<T, Boolean> predicate )
 42      {
 543         ArgumentValidator.ValidateNotNullReference( enumerable );
 544         ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 1045         return FromTransformCallback( enumerable, predicate, ( e, p ) => new WhereEnumerator<T>( e, p ) );
 46      }
 47
 48      /// <summary>
 49      /// This extension method will return <see cref="IAsyncEnumerable{T}"/> which will filter items based on given asy
 50      /// </summary>
 51      /// <typeparam name="T">The type of items.</typeparam>
 52      /// <param name="enumerable">This <see cref="IAsyncEnumerable{T}"/>.</param>
 53      /// <param name="asyncPredicate">The callback which will asynchronously filter the results. By returning <c>true</
 54      /// <returns><see cref="IAsyncEnumerable{T}"/> which will filter items based on given predicate callback.</returns
 55      /// <exception cref="NullReferenceException">If this <see cref="IAsyncEnumerable{T}"/> is <c>null</c>.</exception>
 56      /// <exception cref="ArgumentNullException">If <paramref name="asyncPredicate"/> is <c>null</c>.</exception>
 57      /// <seealso cref="System.Linq.Enumerable.Where{TSource}(IEnumerable{TSource}, Func{TSource, Boolean})"/>
 58      public IAsyncEnumerable<T> Where<T>( IAsyncEnumerable<T> enumerable, Func<T, Task<Boolean>> asyncPredicate )
 59      {
 260         ArgumentValidator.ValidateNotNullReference( enumerable );
 261         ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 462         return FromTransformCallback( enumerable, asyncPredicate, ( e, p ) => new AsyncWhereEnumerator<T>( e, p ) );
 63      }
 64   }
 65
 66   internal sealed class WhereEnumerator<T> : IAsyncEnumerator<T>
 67   {
 68      private readonly IAsyncEnumerator<T> _source;
 69      private readonly Func<T, Boolean> _predicate;
 70
 71      public WhereEnumerator(
 72         IAsyncEnumerator<T> source,
 73         Func<T, Boolean> syncPredicate
 74         )
 75      {
 76         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 77         this._predicate = ArgumentValidator.ValidateNotNull( nameof( syncPredicate ), syncPredicate );
 78      }
 79
 80      public Task<Boolean> WaitForNextAsync() => this._source.WaitForNextAsync();
 81
 82      public T TryGetNext( out Boolean success )
 83      {
 84         var encountered = false;
 85         T item;
 86         do
 87         {
 88            item = this._source.TryGetNext( out success );
 89            encountered = success && this._predicate( item );
 90         } while ( success && !encountered );
 91
 92         success = encountered;
 93         return item;
 94      }
 95
 96      public Task DisposeAsync() => this._source.DisposeAsync();
 97   }
 98
 99   internal sealed class AsyncWhereEnumerator<T> : IAsyncEnumerator<T>
 100   {
 101      private readonly IAsyncEnumerator<T> _source;
 102      private readonly Func<T, Task<Boolean>> _predicate;
 103      private readonly LinkedList<T> _list;
 104
 105      public AsyncWhereEnumerator(
 106         IAsyncEnumerator<T> source,
 107         Func<T, Task<Boolean>> asyncPredicate
 108         )
 109      {
 110         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 111         this._predicate = asyncPredicate;
 112         this._list = new LinkedList<T>();
 113      }
 114
 115      //public Boolean IsConcurrentEnumerationSupported => this._source.IsConcurrentEnumerationSupported;
 116
 117      public async Task<Boolean> WaitForNextAsync()
 118      {
 119         var list = this._list;
 120         // Discard any previous items
 121         list.Clear();
 122         // We must use the predicate in this method, since this is our only asynchronous method while enumerating
 123         while ( list.Count == 0 && await this._source.WaitForNextAsync() )
 124         {
 125            Boolean success;
 126            do
 127            {
 128               var item = this._source.TryGetNext( out success );
 129               if ( success && await this._predicate( item ) )
 130               {
 131                  list.AddLast( item );
 132               }
 133            } while ( success );
 134         }
 135
 136         return list.Count > 0;
 137      }
 138
 139
 140      public T TryGetNext( out Boolean success )
 141      {
 142         success = this._list.Count > 0;
 143         T retVal;
 144         if ( success )
 145         {
 146            retVal = this._list.First.Value;
 147            this._list.RemoveFirst();
 148         }
 149         else
 150         {
 151            retVal = default;
 152         }
 153         return retVal;
 154      }
 155
 156      public Task DisposeAsync() => this._source.DisposeAsync();
 157   }
 158
 159}

Methods/Properties

AggregateAsync()
AggregateAsync()
>c__DisplayClass3_0`1/<<AggregateAsync()
AggregateAsync()
AggregateAsync()
>c__DisplayClass5_0`2/<<AggregateAsync()
AnyAsync()
AnyAsync(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Boolean>)
AnyAsync(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.ValueTask`1<System.Boolean>>)
AllAsync()
AllAsync()
>c__DisplayClass10_0`1/<<AllAsync()
AnyAsync_NotNull()
AnyAsync_NotNull()
>c__DisplayClass12_0`1/<<AnyAsync_NotNull()
Instance()
.ctor()
FromTransformCallback(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<System.Collections.Generic.IAsyncEnumerator`1<T>,System.Collections.Generic.IAsyncEnumerator`1<U>>)
FromTransformCallback(System.Collections.Generic.IAsyncEnumerable`1<T>,TArg,System.Func`3<System.Collections.Generic.IAsyncEnumerator`1<T>,TArg,System.Collections.Generic.IAsyncEnumerator`1<U>>)
.ctor(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<System.Collections.Generic.IAsyncEnumerator`1<T>,System.Collections.Generic.IAsyncEnumerator`1<U>>)
cEnumeration.Abstractions.IAsyncEnumerable.get_AsyncProvider()
System.Collections.Generic.IAsyncEnumerable<U>.GetAsyncEnumerator()
.ctor(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`3<System.Collections.Generic.IAsyncEnumerator`1<T>,TArg,System.Collections.Generic.IAsyncEnumerator`1<U>>,TArg)
cEnumeration.Abstractions.IAsyncEnumerable.get_AsyncProvider()
System.Collections.Generic.IAsyncEnumerable<U>.GetAsyncEnumerator()
FirstAsync(System.Collections.Generic.IAsyncEnumerable`1<T>)
FirstOrDefaultAsync(System.Collections.Generic.IAsyncEnumerable`1<T>)
FirstAsync()
OfType(System.Collections.Generic.IAsyncEnumerable`1<T>)
Select(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,U>)
Select(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.ValueTask`1<U>>)
SelectMany(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Collections.Generic.IEnumerable`1<U>>)
SelectMany(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Collections.Generic.IAsyncEnumerable`1<U>>)
SelectMany(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.Task`1<System.Collections.Generic.IEnumerable`1<U>>>)
SelectMany(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.Task`1<System.Collections.Generic.IAsyncEnumerable`1<U>>>)
Skip(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Int32)
Skip(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Int64)
SkipWhile(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Boolean>)
SkipWhile(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.ValueTask`1<System.Boolean>>)
Take(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Int32)
Take(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Int64)
TakeWhile(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Boolean>)
TakeWhile(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.Task`1<System.Boolean>>)
Where(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Boolean>)
Where(System.Collections.Generic.IAsyncEnumerable`1<T>,System.Func`2<T,System.Threading.Tasks.Task`1<System.Boolean>>)