ToArray.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. using Cysharp.Threading.Tasks.Internal;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. namespace Cysharp.Threading.Tasks.Linq
  6. {
  7. public static partial class UniTaskAsyncEnumerable
  8. {
  9. public static UniTask<TSource[]> ToArrayAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
  10. {
  11. Error.ThrowArgumentNullException(source, nameof(source));
  12. return Cysharp.Threading.Tasks.Linq.ToArray.ToArrayAsync(source, cancellationToken);
  13. }
  14. }
  15. internal static class ToArray
  16. {
  17. internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
  18. {
  19. var pool = ArrayPool<TSource>.Shared;
  20. var array = pool.Rent(16);
  21. TSource[] result = default;
  22. IUniTaskAsyncEnumerator<TSource> e = default;
  23. try
  24. {
  25. e = source.GetAsyncEnumerator(cancellationToken);
  26. var i = 0;
  27. while (await e.MoveNextAsync())
  28. {
  29. ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
  30. array[i++] = e.Current;
  31. }
  32. if (i == 0)
  33. {
  34. result = Array.Empty<TSource>();
  35. }
  36. else
  37. {
  38. result = new TSource[i];
  39. Array.Copy(array, result, i);
  40. }
  41. }
  42. finally
  43. {
  44. pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
  45. if (e != null)
  46. {
  47. await e.DisposeAsync();
  48. }
  49. }
  50. return result;
  51. }
  52. }
  53. }