Beispiel #1
0
        internal static async Task <LookupWithTask <TKey, TElement> > CreateAsync(IAsyncEnumerable <TElement> source, Func <TElement, CancellationToken, ValueTask <TKey> > keySelector, IEqualityComparer <TKey>?comparer, CancellationToken cancellationToken)
        {
            var lookup = new LookupWithTask <TKey, TElement>(comparer);

            await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
            {
                var key = await keySelector(item, cancellationToken).ConfigureAwait(false);

                lookup.GetOrCreateGrouping(key).Add(item);
            }

            return(lookup);
        }
Beispiel #2
0
        internal static async Task <LookupWithTask <TKey, TElement> > CreateForJoinAsync(IAsyncEnumerable <TElement> source, Func <TElement, CancellationToken, ValueTask <TKey> > keySelector, IEqualityComparer <TKey> comparer, CancellationToken cancellationToken)
        {
            var lookup = new LookupWithTask <TKey, TElement>(comparer);

            await foreach (var item in AsyncEnumerableExtensions.WithCancellation(source, cancellationToken).ConfigureAwait(false))
            {
                var key = await keySelector(item, cancellationToken).ConfigureAwait(false);

                if (key != null)
                {
                    lookup.GetGrouping(key, create: true).Add(item);
                }
            }

            return(lookup);
        }
Beispiel #3
0
        internal static async Task <LookupWithTask <TKey, TElement> > CreateAsync <TSource>(IAsyncEnumerable <TSource> source, Func <TSource, CancellationToken, ValueTask <TKey> > keySelector, Func <TSource, CancellationToken, ValueTask <TElement> > elementSelector, IEqualityComparer <TKey> comparer, CancellationToken cancellationToken)
        {
            Debug.Assert(source != null);
            Debug.Assert(keySelector != null);
            Debug.Assert(elementSelector != null);

            var lookup = new LookupWithTask <TKey, TElement>(comparer);

            await foreach (var item in source.WithCancellation(cancellationToken).ConfigureAwait(false))
            {
                var key = await keySelector(item, cancellationToken).ConfigureAwait(false);

                var group = lookup.GetGrouping(key, create: true);

                var element = await elementSelector(item, cancellationToken).ConfigureAwait(false);

                group.Add(element);
            }

            return(lookup);
        }
Beispiel #4
0
                public async ValueTask <bool> MoveNextAsync()
                {
                    // nothing to do
                    if (!await _outer.MoveNextAsync().ConfigureAwait(false))
                    {
                        return(false);
                    }

                    if (_lookup == null)
                    {
                        _lookup = await Internal.LookupWithTask <TKey, TInner> .CreateForJoinAsync(_inner, _innerKeySelector, _comparer, _cancellationToken).ConfigureAwait(false);
                    }

                    var item = _outer.Current;

                    var outerKey = await _outerKeySelector(item, _cancellationToken).ConfigureAwait(false);

                    var inner = _lookup[outerKey].ToAsyncEnumerable();

                    Current = await _resultSelector(item, inner, _cancellationToken).ConfigureAwait(false);

                    return(true);
                }
Beispiel #5
0
            protected override async ValueTask <bool> MoveNextCore()
            {
                switch (_state)
                {
                case AsyncIteratorState.Allocated:
                    _outerEnumerator = _outer.GetAsyncEnumerator(_cancellationToken);
                    _mode            = State_If;
                    _state           = AsyncIteratorState.Iterating;
                    goto case AsyncIteratorState.Iterating;

                case AsyncIteratorState.Iterating:
                    switch (_mode)
                    {
                    case State_If:
                        if (await _outerEnumerator.MoveNextAsync().ConfigureAwait(false))
                        {
                            _lookup = await Internal.LookupWithTask <TKey, TInner> .CreateForJoinAsync(_inner, _innerKeySelector, _comparer, _cancellationToken).ConfigureAwait(false);

                            if (_lookup.Count != 0)
                            {
                                _mode = State_DoLoop;
                                goto case State_DoLoop;
                            }
                        }

                        break;

                    case State_DoLoop:
                        _item = _outerEnumerator.Current;
                        var g = _lookup.GetGrouping(await _outerKeySelector(_item, _cancellationToken).ConfigureAwait(false), create: false);
                        if (g != null)
                        {
                            _count    = g._count;
                            _elements = g._elements;
                            _index    = 0;
                            _mode     = State_For;
                            goto case State_For;
                        }

                        // advance to while
                        _mode = State_While;
                        goto case State_While;

                    case State_For:
                        _current = await _resultSelector(_item, _elements[_index], _cancellationToken).ConfigureAwait(false);

                        _index++;
                        if (_index == _count)
                        {
                            _mode = State_While;
                        }

                        return(true);

                    case State_While:
                        var hasNext = await _outerEnumerator.MoveNextAsync().ConfigureAwait(false);

                        if (hasNext)
                        {
                            goto case State_DoLoop;
                        }

                        break;
                    }

                    await DisposeAsync().ConfigureAwait(false);

                    break;
                }

                return(false);
            }