using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; namespace SharpCompress; public static class AsyncEnumerableEx { public static async IAsyncEnumerable Empty() where T : notnull { await Task.CompletedTask; yield break; } } public static class EnumerableExtensions { public static async IAsyncEnumerable ToAsyncEnumerable(this IEnumerable source) { await Task.CompletedTask; foreach (var item in source) { yield return item; } } } public static class AsyncEnumerableExtensions { public static async IAsyncEnumerable Select( this IAsyncEnumerable source, Func selector) { await foreach (var element in source) { yield return selector(element); } } public static async ValueTask CountAsync( this IAsyncEnumerable source, CancellationToken cancellationToken = default) { await using var e = source.GetAsyncEnumerator(cancellationToken); var count = 0; while (await e.MoveNextAsync()) { checked { count++; } } return count; } public static async IAsyncEnumerable TakeAsync( this IAsyncEnumerable source, int count) { await foreach (var element in source) { yield return element; if (--count == 0) { break; } } } public static async ValueTask> ToListAsync(this IAsyncEnumerable source) { var list = new List(); await foreach (var item in source) { list.Add(item); } return list; } public static async IAsyncEnumerable CastAsync( this IAsyncEnumerable source ) where TResult : class { await foreach (var item in source) { yield return (item as TResult).NotNull(); } } public static async ValueTask AggregateAsync( this IAsyncEnumerable source, TAccumulate seed, Func func ) { TAccumulate result = seed; await foreach (var element in source) { result = func(result, element); } return result; } public static async ValueTask AllAsync( this IAsyncEnumerable source, Func predicate ) { await foreach (var item in source) { if (!predicate(item)) { return false; } } return true; } public static IAsyncEnumerable Where( this IAsyncEnumerable source, Func predicate ) { return WhereIterator(source, predicate); } private static async IAsyncEnumerable WhereIterator( IAsyncEnumerable source, Func predicate ) { await foreach (var item in source) { if (predicate(item)) { yield return item; } } } public static async IAsyncEnumerable WhereAsync( this IAsyncEnumerable source, Func predicate ) { await foreach (var item in source) { if (predicate(item)) { yield return item; } } } public static async ValueTask SingleAsync( this IAsyncEnumerable source, Func? predicate = null ) { IAsyncEnumerator enumerator; if (predicate is null) { enumerator = source.GetAsyncEnumerator(); } else { enumerator = source.WhereAsync(predicate).GetAsyncEnumerator(); } if (!await enumerator.MoveNextAsync()) { throw new InvalidOperationException("The source sequence is empty."); } var value = enumerator.Current; if (await enumerator.MoveNextAsync()) { throw new InvalidOperationException( "The source sequence contains more than one element." ); } return value; } public static async ValueTask FirstAsync(this IAsyncEnumerable source) { await foreach (var item in source) { return item; } throw new InvalidOperationException("The source sequence is empty."); } public static async ValueTask FirstOrDefaultAsync(this IAsyncEnumerable source) { await foreach (var item in source) { return item; } return default; } }