예제 #1
0
        public static System.Collections.Generic.IAsyncEnumerable <T> ToResultsAsyncEnumerable <T>(this IEnumerable <Task <T> > tasks)
        {
            return(AsyncEnumerable.Create(
                       (token) =>
            {
                var enumerator = tasks.GetEnumerator();
                T current = default;

                return AsyncEnumerator.Create(
                    async() =>
                {
                    if (enumerator.MoveNext())
                    {
                        current = await enumerator.Current;
                        return true;
                    }

                    return false;
                },
                    () => current,
                    () =>
                {
                    enumerator.Dispose();
                    return new ValueTask();
                });
            }));
        }
    public IAsyncEnumerable <TDocument> FindAsyncEnumerable <TDocument>(IMongoCollection <TDocument> collection, FilterDefinition <TDocument> filter)
    {
        IAsyncEnumerable <TDocument> a = AsyncEnumerable.Create(
            token =>
        {
            IAsyncCursor <TDocument>?cursor = null;

            async ValueTask <bool> MoveNextAsync()
            {
                cursor ??= await collection.FindAsync(filter, null, token);

                return(await cursor.MoveNextAsync(token));
            }

            return(AsyncEnumerator.Create(
                       MoveNextAsync,
                       () => cursor?.Current ?? ImmutableList <TDocument> .Empty,
                       () =>
            {
                cursor?.Dispose();
                return default;
            }));
        })
                                         .SelectMany(x => x.ToAsyncEnumerable());

        return(a);
    }
예제 #3
0
    public static IAsyncEnumerable <TDocument> ToAsyncEnumerable <TDocument>(
        this IAsyncCursorSource <TDocument> source,
        CancellationToken cancellationToken = default(CancellationToken))
    {
        return(AsyncEnumerable.Create(
                   token =>
        {
            IAsyncCursor <TDocument>?cursor = null;

            async ValueTask <bool> MoveNextAsync()
            {
                cursor ??= await source.ToCursorAsync(cancellationToken);

                return await cursor.MoveNextAsync(token);
            }

            return AsyncEnumerator.Create(
                MoveNextAsync,
                () => cursor?.Current ?? ImmutableList <TDocument> .Empty,
                () =>
            {
                cursor?.Dispose();
                return default;
            });
        })
               .SelectMany(x => x.ToAsyncEnumerable()));
    }
        /// <summary>
        /// Enumerates a given <paramref name="enumerable"/> until the predicate <paramref name="predicate"/> returns true.
        /// </summary>
        private static System.Collections.Generic.IAsyncEnumerable <T> StopAfter <T>(this System.Collections.Generic.IAsyncEnumerable <T> enumerable, Func <T, bool> predicate)
        {
            return(AsyncEnumerable.Create(
                       token =>
            {
                var enumerator = enumerable.GetAsyncEnumerator(token);
                bool stop = false;
                return AsyncEnumerator.Create(
                    async() =>
                {
                    if (stop)
                    {
                        return false;
                    }

                    if (await enumerator.MoveNextAsync(token))
                    {
                        if (!predicate(enumerator.Current))
                        {
                            stop = true;
                        }

                        return true;
                    }

                    return false;
                },
                    () => enumerator.Current,
                    () => enumerator.DisposeAsync());
            }));
        }
예제 #5
0
        public static System.Collections.Generic.IAsyncEnumerable <T> CreateSingleProducerTaskAsyncEnumerable <T>(
            Func <Task <IEnumerable <T> > > producerTaskFunc)
            where T : ResultBase
        {
            Task <IEnumerator <T> > producerTask = Task.Run(async() =>
            {
                var enumerable = await producerTaskFunc();
                return(enumerable.GetEnumerator());
            });
            IEnumerator <T> enumerator = Enumerable.Empty <T>().GetEnumerator();

            return(AsyncEnumerable.Create(
                       (token) => AsyncEnumerator.Create(
                           async() =>
            {
                enumerator = await producerTask;
                return enumerator.MoveNext();
            },
                           () => enumerator.Current,
                           () =>
            {
                enumerator.Dispose();
                return new ValueTask();
            })));
        }
예제 #6
0
 public static IAsyncEnumerable <T> ToAsyncEnumerable <T>(this IEnumerator <T> enumerator)
 =>
 AsyncEnumerable.Create((cancellationToken)
                        => AsyncEnumerator.Create(
                            () => new ValueTask <bool>(enumerator.MoveNext()),
                            () => enumerator.Current,
                            () => new ValueTask())
                        );
예제 #7
0
 public static IAsyncEnumerator <T> Append <T>(this IAsyncEnumerator <T> me, IAsyncEnumerator <T> other)
 {
     return(AsyncEnumerator.Create(
                async() =>
                await other.MoveNext() ? other.Current :
                await me.MoveNext() ? me.Current :
                default(T),
                () => {
         (other as IDisposable)?.Dispose();
         (me as IDisposable)?.Dispose();
     }));
 }
        public IAsyncEnumerator <T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
        {
            var enumerator = GetEnumerator();

            return(AsyncEnumerator.Create(
                       moveNextAsync: () => new ValueTask <bool>(enumerator.MoveNext()),
                       getCurrent: () => enumerator.Current,
                       disposeAsync: () =>
            {
                enumerator.Dispose();
                return new ValueTask();
            }
                       ));
        }
예제 #9
0
        public static IAsyncEnumerable <T> ToTaskResultEnumerable <T>(this IEnumerable <Task <T> > rootEnum)
        {
            return(AsyncEnumerable.Create(_ =>
            {
                IEnumerator <Task <T> > rootEnumerator = rootEnum.GetEnumerator();
                T val = default(T);
                return AsyncEnumerator.Create(async() =>
                {
                    if (!rootEnumerator.MoveNext())
                    {
                        return false;
                    }

                    val = await rootEnumerator.Current.ConfigureAwait(false);
                    return true;
                }, () => val, () => { rootEnumerator.Dispose(); return default; });
            }));
        }
예제 #10
0
        public static IAsyncEnumerable <T> FromArray <T>(IList <T> items)
        {
            var index = -1;

            return(AsyncEnumerable.Create <T>(
                       cancellationToken => AsyncEnumerator.Create(
                           () =>
            {
                if (index + 1 >= items.Count)
                {
                    return new ValueTask <bool>(false);
                }
                index++;
                return new ValueTask <bool>(true);
            },
                           () => items[index],
                           () => new ValueTask())));
        }
예제 #11
0
        /// <inheritdoc />
        public System.Collections.Generic.IAsyncEnumerable <StructResult <StrongFingerprint> > EnumerateStrongFingerprints(Context context)
        {
            context.Debug($"{nameof(SQLiteMemoizationStore)}.{nameof(EnumerateStrongFingerprints)}({context.Id})");
            return(AsyncEnumerable.Create(
                       token =>
            {
                const long pageLimit = 100;
                long offset = 0;
                IEnumerator <StrongFingerprint> strongFingerprints = null;
                StructResult <StrongFingerprint> error = null;
                return AsyncEnumerator.Create(
                    async() =>
                {
                    try
                    {
                        if (error != null)
                        {
                            return false;
                        }

                        if (strongFingerprints == null || !strongFingerprints.MoveNext())
                        {
                            // ReSharper disable once GenericEnumeratorNotDisposed
                            strongFingerprints = (await EnumerateStrongFingerprintsAsync(pageLimit, offset)).GetEnumerator();
                            if (!strongFingerprints.MoveNext())
                            {
                                return false;
                            }
                        }

                        offset++;
                        return true;
                    }
                    catch (Exception e)
                    {
                        error = new StructResult <StrongFingerprint>(e);
                        return true;
                    }
                },
                    () => error ?? new StructResult <StrongFingerprint>(strongFingerprints.Current),
                    () => { strongFingerprints?.Dispose(); return new ValueTask(); });
            }));
        }
        public static async Task <IAsyncEnumerable <T> > FlattenAsync <T>(this Task <IEnumerable <T> > task)
        {
            IEnumerable <T> enumerable = await task;

            return(AsyncEnumerable.Create(
                       token =>
            {
                IEnumerator <T> enumerator = enumerable.GetEnumerator();

                return AsyncEnumerator
                .Create(
                    async() => await Task.FromResult(enumerator.MoveNext()),
                    () => enumerator.Current,
                    async() =>
                {
                    enumerator.Dispose();
                    await Task.CompletedTask;
                })
                .WithCancellation(token);
            }));
        }
예제 #13
0
        /// <summary>
        /// Skip past the first occurance of separator.
        /// </summary>
        /// <param name="me">Enumerator to skip on.</param>
        /// <param name="separator">Separator to skip past. Shall not contain null.</param>
        /// <typeparam name="T">Any type implementing <c>IEquatable</c>.</typeparam>
        public static IAsyncEnumerator <T> Skip <T>(this IAsyncEnumerator <T> me, params T[] separator)
            where T : IEquatable <T>
        {
            int position = 0;
            async Tasks.Task <T> next()
            {
                while (await me.MoveNext())
                {
                    if (!me.Current.Equals(separator[position++]))
                    {
                        position = 0;
                    }
                    else if (separator.Length == position)
                    {
                        break;
                    }
                }
                return(me.Current);
            }

            return(AsyncEnumerator.Create(next, me as IDisposable));
        }
예제 #14
0
        /// <summary>
        /// Return new enumerator containing the next <paramref name="count"/> elements in <paramref name="me"/>.
        /// </summary>
        /// <param name="me">Enumerator to read from.</param>
        /// <param name="count">Number of elements read.</param>
        /// <typeparam name="T">Any type.</typeparam>
        public static IAsyncEnumerator <T> Read <T>(this IAsyncEnumerator <T> me, int count)
        {
            async Tasks.Task <T> next() => await me.MoveNext() && unchecked (count-- > 0) ?  me.Current : default(T);

            return(AsyncEnumerator.Create(next, me as IDisposable));
        }
        /// <inheritdoc cref="IArrangement" />
        public bool TryApplyTo(IInvocation invocation)
        {
            Ensures.NotNull(invocation, nameof(invocation));

            if (invocation.Signature == Signature)
            {
                if (invocation.HasFeature <IAsyncInvocation>())
                {
                    if (invocation.TryGetFeature <IAsyncInvocation <T> >(out var asyncFeature))
                    {
                        asyncFeature.AsyncReturnValue = GetNextReturnValue();
                        return(true);
                    }
                    else if (invocation.TryGetFeature <IAsyncInvocation <Task <T> > >(out var asyncTaskFeature))
                    {
                        var returnValue = GetNextReturnValue();
                        asyncTaskFeature.AsyncReturnValue = Task.FromResult(returnValue);
                        return(true);
                    }
                    else if (invocation.TryGetFeature <IAsyncInvocation <ValueTask <T> > >(out var asyncValueTaskFeature))
                    {
                        var returnValue = GetNextReturnValue();
                        asyncValueTaskFeature.AsyncReturnValue = new ValueTask <T>(returnValue);
                        return(true);
                    }
                    else if (invocation.TryGetFeature <IAsyncInvocation <IAsyncEnumerable <T> > >(out var asyncEnumerableFeature))
                    {
                        var returnValue = GetNextReturnValue();
                        asyncEnumerableFeature.AsyncReturnValue = AsyncEnumerable.Create(_ =>
                                                                                         AsyncEnumerator.Create(
                                                                                             () => new ValueTask <bool>(true),
                                                                                             () => returnValue,
                                                                                             () => default));
                        return(true);
                    }
                }
                else if (invocation.TryGetFeature <IReturnValue <T> >(out var returnValueFeature))
                {
                    returnValueFeature.ReturnValue = GetNextReturnValue();
                    return(true);
                }
            }

            return(false);
        }
예제 #16
0
        public static IAsyncEnumerator <T> Filter <T>(this IAsyncEnumerator <T> me, Func <T, bool> predicate)
        {
            async Tasks.Task <T> next() => !await me.MoveNext() ? default(T) :       predicate(me.Current) ? me.Current : await next();

            return(AsyncEnumerator.Create(next, me as IDisposable));
        }
예제 #17
0
 public static IAsyncEnumerator <S> Map <T, S>(this IAsyncEnumerator <T> me, Func <T, S> function)
 {
     return(AsyncEnumerator.Create(async() => await me.MoveNext() ? function(me.Current) : default(S), me as IDisposable));
 }
예제 #18
0
 public static IAsyncEnumerator <T> Append <T>(this Generic.IEnumerator <T> me, IAsyncEnumerator <T> other)
 {
     return(AsyncEnumerator.Create(me).Append(other));
 }
예제 #19
0
 public static IAsyncEnumerator <T> Prepend <T>(this IAsyncEnumerator <T> me, Generic.IEnumerator <T> other)
 {
     return(me.Prepend(AsyncEnumerator.Create(other)));
 }
예제 #20
0
        /// <summary>
        /// Skip the next <paramref name="count"/> elements in <paramref name="me"/>.
        /// </summary>
        /// <param name="me">Enumerator to skip in.</param>
        /// <param name="count">Number of elements to skip.</param>
        /// <typeparam name="T">Any type.</typeparam>
        public static IAsyncEnumerator <T> Skip <T>(this IAsyncEnumerator <T> me, int count)
        {
            async Tasks.Task <T> next() => !await me.MoveNext() ?  default(T) :      unchecked (count-- > 0) ? await next() : me.Current;

            return(AsyncEnumerator.Create(next, me as IDisposable));
        }
예제 #21
0
 public static IAsyncEnumerator <T> While <T>(this IAsyncEnumerator <T> me, Func <T, bool> predicate) =>
 AsyncEnumerator.Create(async() => await me.MoveNext() && predicate(me.Current) ? me.Current : default(T), me as IDisposable);
예제 #22
0
        /// <summary>
        /// Retrieve a <see cref="IAsyncEnumerator{T}"/> using a SOQL query. Batches will be retrieved asynchronously.
        /// <para>When using the iterator, the initial result batch will be returned as soon as it is received. The additional result batches will be retrieved only as needed.</para>
        /// </summary>
        /// <param name="queryString">SOQL query string, without any URL escaping/encoding</param>
        /// <param name="queryAll">Optional. True if deleted records are to be included.await Defaults to false.</param>
        /// <param name="batchSize">Optional. Size of result batches between 200 and 2000</param>
        /// <returns><see cref="IAsyncEnumerator{T}"/> of results</returns>
        public IAsyncEnumerator <T> QueryAsyncEnumerator <T>(string queryString, bool queryAll = false, int?batchSize = null)
        {
            Dictionary <string, string> headers = new Dictionary <string, string>();

            //Add call options
            Dictionary <string, string> callOptions = HeaderFormatter.SforceCallOptions(ClientName);

            headers.AddRange(callOptions);

            //Add query options headers if batch size specified
            if (batchSize.HasValue)
            {
                Dictionary <string, string> queryOptions = HeaderFormatter.SforceQueryOptions(batchSize.Value);
                headers.AddRange(queryOptions);
            }

            var jsonClient = new JsonClient(AccessToken, _httpClient);

            // Enumerator on the current batch items
            IEnumerator <T> currentBatchEnumerator = null;
            var             done           = false;
            var             nextRecordsUri = UriFormatter.Query(InstanceUrl, ApiVersion, queryString, queryAll);

#if NETSTANDARD2_1
            return(AsyncEnumerator.Create(MoveNextAsync, Current, Dispose));

            async ValueTask <bool> MoveNextAsync()
            {
#else
            return(AsyncEnumerable.CreateEnumerator(MoveNextAsync, Current, Dispose));

            async Task <bool> MoveNextAsync(CancellationToken token)
            {
                if (token.IsCancellationRequested)
                {
                    return(false);
                }
#endif
                // If items remain in the current Batch enumerator, go to next item
                if (currentBatchEnumerator?.MoveNext() == true)
                {
                    return(true);
                }

                // if done, no more items.
                if (done)
                {
                    return(false);
                }

                // else : no enumerator or currentBatchEnumerator ended
                // so get the next batch
                var qr = await jsonClient.HttpGetAsync <QueryResult <T> >(nextRecordsUri, headers);

#if DEBUG
                Debug.WriteLine($"Got query resuts, {qr.TotalSize} totalSize, {qr.Records.Count} in this batch, final batch: {qr.Done}");
#endif

                currentBatchEnumerator = qr.Records.GetEnumerator();

                if (!string.IsNullOrEmpty(qr.NextRecordsUrl))
                {
                    nextRecordsUri = new Uri(new Uri(InstanceUrl), qr.NextRecordsUrl);
                    done           = false;
                }
                else
                {
                    //Normally if query has remaining batches, NextRecordsUrl will have a value, and Done will be false.
                    //In case of some unforseen error, flag the result as done if we're missing the NextRecordsURL
                    done = true;
                }

                return(currentBatchEnumerator.MoveNext());
            }

            T Current()
            {
                return(currentBatchEnumerator == null ? default(T) : currentBatchEnumerator.Current);
            }

#if NETSTANDARD2_1
            ValueTask Dispose()
            {
                currentBatchEnumerator?.Dispose();
                jsonClient.Dispose();
                return(new ValueTask());
            }
#else
            void Dispose()
            {
                currentBatchEnumerator?.Dispose();
                jsonClient.Dispose();
            }
#endif
        }