123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the MIT License.
- // See the LICENSE file in the project root for more information.
- using System.Collections;
- using System.Collections.Generic;
- using System.Threading;
- using System.Threading.Tasks;
- namespace System.Linq
- {
- #if INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
- // NB: Large portions of the implementation are based on https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/OrderedEnumerable.cs.
- internal abstract class OrderedAsyncEnumerable<TElement> : AsyncIterator<TElement>, IOrderedAsyncEnumerable<TElement>, IAsyncPartition<TElement>
- {
- protected readonly IAsyncEnumerable<TElement> _source;
- private TElement[]? _buffer;
- private int[]? _indexes;
- private int _index;
- protected OrderedAsyncEnumerable(IAsyncEnumerable<TElement> source)
- {
- _source = source ?? throw Error.ArgumentNull(nameof(source));
- }
- IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey>? comparer, bool descending)
- {
- return new OrderedAsyncEnumerable<TElement, TKey>(_source, keySelector, comparer, descending, this);
- }
- IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, bool descending)
- {
- return new OrderedAsyncEnumerableWithTask<TElement, TKey>(_source, keySelector, comparer, descending, this);
- }
- IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, bool descending)
- {
- return new OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey>(_source, keySelector, comparer, descending, this);
- }
- protected override async ValueTask<bool> MoveNextCore()
- {
- switch (_state)
- {
- case AsyncIteratorState.Allocated:
- _buffer = await _source.ToArrayAsync(_cancellationToken).ConfigureAwait(false); // TODO: Use buffer.
- var sorter = GetAsyncEnumerableSorter(_cancellationToken);
- _indexes = await sorter.Sort(_buffer, _buffer.Length).ConfigureAwait(false);
- _index = 0;
- _state = AsyncIteratorState.Iterating;
- goto case AsyncIteratorState.Iterating;
- case AsyncIteratorState.Iterating:
- if (_index < _buffer!.Length)
- {
- _current = _buffer[_indexes![_index++]];
- return true;
- }
- await DisposeAsync().ConfigureAwait(false);
- break;
- }
- return false;
- }
- public override async ValueTask DisposeAsync()
- {
- _buffer = null;
- _indexes = null;
- await base.DisposeAsync().ConfigureAwait(false);
- }
- internal abstract AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement>? next, CancellationToken cancellationToken);
- internal AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(CancellationToken cancellationToken) => GetAsyncEnumerableSorter(next: null, cancellationToken);
- public async ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count == 0)
- {
- return [];
- }
- var array = elements.Array;
- var map = await SortedMap(array, count, cancellationToken).ConfigureAwait(false);
- var result = new TElement[count];
- for (var i = 0; i < result.Length; i++)
- {
- result[i] = array[map[i]];
- }
- return result;
- }
- internal async ValueTask<TElement[]> ToArrayAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count <= minIndexInclusive)
- {
- return [];
- }
- if (count <= maxIndexInclusive)
- {
- maxIndexInclusive = count - 1;
- }
- var array = elements.Array;
- if (minIndexInclusive == maxIndexInclusive)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- var element = await sorter.ElementAt(array, count, minIndexInclusive).ConfigureAwait(false);
- return [element];
- }
- var map = await SortedMap(array, count, minIndexInclusive, maxIndexInclusive, cancellationToken).ConfigureAwait(false);
- var result = new TElement[maxIndexInclusive - minIndexInclusive + 1];
- for (var i = 0; minIndexInclusive <= maxIndexInclusive; i++)
- {
- result[i] = array[map[minIndexInclusive++]];
- }
- return result;
- }
- public async ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count == 0)
- {
- return [];
- }
- var array = elements.Array;
- var map = await SortedMap(array, count, cancellationToken).ConfigureAwait(false);
- var result = new List<TElement>(count);
- for (var i = 0; i < count; i++)
- {
- result.Add(array[map[i]]);
- }
- return result;
- }
- internal async ValueTask<List<TElement>> ToListAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count <= minIndexInclusive)
- {
- return [];
- }
- if (count <= maxIndexInclusive)
- {
- maxIndexInclusive = count - 1;
- }
- var array = elements.Array;
- if (minIndexInclusive == maxIndexInclusive)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- var element = await sorter.ElementAt(array, count, minIndexInclusive).ConfigureAwait(false);
- return [element];
- }
- var map = await SortedMap(array, count, minIndexInclusive, maxIndexInclusive, cancellationToken).ConfigureAwait(false);
- var list = new List<TElement>(maxIndexInclusive - minIndexInclusive + 1);
- while (minIndexInclusive <= maxIndexInclusive)
- {
- list.Add(array[map[minIndexInclusive++]]);
- }
- return list;
- }
- public async ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
- {
- if (_source is IAsyncIListProvider<TElement> listProv)
- {
- var count = await listProv.GetCountAsync(onlyIfCheap, cancellationToken).ConfigureAwait(false);
- return count;
- }
- return !onlyIfCheap || _source is ICollection<TElement> || _source is ICollection ? await _source.CountAsync(cancellationToken).ConfigureAwait(false) : -1;
- }
- internal async ValueTask<int> GetCountAsync(int minIndexInclusive, int maxIndexInclusive, bool onlyIfCheap, CancellationToken cancellationToken)
- {
- var count = await GetCountAsync(onlyIfCheap, cancellationToken).ConfigureAwait(false);
- if (count <= 0)
- {
- return count;
- }
- if (count <= minIndexInclusive)
- {
- return 0;
- }
- return (count <= maxIndexInclusive ? count : maxIndexInclusive + 1) - minIndexInclusive;
- }
- private ValueTask<int[]> SortedMap(TElement[] elements, int count, CancellationToken cancellationToken)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- return sorter.Sort(elements, count);
- }
- private ValueTask<int[]> SortedMap(TElement[] elements, int count, int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- return sorter.Sort(elements, count, minIndexInclusive, maxIndexInclusive);
- }
- private AsyncCachingComparer<TElement> GetComparer() => GetComparer(childComparer: null);
- internal abstract AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement>? childComparer);
- public async ValueTask<Maybe<TElement>> TryGetFirstAsync(CancellationToken cancellationToken)
- {
- await using var e = _source.GetConfiguredAsyncEnumerator(cancellationToken, false);
- if (!await e.MoveNextAsync())
- {
- return new Maybe<TElement>();
- }
- var value = e.Current;
- var comparer = GetComparer();
- await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
- while (await e.MoveNextAsync())
- {
- var x = e.Current;
- if (await comparer.Compare(x, cacheLower: true, cancellationToken).ConfigureAwait(false) < 0)
- {
- value = x;
- }
- }
- return new Maybe<TElement>(value);
- }
- public async ValueTask<Maybe<TElement>> TryGetLastAsync(CancellationToken cancellationToken)
- {
- await using var e = _source.GetConfiguredAsyncEnumerator(cancellationToken, false);
- if (!await e.MoveNextAsync())
- {
- return new Maybe<TElement>();
- }
- var value = e.Current;
- var comparer = GetComparer();
- await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
- while (await e.MoveNextAsync())
- {
- var current = e.Current;
- if (await comparer.Compare(current, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
- {
- value = current;
- }
- }
- return new Maybe<TElement>(value);
- }
- internal async ValueTask<Maybe<TElement>> TryGetLastAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (minIndexInclusive >= count)
- {
- return new Maybe<TElement>();
- }
- var array = elements.Array;
- TElement last;
- if (maxIndexInclusive < count - 1)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- last = await sorter.ElementAt(array, count, maxIndexInclusive).ConfigureAwait(false);
- }
- else
- {
- last = await Last(array, count, cancellationToken).ConfigureAwait(false);
- }
- return new Maybe<TElement>(last);
- }
- private async ValueTask<TElement> Last(TElement[] items, int count, CancellationToken cancellationToken)
- {
- var value = items[0];
- var comparer = GetComparer();
- await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
- for (var i = 1; i != count; ++i)
- {
- var x = items[i];
- if (await comparer.Compare(x, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
- {
- value = x;
- }
- }
- return value;
- }
- public IAsyncPartition<TElement> Skip(int count) => new OrderedAsyncPartition<TElement>(this, count, int.MaxValue);
- public IAsyncPartition<TElement> Take(int count) => new OrderedAsyncPartition<TElement>(this, 0, count - 1);
- public ValueTask<Maybe<TElement>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
- {
- if (index == 0)
- {
- return TryGetFirstAsync(cancellationToken);
- }
- if (index > 0)
- {
- return Core();
- async ValueTask<Maybe<TElement>> Core()
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (index < count)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- var element = await sorter.ElementAt(elements.Array, count, index).ConfigureAwait(false);
- return new Maybe<TElement>(element);
- }
- return new Maybe<TElement>();
- }
- }
- return new ValueTask<Maybe<TElement>>(new Maybe<TElement>());
- }
- }
- internal sealed class OrderedAsyncEnumerable<TElement, TKey> : OrderedAsyncEnumerable<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- private readonly Func<TElement, TKey> _keySelector;
- private readonly OrderedAsyncEnumerable<TElement>? _parent;
- public OrderedAsyncEnumerable(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey>? comparer, bool descending, OrderedAsyncEnumerable<TElement>? parent)
- : base(source)
- {
- _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
- _comparer = comparer ?? Comparer<TKey>.Default;
- _descending = descending;
- _parent = parent;
- }
- public override AsyncIteratorBase<TElement> Clone()
- {
- return new OrderedAsyncEnumerable<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
- }
- internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement>? next, CancellationToken cancellationToken)
- {
- var sorter = new SyncKeySelectorAsyncEnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
- if (_parent != null)
- {
- return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
- }
- return sorter;
- }
- internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement>? childComparer)
- {
- AsyncCachingComparer<TElement> cmp = childComparer == null
- ? new AsyncCachingComparer<TElement, TKey>(_keySelector, _comparer, _descending)
- : new AsyncCachingComparerWithChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
- return _parent != null ? _parent.GetComparer(cmp) : cmp;
- }
- }
- internal sealed class OrderedAsyncEnumerableWithTask<TElement, TKey> : OrderedAsyncEnumerable<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- private readonly Func<TElement, ValueTask<TKey>> _keySelector;
- private readonly OrderedAsyncEnumerable<TElement>? _parent;
- public OrderedAsyncEnumerableWithTask(IAsyncEnumerable<TElement> source, Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, bool descending, OrderedAsyncEnumerable<TElement>? parent)
- : base(source)
- {
- _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
- _comparer = comparer ?? Comparer<TKey>.Default;
- _descending = descending;
- _parent = parent;
- }
- public override AsyncIteratorBase<TElement> Clone()
- {
- return new OrderedAsyncEnumerableWithTask<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
- }
- internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement>? next, CancellationToken cancellationToken)
- {
- var sorter = new AsyncKeySelectorAsyncEnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
- if (_parent != null)
- {
- return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
- }
- return sorter;
- }
- internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement>? childComparer)
- {
- AsyncCachingComparer<TElement> cmp = childComparer == null
- ? new AsyncCachingComparerWithTask<TElement, TKey>(_keySelector, _comparer, _descending)
- : new AsyncCachingComparerWithTaskAndChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
- return _parent != null ? _parent.GetComparer(cmp) : cmp;
- }
- }
- #if !NO_DEEP_CANCELLATION
- internal sealed class OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey> : OrderedAsyncEnumerable<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- private readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
- private readonly OrderedAsyncEnumerable<TElement>? _parent;
- public OrderedAsyncEnumerableWithTaskAndCancellation(IAsyncEnumerable<TElement> source, Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey>? comparer, bool descending, OrderedAsyncEnumerable<TElement>? parent)
- : base(source)
- {
- _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
- _comparer = comparer ?? Comparer<TKey>.Default;
- _descending = descending;
- _parent = parent;
- }
- public override AsyncIteratorBase<TElement> Clone()
- {
- return new OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
- }
- internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement>? next, CancellationToken cancellationToken)
- {
- var sorter = new AsyncKeySelectorAsyncEnumerableSorterWithCancellation<TElement, TKey>(_keySelector, _comparer, _descending, next, cancellationToken);
- if (_parent != null)
- {
- return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
- }
- return sorter;
- }
- internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement>? childComparer)
- {
- AsyncCachingComparer<TElement> cmp = childComparer == null
- ? new AsyncCachingComparerWithTaskAndCancellation<TElement, TKey>(_keySelector, _comparer, _descending)
- : new AsyncCachingComparerWithTaskAndCancellationAndChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
- return _parent != null ? _parent.GetComparer(cmp) : cmp;
- }
- }
- #endif
- internal abstract class AsyncEnumerableSorter<TElement>
- {
- internal abstract ValueTask ComputeKeys(TElement[] elements, int count);
- internal abstract int CompareAnyKeys(int index1, int index2);
- public async ValueTask<int[]> Sort(TElement[] elements, int count)
- {
- var map = await ComputeMap(elements, count).ConfigureAwait(false);
- QuickSort(map, 0, count - 1);
- return map;
- }
- public async ValueTask<int[]> Sort(TElement[] elements, int count, int minIndexInclusive, int maxIndexInclusive)
- {
- var map = await ComputeMap(elements, count).ConfigureAwait(false);
- PartialQuickSort(map, 0, count - 1, minIndexInclusive, maxIndexInclusive);
- return map;
- }
- public async ValueTask<TElement> ElementAt(TElement[] elements, int count, int index)
- {
- var map = await ComputeMap(elements, count).ConfigureAwait(false);
- return index == 0 ?
- elements[Min(map, count)] :
- elements[QuickSelect(map, count - 1, index)];
- }
- private async ValueTask<int[]> ComputeMap(TElement[] elements, int count)
- {
- await ComputeKeys(elements, count).ConfigureAwait(false);
- var map = new int[count];
- for (var i = 0; i < count; i++)
- {
- map[i] = i;
- }
- return map;
- }
- protected abstract void QuickSort(int[] map, int left, int right);
- protected abstract void PartialQuickSort(int[] map, int left, int right, int minIndexInclusive, int maxIndexInclusive);
- protected abstract int QuickSelect(int[] map, int right, int idx);
- protected abstract int Min(int[] map, int count);
- }
- internal abstract class AsyncEnumerableSorterBase<TElement, TKey> : AsyncEnumerableSorter<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- protected readonly AsyncEnumerableSorter<TElement>? _next;
- protected TKey[]? _keys;
- public AsyncEnumerableSorterBase(IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement>? next)
- {
- _comparer = comparer;
- _descending = descending;
- _next = next;
- }
- internal sealed override int CompareAnyKeys(int index1, int index2)
- {
- var c = _comparer.Compare(_keys![index1], _keys[index2]); // NB: _keys is assigned before calling this method.
- if (c == 0)
- {
- return _next == null ? index1 - index2 : _next.CompareAnyKeys(index1, index2);
- }
- else
- {
- return (_descending != (c > 0)) ? 1 : -1;
- }
- }
- private int CompareKeys(int index1, int index2) => index1 == index2 ? 0 : CompareAnyKeys(index1, index2);
- protected override void QuickSort(int[] keys, int lo, int hi) => Array.Sort(keys, lo, hi - lo + 1, Comparer<int>.Create(CompareAnyKeys));
- protected override void PartialQuickSort(int[] map, int left, int right, int minIndexInclusive, int maxIndexInclusive)
- {
- do
- {
- var i = left;
- var j = right;
- var x = map[i + ((j - i) >> 1)];
- do
- {
- while (i < map.Length && CompareKeys(x, map[i]) > 0)
- {
- i++;
- }
- while (j >= 0 && CompareKeys(x, map[j]) < 0)
- {
- j--;
- }
- if (i > j)
- {
- break;
- }
- if (i < j)
- {
- (map[j], map[i]) = (map[i], map[j]);
- }
- i++;
- j--;
- }
- while (i <= j);
- if (minIndexInclusive >= i)
- {
- left = i + 1;
- }
- else if (maxIndexInclusive <= j)
- {
- right = j - 1;
- }
- if (j - left <= right - i)
- {
- if (left < j)
- {
- PartialQuickSort(map, left, j, minIndexInclusive, maxIndexInclusive);
- }
- left = i;
- }
- else
- {
- if (i < right)
- {
- PartialQuickSort(map, i, right, minIndexInclusive, maxIndexInclusive);
- }
- right = j;
- }
- }
- while (left < right);
- }
- protected override int QuickSelect(int[] map, int right, int idx)
- {
- var left = 0;
- do
- {
- var i = left;
- var j = right;
- var x = map[i + ((j - i) >> 1)];
- do
- {
- while (i < map.Length && CompareKeys(x, map[i]) > 0)
- {
- i++;
- }
- while (j >= 0 && CompareKeys(x, map[j]) < 0)
- {
- j--;
- }
- if (i > j)
- {
- break;
- }
- if (i < j)
- {
- (map[j], map[i]) = (map[i], map[j]);
- }
- i++;
- j--;
- }
- while (i <= j);
- if (i <= idx)
- {
- left = i + 1;
- }
- else
- {
- right = j - 1;
- }
- if (j - left <= right - i)
- {
- if (left < j)
- {
- right = j;
- }
- left = i;
- }
- else
- {
- if (i < right)
- {
- left = i;
- }
- right = j;
- }
- }
- while (left < right);
- return map[idx];
- }
- protected override int Min(int[] map, int count)
- {
- var index = 0;
- for (var i = 1; i < count; i++)
- {
- if (CompareKeys(map[i], map[index]) < 0)
- {
- index = i;
- }
- }
- return map[index];
- }
- }
- internal sealed class SyncKeySelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
- {
- private readonly Func<TElement, TKey> _keySelector;
- public SyncKeySelectorAsyncEnumerableSorter(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement>? next)
- : base(comparer, descending, next)
- {
- _keySelector = keySelector;
- }
- internal override async ValueTask ComputeKeys(TElement[] elements, int count)
- {
- _keys = new TKey[count];
- for (var i = 0; i < count; i++)
- {
- _keys[i] = _keySelector(elements[i]);
- }
- if (_next != null)
- {
- await _next.ComputeKeys(elements, count).ConfigureAwait(false);
- }
- }
- }
- internal sealed class AsyncKeySelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
- {
- private readonly Func<TElement, ValueTask<TKey>> _keySelector;
- public AsyncKeySelectorAsyncEnumerableSorter(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement>? next)
- : base(comparer, descending, next)
- {
- _keySelector = keySelector;
- }
- internal override async ValueTask ComputeKeys(TElement[] elements, int count)
- {
- _keys = new TKey[count];
- for (var i = 0; i < count; i++)
- {
- _keys[i] = await _keySelector(elements[i]).ConfigureAwait(false);
- }
- if (_next != null)
- {
- await _next.ComputeKeys(elements, count).ConfigureAwait(false);
- }
- }
- }
- #if !NO_DEEP_CANCELLATION
- internal sealed class AsyncKeySelectorAsyncEnumerableSorterWithCancellation<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
- {
- private readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
- private readonly CancellationToken _cancellationToken;
- public AsyncKeySelectorAsyncEnumerableSorterWithCancellation(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement>? next, CancellationToken cancellationToken)
- : base(comparer, descending, next)
- {
- _keySelector = keySelector;
- _cancellationToken = cancellationToken;
- }
- internal override async ValueTask ComputeKeys(TElement[] elements, int count)
- {
- _keys = new TKey[count];
- for (var i = 0; i < count; i++)
- {
- _keys[i] = await _keySelector(elements[i], _cancellationToken).ConfigureAwait(false);
- }
- if (_next != null)
- {
- await _next.ComputeKeys(elements, count).ConfigureAwait(false);
- }
- }
- }
- #endif
- internal sealed class OrderedAsyncPartition<TElement> : AsyncIterator<TElement>, IAsyncPartition<TElement>
- {
- private readonly OrderedAsyncEnumerable<TElement> _source;
- private readonly int _minIndexInclusive;
- private readonly int _maxIndexInclusive;
- public OrderedAsyncPartition(OrderedAsyncEnumerable<TElement> source, int minIndexInclusive, int maxIndexInclusive)
- {
- _source = source;
- _minIndexInclusive = minIndexInclusive;
- _maxIndexInclusive = maxIndexInclusive;
- }
- public override AsyncIteratorBase<TElement> Clone() => new OrderedAsyncPartition<TElement>(_source, _minIndexInclusive, _maxIndexInclusive);
- public ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) =>
- _source.GetCountAsync(_minIndexInclusive, _maxIndexInclusive, onlyIfCheap, cancellationToken);
- public IAsyncPartition<TElement> Skip(int count)
- {
- var minIndex = unchecked(_minIndexInclusive + count);
- if (unchecked((uint)minIndex > (uint)_maxIndexInclusive))
- {
- return AsyncEnumerable.EmptyAsyncIterator<TElement>.Instance;
- }
-
- return new OrderedAsyncPartition<TElement>(_source, minIndex, _maxIndexInclusive);
- }
- public IAsyncPartition<TElement> Take(int count)
- {
- var maxIndex = unchecked(_minIndexInclusive + count - 1);
- if (unchecked((uint)maxIndex >= (uint)_maxIndexInclusive))
- {
- return this;
- }
- return new OrderedAsyncPartition<TElement>(_source, _minIndexInclusive, maxIndex);
- }
- public ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken) =>
- _source.ToArrayAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
- public ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken) =>
- _source.ToListAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
- public ValueTask<Maybe<TElement>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
- {
- if (unchecked((uint)index <= (uint)(_maxIndexInclusive - _minIndexInclusive)))
- {
- return _source.TryGetElementAtAsync(index + _minIndexInclusive, cancellationToken);
- }
- return new ValueTask<Maybe<TElement>>(new Maybe<TElement>());
- }
- public ValueTask<Maybe<TElement>> TryGetFirstAsync(CancellationToken cancellationToken) =>
- _source.TryGetElementAtAsync(_minIndexInclusive, cancellationToken);
- public ValueTask<Maybe<TElement>> TryGetLastAsync(CancellationToken cancellationToken) =>
- _source.TryGetLastAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
- // REVIEW: Consider to tear off an iterator object rather than storing this state here?
- private TElement[]? _buffer;
- private int[]? _indexes;
- private int _minIndexIterator;
- private int _maxIndexIterator;
- protected override async ValueTask<bool> MoveNextCore()
- {
- switch (_state)
- {
- case AsyncIteratorState.Allocated:
- _buffer = await _source.ToArrayAsync(_cancellationToken).ConfigureAwait(false); // TODO: Use buffer.
- _minIndexIterator = _minIndexInclusive;
- _maxIndexIterator = _maxIndexInclusive;
- var count = _buffer.Length;
- if (count > _minIndexIterator)
- {
- if (count <= _maxIndexIterator)
- {
- _maxIndexIterator = count - 1;
- }
- var sorter = _source.GetAsyncEnumerableSorter(_cancellationToken);
- if (_minIndexIterator == _maxIndexIterator)
- {
- _current = await sorter.ElementAt(_buffer, _buffer.Length, _minIndexIterator).ConfigureAwait(false);
- _minIndexIterator = int.MaxValue;
- _maxIndexIterator = int.MinValue;
- _state = AsyncIteratorState.Iterating;
- return true;
- }
- else
- {
- _indexes = await sorter.Sort(_buffer, _buffer.Length, _minIndexIterator, _maxIndexIterator).ConfigureAwait(false);
- }
- _state = AsyncIteratorState.Iterating;
- goto case AsyncIteratorState.Iterating;
- }
- await DisposeAsync();
- break;
- case AsyncIteratorState.Iterating:
- if (_minIndexIterator <= _maxIndexIterator)
- {
- _current = _buffer![_indexes![_minIndexIterator++]];
- return true;
- }
- await DisposeAsync().ConfigureAwait(false);
- break;
- }
- return false;
- }
- public override async ValueTask DisposeAsync()
- {
- _buffer = null;
- _indexes = null;
- await base.DisposeAsync().ConfigureAwait(false);
- }
- }
- internal abstract class AsyncCachingComparer<TElement>
- {
- internal abstract ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken);
- internal abstract ValueTask SetElement(TElement element, CancellationToken cancellationToken);
- }
- internal class AsyncCachingComparer<TElement, TKey> : AsyncCachingComparer<TElement>
- {
- protected readonly Func<TElement, TKey> _keySelector;
- protected readonly IComparer<TKey> _comparer;
- protected readonly bool _descending;
- protected TKey _lastKey;
- public AsyncCachingComparer(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
- {
- _keySelector = keySelector;
- _comparer = comparer;
- _descending = descending;
- _lastKey = default!;
- }
- internal override ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = _keySelector(element);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- }
- return new ValueTask<int>(cmp);
- }
- internal override ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- _lastKey = _keySelector(element);
- return new ValueTask();
- }
- }
- internal sealed class AsyncCachingComparerWithChild<TElement, TKey> : AsyncCachingComparer<TElement, TKey>
- {
- private readonly AsyncCachingComparer<TElement> _child;
- public AsyncCachingComparerWithChild(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
- : base(keySelector, comparer, descending)
- {
- _child = child;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = _keySelector(element);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cmp == 0)
- {
- return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
- }
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- await base.SetElement(element, cancellationToken).ConfigureAwait(false);
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- }
- internal class AsyncCachingComparerWithTask<TElement, TKey> : AsyncCachingComparer<TElement>
- {
- protected readonly Func<TElement, ValueTask<TKey>> _keySelector;
- protected readonly IComparer<TKey> _comparer;
- protected readonly bool _descending;
- protected TKey _lastKey;
- public AsyncCachingComparerWithTask(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
- {
- _keySelector = keySelector;
- _comparer = comparer;
- _descending = descending;
- _lastKey = default!;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- _lastKey = await _keySelector(element).ConfigureAwait(false);
- }
- }
- internal sealed class AsyncCachingComparerWithTaskAndChild<TElement, TKey> : AsyncCachingComparerWithTask<TElement, TKey>
- {
- private readonly AsyncCachingComparer<TElement> _child;
- public AsyncCachingComparerWithTaskAndChild(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
- : base(keySelector, comparer, descending)
- {
- _child = child;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cmp == 0)
- {
- return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
- }
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- await base.SetElement(element, cancellationToken).ConfigureAwait(false);
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- }
- #if !NO_DEEP_CANCELLATION
- internal class AsyncCachingComparerWithTaskAndCancellation<TElement, TKey> : AsyncCachingComparer<TElement>
- {
- protected readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
- protected readonly IComparer<TKey> _comparer;
- protected readonly bool _descending;
- protected TKey _lastKey;
- public AsyncCachingComparerWithTaskAndCancellation(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
- {
- _keySelector = keySelector;
- _comparer = comparer;
- _descending = descending;
- _lastKey = default!;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- _lastKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
- }
- }
- internal sealed class AsyncCachingComparerWithTaskAndCancellationAndChild<TElement, TKey> : AsyncCachingComparerWithTaskAndCancellation<TElement, TKey>
- {
- private readonly AsyncCachingComparer<TElement> _child;
- public AsyncCachingComparerWithTaskAndCancellationAndChild(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
- : base(keySelector, comparer, descending)
- {
- _child = child;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cmp == 0)
- {
- return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
- }
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- await base.SetElement(element, cancellationToken).ConfigureAwait(false);
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- }
- #endif
- #endif // INCLUDE_SYSTEM_LINQ_ASYNCENUMERABLE_DUPLICATES
- }
|