Summary

Class:AsyncEnumeration.Implementation.Provider.TakeEnumerator64`1
Assembly:AsyncEnumeration.Implementation.Provider
File(s):/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Take.cs
Covered lines:14
Uncovered lines:0
Coverable lines:14
Total lines:274
Line coverage:100%
Branch coverage:100%
Tag:7d9974899246b95481b7aa9cd3a1462ae2a67c91

Coverage History

Metrics

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

File(s)

/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      {
 41         ArgumentValidator.ValidateNotNullReference( enumerable );
 42         return amount <= 0 ?
 43            EmptyAsync<T>.Enumerable :
 44            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      {
 58         ArgumentValidator.ValidateNotNullReference( enumerable );
 59         return amount <= 0 ?
 60            EmptyAsync<T>.Enumerable :
 61            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      {
 76         ArgumentValidator.ValidateNotNullReference( enumerable );
 77         ArgumentValidator.ValidateNotNull( nameof( predicate ), predicate );
 78         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      {
 93         ArgumentValidator.ValidateNotNullReference( enumerable );
 94         ArgumentValidator.ValidateNotNull( nameof( asyncPredicate ), asyncPredicate );
 95         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
 4134      public TakeEnumerator64(
 4135         IAsyncEnumerator<T> source,
 4136         Int64 amount
 4137         )
 138      {
 4139         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 4140         this._amount = Math.Max( amount, 0 );
 4141      }
 142
 17143      public Task<Boolean> WaitForNextAsync() => this._amount <= 0 ? TaskUtils.False : this._source.WaitForNextAsync();
 144
 145      public T TryGetNext( out Boolean success )
 146      {
 46147         success = this._amount > 0;
 46148         var retVal = success ? this._source.TryGetNext( out success ) : default;
 46149         if ( success )
 150         {
 33151            --this._amount;
 152         }
 46153         return retVal;
 154      }
 155
 4156      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}