using Cysharp.Threading.Tasks.Internal; using System; using System.Collections.Generic; using System.Threading; namespace Cysharp.Threading.Tasks.Linq { public static partial class UniTaskAsyncEnumerable { public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); return Aggregate.AggregateAsync(source, accumulator, cancellationToken); } public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); return Aggregate.AggregateAsync(source, seed, accumulator, cancellationToken); } public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); return Aggregate.AggregateAsync(source, seed, accumulator, resultSelector, cancellationToken); } public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); return Aggregate.AggregateAwaitAsync(source, accumulator, cancellationToken); } public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); return Aggregate.AggregateAwaitAsync(source, seed, accumulator, cancellationToken); } public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); return Aggregate.AggregateAwaitAsync(source, seed, accumulator, resultSelector, cancellationToken); } public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); return Aggregate.AggregateAwaitWithCancellationAsync(source, accumulator, cancellationToken); } public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); return Aggregate.AggregateAwaitWithCancellationAsync(source, seed, accumulator, cancellationToken); } public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); return Aggregate.AggregateAwaitWithCancellationAsync(source, seed, accumulator, resultSelector, cancellationToken); } } internal static class Aggregate { internal static async UniTask AggregateAsync(IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TSource value; if (await e.MoveNextAsync()) { value = e.Current; } else { throw Error.NoElements(); } while (await e.MoveNextAsync()) { value = accumulator(value, e.Current); } return value; } finally { if (e != null) { await e.DisposeAsync(); } } } internal static async UniTask AggregateAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TAccumulate value = seed; while (await e.MoveNextAsync()) { value = accumulator(value, e.Current); } return value; } finally { if (e != null) { await e.DisposeAsync(); } } } internal static async UniTask AggregateAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TAccumulate value = seed; while (await e.MoveNextAsync()) { value = accumulator(value, e.Current); } return resultSelector(value); } finally { if (e != null) { await e.DisposeAsync(); } } } // with async internal static async UniTask AggregateAwaitAsync(IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TSource value; if (await e.MoveNextAsync()) { value = e.Current; } else { throw Error.NoElements(); } while (await e.MoveNextAsync()) { value = await accumulator(value, e.Current); } return value; } finally { if (e != null) { await e.DisposeAsync(); } } } internal static async UniTask AggregateAwaitAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TAccumulate value = seed; while (await e.MoveNextAsync()) { value = await accumulator(value, e.Current); } return value; } finally { if (e != null) { await e.DisposeAsync(); } } } internal static async UniTask AggregateAwaitAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TAccumulate value = seed; while (await e.MoveNextAsync()) { value = await accumulator(value, e.Current); } return await resultSelector(value); } finally { if (e != null) { await e.DisposeAsync(); } } } // with cancellation internal static async UniTask AggregateAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TSource value; if (await e.MoveNextAsync()) { value = e.Current; } else { throw Error.NoElements(); } while (await e.MoveNextAsync()) { value = await accumulator(value, e.Current, cancellationToken); } return value; } finally { if (e != null) { await e.DisposeAsync(); } } } internal static async UniTask AggregateAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TAccumulate value = seed; while (await e.MoveNextAsync()) { value = await accumulator(value, e.Current, cancellationToken); } return value; } finally { if (e != null) { await e.DisposeAsync(); } } } internal static async UniTask AggregateAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try { TAccumulate value = seed; while (await e.MoveNextAsync()) { value = await accumulator(value, e.Current, cancellationToken); } return await resultSelector(value, cancellationToken); } finally { if (e != null) { await e.DisposeAsync(); } } } } }