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); }
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()); })); }
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(); }))); }
public static IAsyncEnumerable <T> ToAsyncEnumerable <T>(this IEnumerator <T> enumerator) => AsyncEnumerable.Create((cancellationToken) => AsyncEnumerator.Create( () => new ValueTask <bool>(enumerator.MoveNext()), () => enumerator.Current, () => new ValueTask()) );
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(); } )); }
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; }); })); }
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()))); }
/// <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); })); }
/// <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)); }
/// <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); }
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)); }
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)); }
public static IAsyncEnumerator <T> Append <T>(this Generic.IEnumerator <T> me, IAsyncEnumerator <T> other) { return(AsyncEnumerator.Create(me).Append(other)); }
public static IAsyncEnumerator <T> Prepend <T>(this IAsyncEnumerator <T> me, Generic.IEnumerator <T> other) { return(me.Prepend(AsyncEnumerator.Create(other))); }
/// <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)); }
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);
/// <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 }