Ejemplo n.º 1
0
        private static IAsyncEnumerable <TSource> OnErrorResumeNext_ <TSource>(IEnumerable <IAsyncEnumerable <TSource> > sources)
        {
            return(Create(() =>
            {
                var se = sources.GetEnumerator();
                var e = default(IAsyncEnumerator <TSource>);

                var cts = new CancellationTokenDisposable();
                var a = new AssignableDisposable();
                var d = Disposable.Create(cts, se, a);

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) =>
                {
                    if (e == null)
                    {
                        var b = false;
                        try
                        {
                            b = se.MoveNext();
                            if (b)
                            {
                                e = se.Current.GetEnumerator();
                            }
                        }
                        catch (Exception ex)
                        {
                            tcs.TrySetException(ex);
                            return;
                        }

                        if (!b)
                        {
                            tcs.TrySetResult(false);
                            return;
                        }

                        a.Disposable = e;
                    }

                    e.MoveNext(ct).Then(t =>
                    {
                        t.Handle(tcs,
                                 res =>
                        {
                            if (res)
                            {
                                tcs.TrySetResult(true);
                            }
                            else
                            {
                                e.Dispose();
                                e = null;

                                f(tcs, ct);
                            }
                        },
                                 ex =>
                        {
                            e.Dispose();
                            e = null;

                            f(tcs, ct);
                        }
                                 );
                    });
                };

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(a);
                },
                    () => e.Current,
                    d.Dispose
                    );
            }));
        }
Ejemplo n.º 2
0
        public static IAsyncEnumerable <TSource> Catch <TSource, TException>(this IAsyncEnumerable <TSource> source, Func <TException, IAsyncEnumerable <TSource> > handler)
            where TException : Exception
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            return(Create(() =>
            {
                var e = source.GetEnumerator();

                var cts = new CancellationTokenDisposable();
                var a = new AssignableDisposable {
                    Disposable = e
                };
                var d = Disposable.Create(cts, a);
                var done = false;

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) =>
                {
                    if (!done)
                    {
                        e.MoveNext(ct).Then(t =>
                        {
                            t.Handle(tcs,
                                     res =>
                            {
                                tcs.TrySetResult(res);
                            },
                                     ex =>
                            {
                                var err = default(IAsyncEnumerator <TSource>);

                                try
                                {
                                    ex.Flatten().Handle(ex_ =>
                                    {
                                        var exx = ex_ as TException;
                                        if (exx != null)
                                        {
                                            err = handler(exx).GetEnumerator();
                                            return true;
                                        }

                                        return false;
                                    });
                                }
                                catch (Exception ex2)
                                {
                                    tcs.TrySetException(ex2);
                                    return;
                                }

                                if (err != null)
                                {
                                    e = err;
                                    a.Disposable = e;

                                    done = true;
                                    f(tcs, ct);
                                }
                            }
                                     );
                        });
                    }
                    else
                    {
                        e.MoveNext(ct).Then(t =>
                        {
                            t.Handle(tcs, res =>
                            {
                                tcs.TrySetResult(res);
                            });
                        });
                    }
                };

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(a);
                },
                    () => e.Current,
                    d.Dispose
                    );
            }));
        }
Ejemplo n.º 3
0
        public static IAsyncEnumerable <TResult> SelectMany <TSource, TResult>(this IAsyncEnumerable <TSource> source, Func <TSource, int, IAsyncEnumerable <TResult> > selector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            return(CreateEnumerable(
                       () =>
            {
                var e = source.GetEnumerator();
                var ie = default(IAsyncEnumerator <TResult>);

                var index = 0;

                var innerDisposable = new AssignableDisposable();

                var cts = new CancellationTokenDisposable();
                var d = Disposable.Create(cts, innerDisposable, e);

                var inner = default(Func <CancellationToken, Task <bool> >);
                var outer = default(Func <CancellationToken, Task <bool> >);

                inner = async ct =>
                {
                    if (await ie.MoveNext(ct)
                        .ConfigureAwait(false))
                    {
                        return true;
                    }
                    innerDisposable.Disposable = null;
                    return await outer(ct)
                    .ConfigureAwait(false);
                };

                outer = async ct =>
                {
                    if (await e.MoveNext(ct)
                        .ConfigureAwait(false))
                    {
                        var enumerable = selector(e.Current, checked (index++));
                        ie = enumerable.GetEnumerator();
                        innerDisposable.Disposable = ie;

                        return await inner(ct)
                        .ConfigureAwait(false);
                    }
                    return false;
                };

                return CreateEnumerator(ct => ie == null ? outer(cts.Token) : inner(cts.Token),
                                        () => ie.Current,
                                        d.Dispose,
                                        e
                                        );
            }));
        }
Ejemplo n.º 4
0
        public static IAsyncEnumerable <TSource> Expand <TSource>(this IAsyncEnumerable <TSource> source, Func <TSource, IAsyncEnumerable <TSource> > selector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            return(CreateEnumerable(
                       () =>
            {
                var e = default(IAsyncEnumerator <TSource>);

                var cts = new CancellationTokenDisposable();
                var a = new AssignableDisposable();
                var d = Disposable.Create(cts, a);

                var queue = new Queue <IAsyncEnumerable <TSource> >();
                queue.Enqueue(source);

                var current = default(TSource);

                var f = default(Func <CancellationToken, Task <bool> >);
                f = async ct =>
                {
                    if (e == null)
                    {
                        if (queue.Count > 0)
                        {
                            var src = queue.Dequeue();

                            e = src.GetEnumerator();

                            a.Disposable = e;
                            return await f(ct)
                            .ConfigureAwait(false);
                        }
                        return false;
                    }
                    if (await e.MoveNext(ct)
                        .ConfigureAwait(false))
                    {
                        var item = e.Current;
                        var next = selector(item);

                        queue.Enqueue(next);
                        current = item;
                        return true;
                    }
                    e = null;
                    return await f(ct)
                    .ConfigureAwait(false);
                };

                return CreateEnumerator(
                    f,
                    () => current,
                    d.Dispose,
                    e
                    );
            }));
        }
Ejemplo n.º 5
0
        public static IAsyncEnumerable <TSource> Concat <TSource>(this IAsyncEnumerable <TSource> first, IAsyncEnumerable <TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException("first");
            }
            if (second == null)
            {
                throw new ArgumentNullException("second");
            }

            return(Create(() =>
            {
                var switched = false;
                var e = first.GetEnumerator();

                var cts = new CancellationTokenDisposable();
                var a = new AssignableDisposable {
                    Disposable = e
                };
                var d = Disposable.Create(cts, a);

                var f = default(Action <TaskCompletionSource <bool>, CancellationToken>);
                f = (tcs, ct) => e.MoveNext(ct).Then(t =>
                {
                    t.Handle(tcs, res =>
                    {
                        if (res)
                        {
                            tcs.TrySetResult(true);
                        }
                        else
                        {
                            if (switched)
                            {
                                tcs.TrySetResult(false);
                            }
                            else
                            {
                                switched = true;

                                e = second.GetEnumerator();
                                a.Disposable = e;

                                f(tcs, ct);
                            }
                        }
                    });
                });

                return Create(
                    (ct, tcs) =>
                {
                    f(tcs, cts.Token);
                    return tcs.Task.UsingEnumerator(a);
                },
                    () => e.Current,
                    d.Dispose
                    );
            }));
        }