Пример #1
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);
            }));
        }
Пример #2
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);
            }));
        }
Пример #3
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(CreateAsyncObservable <TSource> .From(
                       source,
                       (count, scheduler),
                       static async (source, state, observer) =>
            {
                var(sink, drain) = AsyncObserver.TakeLast(observer, state.count, state.scheduler);

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

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Пример #4
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);
            }));
        }
Пример #5
0
        public static IAsyncObservable <TResult> If <TResult>(Func <ValueTask <bool> > condition, IAsyncObservable <TResult> thenSource, IAsyncObservable <TResult> elseSource)
        {
            if (condition == null)
            {
                throw new ArgumentNullException(nameof(condition));
            }
            if (thenSource == null)
            {
                throw new ArgumentNullException(nameof(thenSource));
            }
            if (elseSource == null)
            {
                throw new ArgumentNullException(nameof(elseSource));
            }

            return(CreateAsyncObservable <TResult> .From(
                       thenSource,
                       (elseSource, condition),
                       static async (thenSource, state, observer) =>
            {
                var b = default(bool);

                try
                {
                    b = await state.condition().ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    return await Throw <TResult>(ex).SubscribeAsync(observer).ConfigureAwait(false);
                }

                return await(b ? thenSource : state.elseSource).SubscribeSafeAsync(observer).ConfigureAwait(false);
            }));
        }
Пример #6
0
        public static IAsyncObservable <TSource> Timeout <TSource>(this IAsyncObservable <TSource> source, TimeSpan dueTime, IAsyncObservable <TSource> other, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (other == null)
            {
                throw new ArgumentNullException(nameof(other));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       (dueTime, other, scheduler),
                       static async (source, state, observer) =>
            {
                var sourceSubscription = new SingleAssignmentAsyncDisposable();

                var(sink, disposable) = await AsyncObserver.Timeout(observer, sourceSubscription, state.dueTime, state.other, state.scheduler).ConfigureAwait(false);

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

                await sourceSubscription.AssignAsync(sourceSubscriptionInner).ConfigureAwait(false);

                return disposable;
            }));
        }
Пример #7
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(CreateAsyncObservable <TSource> .From(
                       source,
                       (duration, clock),
                       static async (source, state, observer) =>
            {
                var(sink, drain) = AsyncObserver.TakeLast(observer, state.duration, state.clock);

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

                return StableCompositeAsyncDisposable.Create(subscription, drain);
            }));
        }
Пример #8
0
        public static IAsyncObservable <TSource> Throttle <TSource>(this IAsyncObservable <TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (dueTime < TimeSpan.Zero)
            {
                throw new ArgumentOutOfRangeException(nameof(dueTime));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       (dueTime, scheduler),
                       static async (source, state, observer) =>
            {
                var d = new CompositeAsyncDisposable();

                var(sink, throttler) = AsyncObserver.Throttle(observer, state.dueTime, state.scheduler);

                await d.AddAsync(throttler).ConfigureAwait(false);

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

                await d.AddAsync(sourceSubscription).ConfigureAwait(false);

                return d;
            }));
        }
Пример #9
0
        public static IAsyncObservable <TResult> Multicast <TSource, TIntermediate, TResult>(this IAsyncObservable <TSource> source, Func <ValueTask <IAsyncSubject <TSource, TIntermediate> > > subjectFactory, Func <IAsyncObservable <TIntermediate>, ValueTask <IAsyncObservable <TResult> > > selector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (subjectFactory == null)
            {
                throw new ArgumentNullException(nameof(subjectFactory));
            }
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

            // REVIEW: Use a lifted observer operator.

            return(CreateAsyncObservable <TResult> .From(
                       source,
                       (subjectFactory, selector),
                       static async (source, state, observer) =>
            {
                var observable = default(IAsyncObservable <TResult>);
                var connectable = default(IConnectableAsyncObservable <TIntermediate>);

                try
                {
                    var subject = await state.subjectFactory().ConfigureAwait(false);
                    connectable = new ConnectableAsyncObservable <TSource, TIntermediate>(source, subject);
                    observable = await state.selector(connectable).ConfigureAwait(false);
                }
                catch (Exception ex)
                {
                    await observer.OnErrorAsync(ex).ConfigureAwait(false);
                    return AsyncDisposable.Nop;
                }

                var d = new CompositeAsyncDisposable();

                var subscription = await observable.SubscribeAsync(observer).ConfigureAwait(false);
                await d.AddAsync(subscription).ConfigureAwait(false);

                var connection = await connectable.ConnectAsync().ConfigureAwait(false);
                await d.AddAsync(connection).ConfigureAwait(false);

                return d;
            }));
        }
Пример #10
0
        public static IAsyncObservable <TSource> Prepend <TSource>(this IAsyncObservable <TSource> source, TSource value, IAsyncScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (scheduler == null)
            {
                throw new ArgumentNullException(nameof(scheduler));
            }

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       (scheduler, value),
                       static (source, state, observer) => AsyncObserver.Prepend(observer, source, state.value, state.scheduler)));
        }
Пример #11
0
        public static IAsyncObservable <TSource> SubscribeOn <TSource>(this IAsyncObservable <TSource> source, IAsyncScheduler subscribeScheduler, IAsyncScheduler disposeScheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (subscribeScheduler == null)
            {
                throw new ArgumentNullException(nameof(subscribeScheduler));
            }
            if (disposeScheduler == null)
            {
                throw new ArgumentNullException(nameof(disposeScheduler));
            }

            return(CreateAsyncObservable <TSource> .From(
                       source,
                       (subscribeScheduler, disposeScheduler),
                       static async (source, state, observer) =>
            {
                var m = new SingleAssignmentAsyncDisposable();
                var d = new SerialAsyncDisposable();

                await d.AssignAsync(m).ConfigureAwait(false);

                var scheduled = await state.subscribeScheduler.ScheduleAsync(async ct =>
                {
                    var subscription = await source.SubscribeSafeAsync(observer).RendezVous(state.subscribeScheduler, ct);

                    var scheduledDispose = AsyncDisposable.Create(async() =>
                    {
                        await state.disposeScheduler.ScheduleAsync(async _ =>
                        {
                            await subscription.DisposeAsync().RendezVous(state.disposeScheduler, ct);
                        }).ConfigureAwait(false);
                    });

                    await d.AssignAsync(scheduledDispose).RendezVous(state.subscribeScheduler, ct);
                }).ConfigureAwait(false);

                await m.AssignAsync(scheduled).ConfigureAwait(false);

                return d;
            }));
        }
Пример #12
0
        public static IAsyncObservable <ILookup <TKey, TValue> > ToLookup <TSource, TKey, TValue>(this IAsyncObservable <TSource> source, Func <TSource, ValueTask <TKey> > keySelector, Func <TSource, ValueTask <TValue> > valueSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (keySelector == null)
            {
                throw new ArgumentNullException(nameof(keySelector));
            }
            if (valueSelector == null)
            {
                throw new ArgumentNullException(nameof(valueSelector));
            }

            return(CreateAsyncObservable <ILookup <TKey, TValue> > .From(
                       source,
                       (keySelector, valueSelector),
                       static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToLookup(observer, state.keySelector, state.valueSelector))));
        }
Пример #13
0
        public static IAsyncObservable <TResult> Join <TLeft, TRight, TLeftDuration, TRightDuration, TResult>(this IAsyncObservable <TLeft> left, IAsyncObservable <TRight> right, Func <TLeft, IAsyncObservable <TLeftDuration> > leftDurationSelector, Func <TRight, IAsyncObservable <TRightDuration> > rightDurationSelector, Func <TLeft, TRight, TResult> resultSelector)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }
            if (leftDurationSelector == null)
            {
                throw new ArgumentNullException(nameof(leftDurationSelector));
            }
            if (rightDurationSelector == null)
            {
                throw new ArgumentNullException(nameof(rightDurationSelector));
            }
            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return(CreateAsyncObservable <TResult> .From(
                       left,
                       (right, leftDurationSelector, rightDurationSelector, resultSelector),
                       static async (left, state, observer) =>
            {
                var subscriptions = new CompositeAsyncDisposable();

                var(leftObserver, rightObserver, disposable) = AsyncObserver.Join(observer, subscriptions, state.leftDurationSelector, state.rightDurationSelector, state.resultSelector);

                var leftSubscription = await left.SubscribeSafeAsync(leftObserver).ConfigureAwait(false);
                await subscriptions.AddAsync(leftSubscription).ConfigureAwait(false);

                var rightSubscription = await state.right.SubscribeSafeAsync(rightObserver).ConfigureAwait(false);
                await subscriptions.AddAsync(rightSubscription).ConfigureAwait(false);

                return disposable;
            }));
        }
Пример #14
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(CreateAsyncObservable <TSource> .From(
                       source,
                       (scheduler, interval),
                       static async (source, state, observer) =>
            {
                var(sourceSink, sampler) = await AsyncObserver.Sample(observer, state.interval, state.scheduler).ConfigureAwait(false);

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

                return StableCompositeAsyncDisposable.Create(sourceSubscription, sampler);
            }));
        }
Пример #15
0
        public static IAsyncObservable <IDictionary <TKey, TValue> > ToDictionary <TSource, TKey, TValue>(this IAsyncObservable <TSource> source, Func <TSource, TKey> keySelector, Func <TSource, TValue> valueSelector, IEqualityComparer <TKey> comparer)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (keySelector == null)
            {
                throw new ArgumentNullException(nameof(keySelector));
            }
            if (valueSelector == null)
            {
                throw new ArgumentNullException(nameof(valueSelector));
            }
            if (comparer == null)
            {
                throw new ArgumentNullException(nameof(comparer));
            }

            return(CreateAsyncObservable <IDictionary <TKey, TValue> > .From(
                       source,
                       (keySelector, valueSelector, comparer),
                       static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.ToDictionary(observer, state.keySelector, state.valueSelector, state.comparer))));;
        }
Пример #16
0
 internal static IAsyncObservable <TSource> Create <TSource, TState>(IAsyncObservable <TSource> source, TState state, Func <IAsyncObservable <TSource>, TState, IAsyncObserver <TSource>, ValueTask <IAsyncDisposable> > subscribeAsync)
 {
     return(CreateAsyncObservable <TSource> .From(source, state, subscribeAsync));
 }