// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. // Copied from https://github.com/dotnet/corefx/blob/5f1dd8298e4355b63bb760d88d437a91b3ca808c/src/System.Linq/src/System/Linq/Partition.cs using System.Collections.Generic; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; namespace System.Linq { /// /// An iterator that yields the items of part of an . /// /// The type of the source list. internal sealed class AsyncListPartition : AsyncIterator, IAsyncPartition { private readonly IList _source; private readonly int _minIndexInclusive; private readonly int _maxIndexInclusive; private int _index; public AsyncListPartition(IList source, int minIndexInclusive, int maxIndexInclusive) { Debug.Assert(source != null); Debug.Assert(minIndexInclusive >= 0); Debug.Assert(minIndexInclusive <= maxIndexInclusive); _source = source; _minIndexInclusive = minIndexInclusive; _maxIndexInclusive = maxIndexInclusive; _index = 0; } public override AsyncIterator Clone() { return new AsyncListPartition(_source, _minIndexInclusive, _maxIndexInclusive); } protected override async ValueTask MoveNextCore() { if ((uint)_index <= (uint)(_maxIndexInclusive - _minIndexInclusive) && _index < _source.Count - _minIndexInclusive) { _current = _source[_minIndexInclusive + _index]; ++_index; return true; } await DisposeAsync().ConfigureAwait(false); return false; } #if NOT_YET public override IEnumerable Select(Func selector) { return new SelectListPartitionIterator(_source, selector, _minIndexInclusive, _maxIndexInclusive); } public override IEnumerable Select(Func> selector) { return new SelectListPartitionIterator(_source, selector, _minIndexInclusive, _maxIndexInclusive); } #endif public IAsyncPartition Skip(int count) { var minIndex = _minIndexInclusive + count; if ((uint)minIndex > (uint)_maxIndexInclusive) { return AsyncEnumerable.EmptyAsyncIterator.Instance; } else { return new AsyncListPartition(_source, minIndex, _maxIndexInclusive); } } public IAsyncPartition Take(int count) { var maxIndex = _minIndexInclusive + count - 1; if ((uint)maxIndex >= (uint)_maxIndexInclusive) { return this; } else { return new AsyncListPartition(_source, _minIndexInclusive, maxIndex); } } public Task> TryGetElementAsync(int index, CancellationToken cancellationToken) { if ((uint)index <= (uint)(_maxIndexInclusive - _minIndexInclusive) && index < _source.Count - _minIndexInclusive) { var res = _source[_minIndexInclusive + index]; return Task.FromResult(new Maybe(res)); } return Task.FromResult(new Maybe()); } public Task> TryGetFirstAsync(CancellationToken cancellationToken) { if (_source.Count > _minIndexInclusive) { var res = _source[_minIndexInclusive]; return Task.FromResult(new Maybe(res)); } return Task.FromResult(new Maybe()); } public Task> TryGetLastAsync(CancellationToken cancellationToken) { var lastIndex = _source.Count - 1; if (lastIndex >= _minIndexInclusive) { var res = _source[Math.Min(lastIndex, _maxIndexInclusive)]; return Task.FromResult(new Maybe(res)); } return Task.FromResult(new Maybe()); } private int Count { get { var count = _source.Count; if (count <= _minIndexInclusive) { return 0; } return Math.Min(count - 1, _maxIndexInclusive) - _minIndexInclusive + 1; } } public Task ToArrayAsync(CancellationToken cancellationToken) { var count = Count; if (count == 0) { return Task.FromResult( #if NO_ARRAY_EMPTY EmptyArray.Value #else Array.Empty() #endif ); } var array = new TSource[count]; for (int i = 0, curIdx = _minIndexInclusive; i != array.Length; ++i, ++curIdx) { array[i] = _source[curIdx]; } return Task.FromResult(array); } public Task> ToListAsync(CancellationToken cancellationToken) { var count = Count; if (count == 0) { return Task.FromResult(new List()); } var list = new List(count); var end = _minIndexInclusive + count; for (var i = _minIndexInclusive; i != end; ++i) { list.Add(_source[i]); } return Task.FromResult(list); } public Task GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) { return Task.FromResult(Count); } } }