Beispiel #1
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);
            }));
        }
Beispiel #2
0
        public static IAsyncObservable <TSource> Sample <TSource>(this IAsyncObservable <TSource> source, TimeSpan interval, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

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

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

                return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler);
            }));
        }
Beispiel #3
0
        public static IAsyncObservable <TSource> Catch <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.Catch(observer, second);

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

                return StableCompositeAsyncDisposable.Create(subscription, inner);
            }));
        }
Beispiel #4
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);
            }));
        }
Beispiel #5
0
        public static IAsyncObservable <IList <TSource> > Buffer <TSource>(this IAsyncObservable <TSource> source, TimeSpan timeSpan)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (timeSpan < TimeSpan.Zero)
            {
                throw new ArgumentNullException(nameof(timeSpan));
            }

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

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

                return StableCompositeAsyncDisposable.Create(subscription, timer);
            }));
        }
Beispiel #6
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);
            }));
        }
Beispiel #7
0
        public static IAsyncObservable <TResult> SelectMany <TSource, TResult>(this IAsyncObservable <TSource> source, Func <TSource, Task <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);
            }));
        }
Beispiel #8
0
        public static IAsyncObservable <TSource> SkipUntil <TSource>(this IAsyncObservable <TSource> source, DateTimeOffset endTime)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

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

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

                return StableCompositeAsyncDisposable.Create(subscription, timer);
            }));
        }
Beispiel #9
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);
            }));
        }
Beispiel #10
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);
            }));
        }
Beispiel #11
0
        public static Task <IAsyncDisposable> Repeat <TSource>(IAsyncObserver <TSource> observer, IAsyncObservable <TSource> source)
        {
            if (observer == null)
            {
                throw new ArgumentNullException(nameof(observer));
            }
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

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

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

            return(CoreAsync());
        }
Beispiel #12
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);
            }));
        }
Beispiel #13
0
        public static IAsyncObservable <TSource> TakeLast <TSource>(this IAsyncObservable <TSource> source, TimeSpan duration, IClock clock, IAsyncScheduler scheduler)
        {
            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 (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

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

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       (duration, clock, scheduler),
                       static async (source, state, observer) =>
            {
                var(sink, drain) = AsyncObserver.TakeLast(observer, state.duration, state.clock, state.scheduler);

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

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Beispiel #14
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));
            }
        }
Beispiel #15
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);
            }));
        }