Summary

Class:AsyncEnumeration.Implementation.Provider.AsyncWhereEnumerator`1
Assembly:AsyncEnumeration.Implementation.Provider
File(s):/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Where.cs
Covered lines:25
Uncovered lines:0
Coverable lines:25
Total lines:159
Line coverage:100%
Branch coverage:83.3%
Tag:7d9974899246b95481b7aa9cd3a1462ae2a67c91

Coverage History

Metrics

MethodCyclomatic complexity NPath complexity Sequence coverage Branch coverage
.ctor(...)101%0%
WaitForNextAsync()1601%1%
TryGetNext(...)201%1%
DisposeAsync()101%0%

File(s)

/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      {
 43         ArgumentValidator.ValidateNotNullReference( enumerable );
 44         ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 45         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      {
 60         ArgumentValidator.ValidateNotNullReference( enumerable );
 61         ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 62         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
 2105      public AsyncWhereEnumerator(
 2106         IAsyncEnumerator<T> source,
 2107         Func<T, Task<Boolean>> asyncPredicate
 2108         )
 109      {
 2110         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 2111         this._predicate = asyncPredicate;
 2112         this._list = new LinkedList<T>();
 2113      }
 114
 115      //public Boolean IsConcurrentEnumerationSupported => this._source.IsConcurrentEnumerationSupported;
 116
 117      public async Task<Boolean> WaitForNextAsync()
 118      {
 4119         var list = this._list;
 120         // Discard any previous items
 4121         list.Clear();
 122         // We must use the predicate in this method, since this is our only asynchronous method while enumerating
 6123         while ( list.Count == 0 && await this._source.WaitForNextAsync() )
 124         {
 125            Boolean success;
 126            do
 127            {
 22128               var item = this._source.TryGetNext( out success );
 22129               if ( success && await this._predicate( item ) )
 130               {
 10131                  list.AddLast( item );
 132               }
 44133            } while ( success );
 134         }
 135
 4136         return list.Count > 0;
 4137      }
 138
 139
 140      public T TryGetNext( out Boolean success )
 141      {
 12142         success = this._list.Count > 0;
 143         T retVal;
 12144         if ( success )
 145         {
 10146            retVal = this._list.First.Value;
 10147            this._list.RemoveFirst();
 10148         }
 149         else
 150         {
 2151            retVal = default;
 152         }
 12153         return retVal;
 154      }
 155
 2156      public Task DisposeAsync() => this._source.DisposeAsync();
 157   }
 158
 159}