Reverse.cs 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. using Cysharp.Threading.Tasks.Internal;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Threading;
  5. namespace Cysharp.Threading.Tasks.Linq
  6. {
  7. public static partial class UniTaskAsyncEnumerable
  8. {
  9. public static IUniTaskAsyncEnumerable<TSource> Reverse<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
  10. {
  11. Error.ThrowArgumentNullException(source, nameof(source));
  12. return new Reverse<TSource>(source);
  13. }
  14. }
  15. internal sealed class Reverse<TSource> : IUniTaskAsyncEnumerable<TSource>
  16. {
  17. readonly IUniTaskAsyncEnumerable<TSource> source;
  18. public Reverse(IUniTaskAsyncEnumerable<TSource> source)
  19. {
  20. this.source = source;
  21. }
  22. public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
  23. {
  24. return new _Reverse(source, cancellationToken);
  25. }
  26. sealed class _Reverse : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
  27. {
  28. readonly IUniTaskAsyncEnumerable<TSource> source;
  29. CancellationToken cancellationToken;
  30. TSource[] array;
  31. int index;
  32. public _Reverse(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
  33. {
  34. this.source = source;
  35. this.cancellationToken = cancellationToken;
  36. TaskTracker.TrackActiveTask(this, 3);
  37. }
  38. public TSource Current { get; private set; }
  39. // after consumed array, don't use await so allow async(not require UniTaskCompletionSourceCore).
  40. public async UniTask<bool> MoveNextAsync()
  41. {
  42. cancellationToken.ThrowIfCancellationRequested();
  43. if (array == null)
  44. {
  45. array = await source.ToArrayAsync(cancellationToken);
  46. index = array.Length - 1;
  47. }
  48. if (index != -1)
  49. {
  50. Current = array[index];
  51. --index;
  52. return true;
  53. }
  54. else
  55. {
  56. return false;
  57. }
  58. }
  59. public UniTask DisposeAsync()
  60. {
  61. TaskTracker.RemoveTracking(this);
  62. return default;
  63. }
  64. }
  65. }
  66. }