Summary

Class:AsyncEnumeration.Implementation.Provider.AsyncSelectEnumerator`2
Assembly:AsyncEnumeration.Implementation.Provider
File(s):/repo-dir/contents/Source/Code/AsyncEnumeration.Implementation.Provider/Select.cs
Covered lines:25
Uncovered lines:0
Coverable lines:25
Total lines:151
Line coverage:100%
Branch coverage:81.2%
Tag:7d9974899246b95481b7aa9cd3a1462ae2a67c91

Coverage History

Metrics

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

File(s)

/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      {
 44         ArgumentValidator.ValidateNotNullReference( enumerable );
 45         ArgumentValidator.ValidateNotNull( nameof( selector ), selector );
 46         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      {
 62         ArgumentValidator.ValidateNotNullReference( enumerable );
 63         ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 64         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
 199      public AsyncSelectEnumerator(
 1100         IAsyncEnumerator<T> source,
 1101         Func<T, ValueTask<U>> asyncSelector
 1102         )
 103      {
 1104         this._source = ArgumentValidator.ValidateNotNull( nameof( source ), source );
 1105         this._selector = ArgumentValidator.ValidateNotNull( nameof( asyncSelector ), asyncSelector );
 1106         this._list = new LinkedList<U>();
 1107      }
 108
 109      public async Task<Boolean> WaitForNextAsync()
 110      {
 2111         var list = this._list;
 112         // Discard any previous items
 2113         list.Clear();
 114         // We must use the selector in this method, since this is our only asynchronous method while enumerating
 3115         while ( list.Count == 0 && await this._source.WaitForNextAsync() )
 116         {
 117            Boolean success;
 118            do
 119            {
 11120               var item = this._source.TryGetNext( out success );
 11121               if ( success )
 122               {
 10123                  list.AddLast( await this._selector( item ) );
 124               }
 11125            } while ( success );
 126         }
 127
 2128         return list.Count > 0;
 2129      }
 130
 131
 132      public U TryGetNext( out Boolean success )
 133      {
 11134         success = this._list.Count > 0;
 135         U retVal;
 11136         if ( success )
 137         {
 10138            retVal = this._list.First.Value;
 10139            this._list.RemoveFirst();
 10140         }
 141         else
 142         {
 1143            retVal = default;
 144         }
 11145         return retVal;
 146      }
 147
 1148      public Task DisposeAsync() => this._source.DisposeAsync();
 149   }
 150
 151}