AsyncListPartition.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT License.
  3. // See the LICENSE file in the project root for more information.
  4. // Copied from https://github.com/dotnet/corefx/blob/5f1dd8298e4355b63bb760d88d437a91b3ca808c/src/System.Linq/src/System/Linq/Partition.cs
  5. using System.Collections.Generic;
  6. using System.Diagnostics;
  7. using System.Threading;
  8. using System.Threading.Tasks;
  9. namespace System.Linq
  10. {
  11. /// <summary>
  12. /// An iterator that yields the items of part of an <see cref="IList{TSource}"/>.
  13. /// </summary>
  14. /// <typeparam name="TSource">The type of the source list.</typeparam>
  15. internal sealed class AsyncListPartition<TSource> : AsyncIterator<TSource>, IAsyncPartition<TSource>
  16. {
  17. private readonly IList<TSource> _source;
  18. private readonly int _minIndexInclusive;
  19. private readonly int _maxIndexInclusive;
  20. private int _index;
  21. public AsyncListPartition(IList<TSource> source, int minIndexInclusive, int maxIndexInclusive)
  22. {
  23. Debug.Assert(minIndexInclusive >= 0);
  24. Debug.Assert(minIndexInclusive <= maxIndexInclusive);
  25. _source = source;
  26. _minIndexInclusive = minIndexInclusive;
  27. _maxIndexInclusive = maxIndexInclusive;
  28. _index = 0;
  29. }
  30. public override AsyncIteratorBase<TSource> Clone()
  31. {
  32. return new AsyncListPartition<TSource>(_source, _minIndexInclusive, _maxIndexInclusive);
  33. }
  34. protected override ValueTask<bool> MoveNextCore()
  35. {
  36. if ((uint)_index <= (uint)(_maxIndexInclusive - _minIndexInclusive) && _index < _source.Count - _minIndexInclusive)
  37. {
  38. _current = _source[_minIndexInclusive + _index];
  39. ++_index;
  40. return new ValueTask<bool>(true);
  41. }
  42. return Core();
  43. async ValueTask<bool> Core()
  44. {
  45. await DisposeAsync().ConfigureAwait(false);
  46. return false;
  47. }
  48. }
  49. #if NOT_YET
  50. public override IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector)
  51. {
  52. return new SelectListPartitionIterator<TSource, TResult>(_source, selector, _minIndexInclusive, _maxIndexInclusive);
  53. }
  54. public override IEnumerable<TResult> Select<TResult>(Func<TSource, ValueTask<TResult>> selector)
  55. {
  56. return new SelectListPartitionIterator<TSource, TResult>(_source, selector, _minIndexInclusive, _maxIndexInclusive);
  57. }
  58. #endif
  59. public IAsyncPartition<TSource> Skip(int count)
  60. {
  61. var minIndex = _minIndexInclusive + count;
  62. if ((uint)minIndex > (uint)_maxIndexInclusive)
  63. {
  64. return AsyncEnumerable.EmptyAsyncIterator<TSource>.Instance;
  65. }
  66. else
  67. {
  68. return new AsyncListPartition<TSource>(_source, minIndex, _maxIndexInclusive);
  69. }
  70. }
  71. public IAsyncPartition<TSource> Take(int count)
  72. {
  73. var maxIndex = _minIndexInclusive + count - 1;
  74. if ((uint)maxIndex >= (uint)_maxIndexInclusive)
  75. {
  76. return this;
  77. }
  78. else
  79. {
  80. return new AsyncListPartition<TSource>(_source, _minIndexInclusive, maxIndex);
  81. }
  82. }
  83. public ValueTask<Maybe<TSource>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
  84. {
  85. if ((uint)index <= (uint)(_maxIndexInclusive - _minIndexInclusive) && index < _source.Count - _minIndexInclusive)
  86. {
  87. var res = _source[_minIndexInclusive + index];
  88. return new ValueTask<Maybe<TSource>>(new Maybe<TSource>(res));
  89. }
  90. return new ValueTask<Maybe<TSource>>(new Maybe<TSource>());
  91. }
  92. public ValueTask<Maybe<TSource>> TryGetFirstAsync(CancellationToken cancellationToken)
  93. {
  94. if (_source.Count > _minIndexInclusive)
  95. {
  96. var res = _source[_minIndexInclusive];
  97. return new ValueTask<Maybe<TSource>>(new Maybe<TSource>(res));
  98. }
  99. return new ValueTask<Maybe<TSource>>(new Maybe<TSource>());
  100. }
  101. public ValueTask<Maybe<TSource>> TryGetLastAsync(CancellationToken cancellationToken)
  102. {
  103. var lastIndex = _source.Count - 1;
  104. if (lastIndex >= _minIndexInclusive)
  105. {
  106. var res = _source[Math.Min(lastIndex, _maxIndexInclusive)];
  107. return new ValueTask<Maybe<TSource>>(new Maybe<TSource>(res));
  108. }
  109. return new ValueTask<Maybe<TSource>>(new Maybe<TSource>());
  110. }
  111. private int Count
  112. {
  113. get
  114. {
  115. var count = _source.Count;
  116. if (count <= _minIndexInclusive)
  117. {
  118. return 0;
  119. }
  120. return Math.Min(count - 1, _maxIndexInclusive) - _minIndexInclusive + 1;
  121. }
  122. }
  123. public ValueTask<TSource[]> ToArrayAsync(CancellationToken cancellationToken)
  124. {
  125. var count = Count;
  126. if (count == 0)
  127. {
  128. return new ValueTask<TSource[]>([]);
  129. }
  130. var array = new TSource[count];
  131. for (int i = 0, curIdx = _minIndexInclusive; i != array.Length; ++i, ++curIdx)
  132. {
  133. array[i] = _source[curIdx];
  134. }
  135. return new ValueTask<TSource[]>(array);
  136. }
  137. public ValueTask<List<TSource>> ToListAsync(CancellationToken cancellationToken)
  138. {
  139. var count = Count;
  140. if (count == 0)
  141. {
  142. return new ValueTask<List<TSource>>([]);
  143. }
  144. var list = new List<TSource>(count);
  145. var end = _minIndexInclusive + count;
  146. for (var i = _minIndexInclusive; i != end; ++i)
  147. {
  148. list.Add(_source[i]);
  149. }
  150. return new ValueTask<List<TSource>>(list);
  151. }
  152. public ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
  153. {
  154. return new ValueTask<int>(Count);
  155. }
  156. }
  157. }