Example #1
0
        public static IAsyncObservable <TSource> TakeLast <TSource>(this IAsyncObservable <TSource> source, TimeSpan duration, IClock clock)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (duration < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(duration));
            }
            if (clock == null)
            {
                throw new ArgumentNullException(nameof(clock));
            }

            if (duration == TimeSpan.Zero)
            {
                return(Empty <TSource>());
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, drain) = AsyncObserver.TakeLast(observer, duration, clock);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Example #2
0
        public static Task <IAsyncDisposable> Repeat <TSource>(IAsyncObserver <TSource> observer, IAsyncObservable <TSource> source, int repeatCount)
        {
            if (observer == null)
            {
                throw new ArgumentNullException(nameof(observer));
            }
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (repeatCount < 0)
            {
                throw new ArgumentNullException(nameof(repeatCount));
            }

            async Task <IAsyncDisposable> CoreAsync()
            {
                var(sink, inner) = Concat(observer, Enumerable.Repeat(source, repeatCount).GetEnumerator());

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return(StableCompositeAsyncDisposable.Create(subscription, inner));
            }

            return(CoreAsync());
        }
Example #3
0
        public static IAsyncObservable <TSource> Amb <TSource>(params IAsyncObservable <TSource>[] sources)
        {
            if (sources == null)
            {
                throw new ArgumentNullException(nameof(sources));
            }

            return(Create <TSource>(async observer =>
            {
                var count = sources.Length;

                var subscriptions = new SingleAssignmentAsyncDisposable[count];

                for (var i = 0; i < count; i++)
                {
                    subscriptions[i] = new SingleAssignmentAsyncDisposable();
                }

                var observers = AsyncObserver.Amb(observer, subscriptions);

                var tasks = new Task[count];

                for (var i = 0; i < count; i++)
                {
                    tasks[i] = sources[i].SubscribeSafeAsync(observers[i]).AsTask().ContinueWith(d => subscriptions[i].AssignAsync(d.Result).AsTask()).Unwrap();
                }

                await Task.WhenAll(tasks).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscriptions);
            }));
        }
Example #4
0
        public static IAsyncObservable <TSource> Amb <TSource>(this IAsyncObservable <TSource> first, IAsyncObservable <TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }
            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }

            return(Create <TSource>(async observer =>
            {
                var firstSubscription = new SingleAssignmentAsyncDisposable();
                var secondSubscription = new SingleAssignmentAsyncDisposable();

                var(firstObserver, secondObserver) = AsyncObserver.Amb(observer, firstSubscription, secondSubscription);

                var firstTask = first.SubscribeSafeAsync(firstObserver).AsTask().ContinueWith(d => firstSubscription.AssignAsync(d.Result).AsTask()).Unwrap();
                var secondTask = second.SubscribeSafeAsync(secondObserver).AsTask().ContinueWith(d => secondSubscription.AssignAsync(d.Result).AsTask()).Unwrap();

                await Task.WhenAll(firstTask, secondTask).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(firstSubscription, secondSubscription);
            }));
        }
Example #5
0
        public static IAsyncObservable <TSource> TakeLast <TSource>(this IAsyncObservable <TSource> source, int count, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            if (count == 0)
            {
                return(Empty <TSource>());
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, drain) = AsyncObserver.TakeLast(observer, count, scheduler);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Example #6
0
        public static IAsyncObservable <IList <TSource> > Zip <TSource>(params IAsyncObservable <TSource>[] sources)
        {
            if (sources == null)
            {
                throw new ArgumentNullException(nameof(sources));
            }

            return(Create <IList <TSource> >(async observer =>
            {
                var count = sources.Length;

                var observers = AsyncObserver.Zip(observer, count);

                var tasks = new Task <IAsyncDisposable> [count];

                for (var i = 0; i < count; i++)
                {
                    tasks[i] = sources[i].SubscribeSafeAsync(observers[i]).AsTask();
                }

                await Task.WhenAll(tasks).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(tasks.Select(t => t.Result));
            }));
        }
Example #7
0
        public static IAsyncObservable <TSource> SkipUntil <TSource>(this IAsyncObservable <TSource> source, DateTimeOffset endTime, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            // REVIEW: May be easier to just use SkipUntil with a Timer parameter. Do we want SkipUntil on the observer?

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       (scheduler, endTime),
                       static async (source, state, observer) =>
            {
                var(sourceObserver, timer) = await AsyncObserver.SkipUntil(observer, state.endTime).ConfigureAwait(false);

                var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, timer);
            }));
        }
Example #8
0
        public static IAsyncObservable <bool> SequenceEqual <TSource>(this IAsyncObservable <TSource> first, IAsyncObservable <TSource> second, IEqualityComparer <TSource> comparer)
        {
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }
            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }
            if (comparer == null)
            {
                throw new ArgumentNullException(nameof(comparer));
            }

            return(CreateAsyncObservable <bool> .From(
                       first,
                       (second, comparer),
                       static async (first, state, observer) =>
            {
                var(firstObserver, secondObserver) = AsyncObserver.SequenceEqual(observer, state.comparer);

                var firstTask = first.SubscribeSafeAsync(firstObserver);
                var secondTask = state.second.SubscribeSafeAsync(secondObserver);

                // REVIEW: Consider concurrent subscriptions.

                var d1 = await firstTask.ConfigureAwait(false);
                var d2 = await secondTask.ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(d1, d2);
            }));
        }
Example #9
0
        public static IAsyncObservable <TResult> SelectMany <TSource, TCollection, TResult>(this IAsyncObservable <TSource> source, Func <TSource, ValueTask <IAsyncObservable <TCollection> > > collectionSelector, Func <TSource, TCollection, ValueTask <TResult> > resultSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (collectionSelector == null)
            {
                throw new ArgumentNullException(nameof(collectionSelector));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(CreateAsyncObservable <TResult> .From(
                       source,
                       (collectionSelector, resultSelector),
                       static async (source, state, observer) =>
            {
                var(sink, inner) = AsyncObserver.SelectMany(observer, state.collectionSelector, state.resultSelector);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Example #10
0
        public static IAsyncObservable <TSource> Skip <TSource>(this IAsyncObservable <TSource> source, TimeSpan duration, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (duration < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(duration));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            if (duration == TimeSpan.Zero)
            {
                return(source);
            }

            // REVIEW: May be easier to just use SkipUntil with a Timer parameter. Do we want Skip on the observer?

            return(Create <TSource>(async observer =>
            {
                var(sourceObserver, timer) = await AsyncObserver.Skip(observer, duration).ConfigureAwait(false);

                var subscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, timer);
            }));
        }
Example #11
0
        public static IAsyncObservable <TSource> StartAsync <TSource>(Func <CancellationToken, Task <TSource> > functionAsync, IAsyncScheduler scheduler)
        {
            if (functionAsync == null)
            {
                throw new ArgumentNullException(nameof(functionAsync));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            var cancel = new CancellationAsyncDisposable();

            var task = default(Task <TSource>);

            try
            {
                task = functionAsync(cancel.Token);
            }
            catch (Exception ex)
            {
                return(Throw <TSource>(ex));
            }

            return(Create <TSource>(async observer =>
            {
                var subscription = await task.ToAsyncObservable(scheduler).SubscribeAsync(observer).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(cancel, subscription);
            }));
        }
Example #12
0
        public static IAsyncObservable <TSource> Catch <TSource>(this IEnumerable <IAsyncObservable <TSource> > sources)
        {
            if (sources == null)
            {
                throw new ArgumentNullException(nameof(sources));
            }

            return(Create <TSource>(async observer =>
            {
                var enumerator = sources.GetEnumerator();

                if (!enumerator.MoveNext())
                {
                    return AsyncDisposable.Nop; // REVIEW: Is Never behavior right here?
                }

                var source = enumerator.Current;

                var(sink, inner) = AsyncObserver.Catch(observer, enumerator);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Example #13
0
        public static IAsyncObservable <IList <TSource> > Buffer <TSource>(this IAsyncObservable <TSource> source, TimeSpan timeSpan, int count, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (timeSpan < TimeSpan.Zero)
            {
                throw new ArgumentNullException(nameof(timeSpan));
            }
            if (count <= 0)
            {
                throw new ArgumentNullException(nameof(count));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            return(Create <IList <TSource> >(async observer =>
            {
                var(sink, timer) = await AsyncObserver.Buffer(observer, timeSpan, count, scheduler).ConfigureAwait(false);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, timer);
            }));
        }
Example #14
0
        public static IAsyncObservable <TSource> SkipUntil <TSource, TUntil>(this IAsyncObservable <TSource> source, IAsyncObservable <TUntil> until)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (until == null)
            {
                throw new ArgumentNullException(nameof(until));
            }

            return(Create <TSource>(async observer =>
            {
                var(sourceObserver, untilObserver) = AsyncObserver.SkipUntil <TSource, TUntil>(observer);

                var sourceTask = source.SubscribeSafeAsync(sourceObserver);
                var untilTask = until.SubscribeSafeAsync(untilObserver);

                // REVIEW: Consider concurrent subscriptions.

                var d1 = await sourceTask.ConfigureAwait(false);
                var d2 = await untilTask.ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(d1, d2);
            }));
        }
        protected override async Task <IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver <TSource> observer)
        {
            if (_disposable != null)
            {
                var d = await _disposable.GetDisposableAsync().ConfigureAwait(false);

                var s = await _subject.SubscribeAsync(observer).ConfigureAwait(false);

                return(StableCompositeAsyncDisposable.Create(d, s));
            }

            return(await _subject.SubscribeAsync(observer).ConfigureAwait(false));
        }
Example #16
0
        public static ValueTask <IAsyncDisposable> Prepend <TSource>(IAsyncObserver <TSource> observer, IAsyncObservable <TSource> source, IAsyncScheduler scheduler, params TSource[] values)
        {
            if (observer == null)
            {
                throw new ArgumentNullException(nameof(observer));
            }
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }
            if (values == null)
            {
                throw new ArgumentNullException(nameof(values));
            }

            return(CoreAsync());

            async ValueTask <IAsyncDisposable> CoreAsync()
            {
                var subscription = new SingleAssignmentAsyncDisposable();

                var task = await scheduler.ScheduleAsync(async ct =>
                {
                    if (ct.IsCancellationRequested)
                    {
                        return;
                    }

                    for (var i = 0; i < values.Length && !ct.IsCancellationRequested; i++)
                    {
                        await observer.OnNextAsync(values[i]).RendezVous(scheduler, ct);
                    }

                    if (ct.IsCancellationRequested)
                    {
                        return;
                    }

                    var inner = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
                    await subscription.AssignAsync(inner).RendezVous(scheduler, ct);
                }).ConfigureAwait(false);

                return(StableCompositeAsyncDisposable.Create(task, subscription));
            }
        }
Example #17
0
        public static IAsyncObservable <TSource> Delay <TSource>(this IAsyncObservable <TSource> source, TimeSpan dueTime)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, drain) = await AsyncObserver.Delay(observer, dueTime).ConfigureAwait(false);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Example #18
0
        public static IAsyncObservable <TSource> Sample <TSource>(this IAsyncObservable <TSource> source, TimeSpan interval)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            return(Create <TSource>(async observer =>
            {
                var(sourceSink, sampler) = await AsyncObserver.Sample(observer, interval).ConfigureAwait(false);

                var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler);
            }));
        }
Example #19
0
        public static IAsyncObservable <TSource> Switch <TSource>(this IAsyncObservable <IAsyncObservable <TSource> > source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, cancel) = AsyncObserver.Switch(observer);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, cancel);
            }));
        }
Example #20
0
        public static IAsyncObservable <TResult> SelectMany <TSource, TResult>(this IAsyncObservable <TSource> source, Func <TSource, int, ValueTask <IAsyncObservable <TResult> > > selector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            return(Create <TResult>(async observer =>
            {
                var(sink, inner) = AsyncObserver.SelectMany(observer, selector);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Example #21
0
        // REVIEW: This overload is inherited from Rx but arguably a bit esoteric as it doesn't provide context to the closing selector.

        public static IAsyncObservable <IList <TSource> > Buffer <TSource, TBufferClosing>(this IAsyncObservable <TSource> source, Func <IAsyncObservable <TBufferClosing> > bufferClosingSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (bufferClosingSelector == null)
            {
                throw new ArgumentNullException(nameof(bufferClosingSelector));
            }

            return(Create <IList <TSource> >(async observer =>
            {
                var(sourceObserver, closingDisposable) = await AsyncObserver.Buffer <TSource, TBufferClosing>(observer, bufferClosingSelector).ConfigureAwait(false);

                var sourceSubscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(sourceSubscription, closingDisposable);
            }));
        }
        public static IAsyncObservable <TSource> OnErrorResumeNext <TSource>(this IAsyncObservable <TSource> first, IAsyncObservable <TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }
            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, inner) = AsyncObserver.OnErrorResumeNext(observer, second);

                var subscription = await first.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Example #23
0
        public static IAsyncObservable <TSource> Retry <TSource>(this IAsyncObservable <TSource> source, int retryCount)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (retryCount < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(retryCount));
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, inner) = AsyncObserver.Retry(observer, source, retryCount);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Example #24
0
        public static IAsyncObservable <TSource> ObserveOn <TSource>(this IAsyncObservable <TSource> source, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, drain) = await AsyncObserver.ObserveOn(observer, scheduler).ConfigureAwait(false);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Example #25
0
        public static IAsyncObservable <IList <TSource> > Buffer <TSource, TBufferBoundary>(this IAsyncObservable <TSource> source, IAsyncObservable <TBufferBoundary> bufferBoundaries)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (bufferBoundaries == null)
            {
                throw new ArgumentNullException(nameof(bufferBoundaries));
            }

            return(Create <IList <TSource> >(async observer =>
            {
                var(sourceObserver, boundariesObserver) = AsyncObserver.Buffer <TSource, TBufferBoundary>(observer);

                var sourceSubscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
                var boundariesSubscription = await bufferBoundaries.SubscribeSafeAsync(boundariesObserver).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(sourceSubscription, boundariesSubscription);
            }));
        }
Example #26
0
        public static IAsyncObservable <TSource> Catch <TSource, TException>(this IAsyncObservable <TSource> source, Func <TException, ValueTask <IAsyncObservable <TSource> > > handler)
            where TException : Exception
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            return(Create <TSource>(async observer =>
            {
                var(sink, inner) = AsyncObserver.Catch(observer, handler);

                var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Example #27
0
        public static IAsyncObservable <TSource> Sample <TSource, TSample>(this IAsyncObservable <TSource> source, IAsyncObservable <TSample> sampler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (sampler == null)
            {
                throw new ArgumentNullException(nameof(sampler));
            }

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       sampler,
                       static async (source, sampler, observer) =>
            {
                var(sourceSink, samplerSink) = AsyncObserver.Sample <TSource, TSample>(observer);

                var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false);
                var samplerSubscription = await sampler.SubscribeSafeAsync(samplerSink).ConfigureAwait(false);

                return StableCompositeAsyncDisposable.Create(sourceSubscription, samplerSubscription);
            }));
        }
Example #28
0
        public static IAsyncObservable <TResult> For <TSource, TResult>(IEnumerable <TSource> source, Func <TSource, Task <IAsyncObservable <TResult> > > resultSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(Create <TResult>(async observer =>
            {
                var subscription = new SerialAsyncDisposable();

                var enumerator = source.GetEnumerator();

                var o = default(IAsyncObserver <TResult>);

                o = AsyncObserver.CreateUnsafe <TResult>(
                    observer.OnNextAsync,
                    observer.OnErrorAsync,
                    MoveNext
                    );

                async Task MoveNext()
                {
                    var b = default(bool);
                    var next = default(IAsyncObservable <TResult>);

                    try
                    {
                        b = enumerator.MoveNext();

                        if (b)
                        {
                            next = await resultSelector(enumerator.Current).ConfigureAwait(false);
                        }
                    }
                    catch (Exception ex)
                    {
                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
                        return;
                    }

                    if (b)
                    {
                        var sad = new SingleAssignmentAsyncDisposable();
                        await subscription.AssignAsync(sad).ConfigureAwait(false);

                        var d = await next.SubscribeSafeAsync(o).ConfigureAwait(false);
                        await sad.AssignAsync(d).ConfigureAwait(false);
                    }
                    else
                    {
                        await observer.OnCompletedAsync().ConfigureAwait(false);
                    }
                }

                await MoveNext().ConfigureAwait(false);

                var disposeEnumerator = AsyncDisposable.Create(() =>
                {
                    enumerator.Dispose();
                    return Task.CompletedTask;
                });

                return StableCompositeAsyncDisposable.Create(disposeEnumerator, subscription);
            }));
        }
Example #29
0
        public static ValueTask <IAsyncDisposable> Prepend <TSource>(IAsyncObserver <TSource> observer, IAsyncObservable <TSource> source, IAsyncScheduler scheduler, IEnumerable <TSource> values)
        {
            if (observer == null)
            {
                throw new ArgumentNullException(nameof(observer));
            }
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }
            if (values == null)
            {
                throw new ArgumentNullException(nameof(values));
            }

            return(CoreAsync());

            async ValueTask <IAsyncDisposable> CoreAsync()
            {
                var subscription = new SingleAssignmentAsyncDisposable();

                var task = await scheduler.ScheduleAsync(async ct =>
                {
                    if (ct.IsCancellationRequested)
                    {
                        return;
                    }

                    var e = default(IEnumerator <TSource>);

                    try
                    {
                        e = values.GetEnumerator();
                    }
                    catch (Exception ex)
                    {
                        await observer.OnErrorAsync(ex).RendezVous(scheduler, ct);
                        return;
                    }

                    using (e)
                    {
                        while (!ct.IsCancellationRequested)
                        {
                            var b     = default(bool);
                            var value = default(TSource);

                            try
                            {
                                b = e.MoveNext();

                                if (b)
                                {
                                    value = e.Current;
                                }
                            }
                            catch (Exception ex)
                            {
                                await observer.OnErrorAsync(ex).RendezVous(scheduler, ct);
                                return;
                            }

                            if (b)
                            {
                                await observer.OnNextAsync(value).RendezVous(scheduler, ct);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }

                    if (ct.IsCancellationRequested)
                    {
                        return;
                    }

                    var inner = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);
                    await subscription.AssignAsync(inner).RendezVous(scheduler, ct);
                }).ConfigureAwait(false);

                return(StableCompositeAsyncDisposable.Create(task, subscription));
            }
        }