Files
sharpcompress/src/SharpCompress/Polyfills/AsyncEnumerableExtensions.cs

208 lines
4.9 KiB
C#
Raw Normal View History

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