move to underunity

This commit is contained in:
neuecc
2020-05-12 03:48:32 +09:00
parent cda59ba9c2
commit c23b9ca480
130 changed files with 705 additions and 56 deletions

View File

@@ -1,85 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;
namespace Cysharp.Threading.Tasks
{
public interface IUniTaskAsyncEnumerable<out T>
{
IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default);
}
public interface IUniTaskAsyncEnumerator<out T> : IUniTaskAsyncDisposable
{
T Current { get; }
UniTask<bool> MoveNextAsync();
}
public interface IUniTaskAsyncDisposable
{
UniTask DisposeAsync();
}
public interface IUniTaskOrderedAsyncEnumerable<TElement> : IUniTaskAsyncEnumerable<TElement>
{
IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending);
IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending);
}
//public interface IUniTaskAsyncGrouping<out TKey, out TElement> : IUniTaskAsyncEnumerable<TElement>
//{
// TKey Key { get; }
//}
public static class UniTaskAsyncEnumerableExtensions
{
public static UniTaskCancelableAsyncEnumerable<T> WithCancellation<T>(this IUniTaskAsyncEnumerable<T> source, CancellationToken cancellationToken)
{
return new UniTaskCancelableAsyncEnumerable<T>(source, cancellationToken);
}
}
[StructLayout(LayoutKind.Auto)]
public readonly struct UniTaskCancelableAsyncEnumerable<T>
{
private readonly IUniTaskAsyncEnumerable<T> enumerable;
private readonly CancellationToken cancellationToken;
internal UniTaskCancelableAsyncEnumerable(IUniTaskAsyncEnumerable<T> enumerable, CancellationToken cancellationToken)
{
this.enumerable = enumerable;
this.cancellationToken = cancellationToken;
}
public Enumerator GetAsyncEnumerator()
{
return new Enumerator(enumerable.GetAsyncEnumerator(cancellationToken));
}
[StructLayout(LayoutKind.Auto)]
public readonly struct Enumerator
{
private readonly IUniTaskAsyncEnumerator<T> enumerator;
internal Enumerator(IUniTaskAsyncEnumerator<T> enumerator)
{
this.enumerator = enumerator;
}
public T Current => enumerator.Current;
public UniTask<bool> MoveNextAsync()
{
return enumerator.MoveNextAsync();
}
public UniTask DisposeAsync()
{
return enumerator.DisposeAsync();
}
}
}
}

View File

@@ -1,318 +0,0 @@
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<TSource> AggregateAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
return Aggregate.InvokeAsync(source, accumulator, cancellationToken);
}
public static UniTask<TAccumulate> AggregateAsync<TSource, TAccumulate>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken);
}
public static UniTask<TResult> AggregateAsync<TSource, TAccumulate, TResult>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> resultSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
Error.ThrowArgumentNullException(accumulator, nameof(resultSelector));
return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken);
}
public static UniTask<TSource> AggregateAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, UniTask<TSource>> accumulator, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
return Aggregate.InvokeAsync(source, accumulator, cancellationToken);
}
public static UniTask<TAccumulate> AggregateAwaitAsync<TSource, TAccumulate>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken);
}
public static UniTask<TResult> AggregateAwaitAsync<TSource, TAccumulate, TResult>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, Func<TAccumulate, UniTask<TResult>> resultSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
Error.ThrowArgumentNullException(accumulator, nameof(resultSelector));
return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken);
}
public static UniTask<TSource> AggregateAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, CancellationToken, UniTask<TSource>> accumulator, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
return Aggregate.InvokeAsync(source, accumulator, cancellationToken);
}
public static UniTask<TAccumulate> AggregateAwaitWithCancellationAsync<TSource, TAccumulate>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken);
}
public static UniTask<TResult> AggregateAwaitWithCancellationAsync<TSource, TAccumulate, TResult>(this IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, Func<TAccumulate, CancellationToken, UniTask<TResult>> resultSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(accumulator, nameof(accumulator));
Error.ThrowArgumentNullException(accumulator, nameof(resultSelector));
return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken);
}
}
internal static class Aggregate
{
internal static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, TSource> 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<TAccumulate> InvokeAsync<TSource, TAccumulate>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> 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<TResult> InvokeAsync<TSource, TAccumulate, TResult>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator, Func<TAccumulate, TResult> 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<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, UniTask<TSource>> 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<TAccumulate> InvokeAsync<TSource, TAccumulate>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> 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<TResult> InvokeAsync<TSource, TAccumulate, TResult>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, UniTask<TAccumulate>> accumulator, Func<TAccumulate, UniTask<TResult>> 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<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TSource, CancellationToken, UniTask<TSource>> 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<TAccumulate> InvokeAsync<TSource, TAccumulate>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> 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<TResult> InvokeAsync<TSource, TAccumulate, TResult>(IUniTaskAsyncEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, CancellationToken, UniTask<TAccumulate>> accumulator, Func<TAccumulate, CancellationToken, UniTask<TResult>> 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();
}
}
}
}
}

View File

@@ -1,108 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<Boolean> AllAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return All.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<Boolean> AllAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return All.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<Boolean> AllAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return All.InvokeAsync(source, predicate, cancellationToken);
}
}
internal static class All
{
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (!predicate(e.Current))
{
return false;
}
}
return true;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (!await predicate(e.Current))
{
return false;
}
}
return true;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (!await predicate(e.Current, cancellationToken))
{
return false;
}
}
return true;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,136 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<Boolean> AnyAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Any.InvokeAsync(source, cancellationToken);
}
public static UniTask<Boolean> AnyAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Any.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<Boolean> AnyAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Any.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<Boolean> AnyAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Any.InvokeAsync(source, predicate, cancellationToken);
}
}
internal static class Any
{
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
if (await e.MoveNextAsync())
{
return true;
}
return false;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (predicate(e.Current))
{
return true;
}
}
return false;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (await predicate(e.Current))
{
return true;
}
}
return false;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (await predicate(e.Current, cancellationToken))
{
return true;
}
}
return false;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,148 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Append<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource element)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new AppendPrepend<TSource>(source, element, true);
}
public static IUniTaskAsyncEnumerable<TSource> Prepend<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource element)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new AppendPrepend<TSource>(source, element, true);
}
}
internal sealed class AppendPrepend<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly TSource element;
readonly bool append; // or prepend
public AppendPrepend(IUniTaskAsyncEnumerable<TSource> source, TSource element, bool append)
{
this.source = source;
this.element = element;
this.append = append;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, element, append, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
enum State : byte
{
None,
RequirePrepend,
RequireAppend,
Completed
}
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly TSource element;
CancellationToken cancellationToken;
State state;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, TSource element, bool append, CancellationToken cancellationToken)
{
this.source = source;
this.element = element;
this.state = append ? State.RequireAppend : State.RequirePrepend;
this.cancellationToken = cancellationToken;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (enumerator == null)
{
if (state == State.RequireAppend)
{
Current = element;
state = State.None;
return CompletedTasks.True;
}
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
if (state == State.Completed)
{
return CompletedTasks.False;
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
MoveNextCoreDelegate(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
if (self.state == State.RequireAppend)
{
self.state = State.Completed;
self.Current = self.element;
self.completionSource.TrySetResult(true);
}
else
{
self.state = State.Completed;
self.completionSource.TrySetResult(false);
}
}
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,10 +0,0 @@
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> AsUniTaskAsyncEnumerable<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
return source;
}
}
}

View File

@@ -1,410 +0,0 @@
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public abstract class MoveNextSource : IUniTaskSource<bool>
{
protected UniTaskCompletionSourceCore<bool> completionSource;
public bool GetResult(short token)
{
return completionSource.GetResult(token);
}
public UniTaskStatus GetStatus(short token)
{
return completionSource.GetStatus(token);
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
completionSource.OnCompleted(continuation, state, token);
}
public UniTaskStatus UnsafeGetStatus()
{
return completionSource.UnsafeGetStatus();
}
void IUniTaskSource.GetResult(short token)
{
completionSource.GetResult(token);
}
protected bool TryGetResult<T>(UniTask<T>.Awaiter awaiter, out T result)
{
try
{
result = awaiter.GetResult();
return true;
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
result = default;
return false;
}
}
protected bool TryGetResult(UniTask.Awaiter awaiter)
{
try
{
awaiter.GetResult();
return true;
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return false;
}
}
}
public abstract class AsyncEnumeratorBase<TSource, TResult> : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> moveNextCallbackDelegate = MoveNextCallBack;
readonly IUniTaskAsyncEnumerable<TSource> source;
protected CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter sourceMoveNext;
public AsyncEnumeratorBase(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
this.source = source;
this.cancellationToken = cancellationToken;
}
// abstract
/// <summary>
/// If return value is false, continue source.MoveNext.
/// </summary>
protected abstract bool TryMoveNextCore(bool sourceHasCurrent, out bool result);
// Util
protected TSource SourceCurrent => enumerator.Current;
// IUniTaskAsyncEnumerator<T>
public TResult Current { get; protected set; }
public UniTask<bool> MoveNextAsync()
{
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
completionSource.Reset();
if (!OnFirstIteration())
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
protected virtual bool OnFirstIteration()
{
return false;
}
protected void SourceMoveNext()
{
CONTINUE:
sourceMoveNext = enumerator.MoveNextAsync().GetAwaiter();
if (sourceMoveNext.IsCompleted)
{
bool result = false;
try
{
if (!TryMoveNextCore(sourceMoveNext.GetResult(), out result))
{
goto CONTINUE;
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (cancellationToken.IsCancellationRequested)
{
completionSource.TrySetCanceled(cancellationToken);
}
else
{
completionSource.TrySetResult(result);
}
}
else
{
sourceMoveNext.SourceOnCompleted(moveNextCallbackDelegate, this);
}
}
static void MoveNextCallBack(object state)
{
var self = (AsyncEnumeratorBase<TSource, TResult>)state;
bool result;
try
{
if (!self.TryMoveNextCore(self.sourceMoveNext.GetResult(), out result))
{
self.SourceMoveNext();
return;
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(result);
}
}
// if require additional resource to dispose, override and call base.DisposeAsync.
public virtual UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
public abstract class AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait> : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> moveNextCallbackDelegate = MoveNextCallBack;
static readonly Action<object> setCurrentCallbackDelegate = SetCurrentCallBack;
readonly IUniTaskAsyncEnumerable<TSource> source;
protected CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter sourceMoveNext;
UniTask<TAwait>.Awaiter resultAwaiter;
public AsyncEnumeratorAwaitSelectorBase(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
this.source = source;
this.cancellationToken = cancellationToken;
}
// abstract
protected abstract UniTask<TAwait> TransformAsync(TSource sourceCurrent);
protected abstract bool TrySetCurrentCore(TAwait awaitResult, out bool terminateIteration);
// Util
protected TSource SourceCurrent { get; private set; }
protected (bool waitCallback, bool requireNextIteration) ActionCompleted(bool trySetCurrentResult, out bool moveNextResult)
{
if (trySetCurrentResult)
{
moveNextResult = true;
return (false, false);
}
else
{
moveNextResult = default;
return (false, true);
}
}
protected (bool waitCallback, bool requireNextIteration) WaitAwaitCallback(out bool moveNextResult) { moveNextResult = default; return (true, false); }
protected (bool waitCallback, bool requireNextIteration) IterateFinished(out bool moveNextResult) { moveNextResult = false; return (false, false); }
// IUniTaskAsyncEnumerator<T>
public TResult Current { get; protected set; }
public UniTask<bool> MoveNextAsync()
{
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
protected void SourceMoveNext()
{
CONTINUE:
sourceMoveNext = enumerator.MoveNextAsync().GetAwaiter();
if (sourceMoveNext.IsCompleted)
{
bool result = false;
try
{
(bool waitCallback, bool requireNextIteration) = TryMoveNextCore(sourceMoveNext.GetResult(), out result);
if (waitCallback)
{
return;
}
if (requireNextIteration)
{
goto CONTINUE;
}
else
{
completionSource.TrySetResult(result);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
else
{
sourceMoveNext.SourceOnCompleted(moveNextCallbackDelegate, this);
}
}
(bool waitCallback, bool requireNextIteration) TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
SourceCurrent = enumerator.Current;
var task = TransformAsync(SourceCurrent);
if (UnwarapTask(task, out var taskResult))
{
var currentResult = TrySetCurrentCore(taskResult, out var terminateIteration);
if (terminateIteration)
{
return IterateFinished(out result);
}
return ActionCompleted(currentResult, out result);
}
else
{
return WaitAwaitCallback(out result);
}
}
return IterateFinished(out result);
}
protected bool UnwarapTask(UniTask<TAwait> taskResult, out TAwait result)
{
resultAwaiter = taskResult.GetAwaiter();
if (resultAwaiter.IsCompleted)
{
result = resultAwaiter.GetResult();
return true;
}
else
{
resultAwaiter.SourceOnCompleted(setCurrentCallbackDelegate, this);
result = default;
return false;
}
}
static void MoveNextCallBack(object state)
{
var self = (AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait>)state;
bool result = false;
try
{
(bool waitCallback, bool requireNextIteration) = self.TryMoveNextCore(self.sourceMoveNext.GetResult(), out result);
if (waitCallback)
{
return;
}
if (requireNextIteration)
{
self.SourceMoveNext();
return;
}
else
{
self.completionSource.TrySetResult(result);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
}
static void SetCurrentCallBack(object state)
{
var self = (AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait>)state;
bool doneSetCurrent;
bool terminateIteration;
try
{
var result = self.resultAwaiter.GetResult();
doneSetCurrent = self.TrySetCurrentCore(result, out terminateIteration);
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
if (doneSetCurrent)
{
self.completionSource.TrySetResult(true);
}
else
{
if (terminateIteration)
{
self.completionSource.TrySetResult(false);
}
else
{
self.SourceMoveNext();
}
}
}
}
// if require additional resource to dispose, override and call base.DisposeAsync.
public virtual UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,237 +0,0 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new[]
{
(typeof(int), "double"),
(typeof(long), "double"),
(typeof(float),"float"),
(typeof(double),"double"),
(typeof(decimal),"decimal"),
(typeof(int?),"double?"),
(typeof(long?),"double?"),
(typeof(float?),"float?"),
(typeof(double?),"double?"),
(typeof(decimal?),"decimal?"),
};
Func<Type, bool> IsNullable = x => x.IsGenericType;
Func<Type, Type> ElementType = x => IsNullable(x) ? x.GetGenericArguments()[0] : x;
Func<Type, string> TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name;
Func<Type, string> WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : "";
Func<Type, string> CalcResult = x => { var e = ElementType(x); return (e == typeof(int) || e == typeof(long)) ? "(double)sum / count" : (e == typeof(float)) ? "(float)(sum / count)" : "sum / count"; };
#>
using System;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
<# foreach(var (t, ret) in types) { #>
public static UniTask<<#= ret #>> AverageAsync(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Average.InvokeAsync(source, cancellationToken);
}
public static UniTask<<#= ret #>> AverageAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Average.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<<#= ret #>> AverageAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Average.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<<#= ret #>> AverageAwaitCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Average.InvokeAsync(source, selector, cancellationToken);
}
<# } #>
}
internal static class Average
{
<# foreach(var (t, ret) in types) { #>
public static async UniTask<<#= ret #>> InvokeAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = e.Current;
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += e.Current;
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
public static async UniTask<<#= ret #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = selector(e.Current);
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += selector(e.Current);
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
public static async UniTask<<#= ret #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = await selector(e.Current);
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += await selector(e.Current);
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
public static async UniTask<<#= ret #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
long count = 0;
<#= TypeName(t) #> sum = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
<# if (IsNullable(t)) { #>
var v = await selector(e.Current, cancellationToken);
if (v.HasValue)
{
checked
{
sum += v.Value;
count++;
}
}
<# } else { #>
checked
{
sum += await selector(e.Current, cancellationToken);
count++;
}
<# } #>
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return <#= CalcResult(t) #>;
}
<# } #>
}
}

View File

@@ -1,340 +0,0 @@
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 IUniTaskAsyncEnumerable<IList<TSource>> Buffer<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
if (count <= 0) throw Error.ArgumentOutOfRange(nameof(count));
return new Buffer<TSource>(source, count);
}
public static IUniTaskAsyncEnumerable<IList<TSource>> Buffer<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count, Int32 skip)
{
Error.ThrowArgumentNullException(source, nameof(source));
if (count <= 0) throw Error.ArgumentOutOfRange(nameof(count));
if (skip <= 0) throw Error.ArgumentOutOfRange(nameof(skip));
return new BufferSkip<TSource>(source, count, skip);
}
}
internal sealed class Buffer<TSource> : IUniTaskAsyncEnumerable<IList<TSource>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public Buffer(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<IList<TSource>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<IList<TSource>>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
bool continueNext;
bool completed;
List<TSource> buffer;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
{
this.source = source;
this.count = count;
this.cancellationToken = cancellationToken;
}
public IList<TSource> Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
buffer = new List<TSource>(count);
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
void SourceMoveNext()
{
if (completed)
{
if (buffer != null && buffer.Count > 0)
{
var ret = buffer;
buffer = null;
Current = ret;
completionSource.TrySetResult(true);
return;
}
else
{
completionSource.TrySetResult(false);
return;
}
}
try
{
LOOP:
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.buffer.Add(self.enumerator.Current);
if (self.buffer.Count == self.count)
{
self.Current = self.buffer;
self.buffer = new List<TSource>(self.count);
self.continueNext = false;
self.completionSource.TrySetResult(true);
return;
}
else
{
if (!self.continueNext)
{
self.SourceMoveNext();
}
}
}
else
{
self.continueNext = false;
self.completed = true;
self.SourceMoveNext();
}
}
else
{
self.continueNext = false;
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
internal sealed class BufferSkip<TSource> : IUniTaskAsyncEnumerable<IList<TSource>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
readonly int skip;
public BufferSkip(IUniTaskAsyncEnumerable<TSource> source, int count, int skip)
{
this.source = source;
this.count = count;
this.skip = skip;
}
public IUniTaskAsyncEnumerator<IList<TSource>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, skip, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<IList<TSource>>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
readonly int skip;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
bool continueNext;
bool completed;
Queue<List<TSource>> buffers;
int index = 0;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, int skip, CancellationToken cancellationToken)
{
this.source = source;
this.count = count;
this.skip = skip;
this.cancellationToken = cancellationToken;
}
public IList<TSource> Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
buffers = new Queue<List<TSource>>();
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
void SourceMoveNext()
{
if (completed)
{
if (buffers.Count > 0)
{
Current = buffers.Dequeue();
completionSource.TrySetResult(true);
return;
}
else
{
completionSource.TrySetResult(false);
return;
}
}
try
{
LOOP:
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
if (self.index++ % self.skip == 0)
{
self.buffers.Enqueue(new List<TSource>(self.count));
}
var item = self.enumerator.Current;
foreach (var buffer in self.buffers)
{
buffer.Add(item);
}
if (self.buffers.Count > 0 && self.buffers.Peek().Count == self.count)
{
self.Current = self.buffers.Dequeue();
self.continueNext = false;
self.completionSource.TrySetResult(true);
return;
}
else
{
if (!self.continueNext)
{
self.SourceMoveNext();
}
}
}
else
{
self.continueNext = false;
self.completed = true;
self.SourceMoveNext();
}
}
else
{
self.continueNext = false;
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,53 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> Cast<TResult>(this IUniTaskAsyncEnumerable<Object> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Cast<TResult>(source);
}
}
internal sealed class Cast<TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<object> source;
public Cast(IUniTaskAsyncEnumerable<object> source)
{
this.source = source;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<object, TResult>
{
public Enumerator(IUniTaskAsyncEnumerable<object> source, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
Current = (TResult)SourceCurrent;
result = true;
return true;
}
result = false;
return true;
}
}
}
}

View File

@@ -1,162 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Concat<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
return new Concat<TSource>(first, second);
}
}
internal sealed class Concat<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> first;
readonly IUniTaskAsyncEnumerable<TSource> second;
public Concat(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second)
{
this.first = first;
this.second = second;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
enum IteratingState
{
IteratingFirst,
IteratingSecond,
Complete
}
readonly IUniTaskAsyncEnumerable<TSource> first;
readonly IUniTaskAsyncEnumerable<TSource> second;
CancellationToken cancellationToken;
IteratingState iteratingState;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, CancellationToken cancellationToken)
{
this.first = first;
this.second = second;
this.cancellationToken = cancellationToken;
this.iteratingState = IteratingState.IteratingFirst;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (iteratingState == IteratingState.Complete) return CompletedTasks.False;
completionSource.Reset();
StartIterate();
return new UniTask<bool>(this, completionSource.Version);
}
void StartIterate()
{
if (enumerator == null)
{
if (iteratingState == IteratingState.IteratingFirst)
{
enumerator = first.GetAsyncEnumerator(cancellationToken);
}
else if (iteratingState == IteratingState.IteratingSecond)
{
enumerator = second.GetAsyncEnumerator(cancellationToken);
}
}
try
{
awaiter = enumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (awaiter.IsCompleted)
{
MoveNextCoreDelegate(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
if (self.iteratingState == IteratingState.IteratingFirst)
{
self.RunSecondAfterDisposeAsync().Forget();
return;
}
self.iteratingState = IteratingState.Complete;
self.completionSource.TrySetResult(false);
}
}
}
async UniTaskVoid RunSecondAfterDisposeAsync()
{
try
{
await enumerator.DisposeAsync();
enumerator = null;
awaiter = default;
iteratingState = IteratingState.IteratingSecond;
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
StartIterate();
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,50 +0,0 @@
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<Boolean> ContainsAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource value, CancellationToken cancellationToken = default)
{
return ContainsAsync(source, value, EqualityComparer<TSource>.Default, cancellationToken);
}
public static UniTask<Boolean> ContainsAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return Contains.InvokeAsync(source, value, comparer, cancellationToken);
}
}
internal static class Contains
{
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (comparer.Equals(value, e.Current))
{
return true;
}
}
return false;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,144 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<Int32> CountAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Count.InvokeAsync(source, cancellationToken);
}
public static UniTask<Int32> CountAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Count.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<Int32> CountAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Count.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<Int32> CountAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Count.InvokeAsync(source, predicate, cancellationToken);
}
}
internal static class Count
{
internal static async UniTask<int> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
var count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
checked { count++; }
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
internal static async UniTask<int> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken)
{
var count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (predicate(e.Current))
{
checked { count++; }
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
internal static async UniTask<int> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
var count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (await predicate(e.Current))
{
checked { count++; }
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
internal static async UniTask<int> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
var count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (await predicate(e.Current, cancellationToken))
{
checked { count++; }
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
}
}

View File

@@ -1,140 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new DefaultIfEmpty<TSource>(source, default);
}
public static IUniTaskAsyncEnumerable<TSource> DefaultIfEmpty<TSource>(this IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new DefaultIfEmpty<TSource>(source, defaultValue);
}
}
internal sealed class DefaultIfEmpty<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly TSource defaultValue;
public DefaultIfEmpty(IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue)
{
this.source = source;
this.defaultValue = defaultValue;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, defaultValue, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
enum IteratingState : byte
{
Empty,
Iterating,
Completed
}
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly TSource defaultValue;
CancellationToken cancellationToken;
IteratingState iteratingState;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue, CancellationToken cancellationToken)
{
this.source = source;
this.defaultValue = defaultValue;
this.cancellationToken = cancellationToken;
this.iteratingState = IteratingState.Empty;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (iteratingState == IteratingState.Completed)
{
return CompletedTasks.False;
}
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.iteratingState = IteratingState.Iterating;
self.Current = self.enumerator.Current;
self.completionSource.TrySetResult(true);
}
else
{
if (self.iteratingState == IteratingState.Empty)
{
self.iteratingState = IteratingState.Completed;
self.Current = self.defaultValue;
self.completionSource.TrySetResult(true);
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,277 +0,0 @@
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 IUniTaskAsyncEnumerable<TSource> Distinct<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
return Distinct(source, EqualityComparer<TSource>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> Distinct<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new Distinct<TSource>(source, comparer);
}
public static IUniTaskAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return Distinct(source, keySelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> Distinct<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new Distinct<TSource, TKey>(source, keySelector, comparer);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
return DistinctAwait(source, keySelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new DistinctAwait<TSource, TKey>(source, keySelector, comparer);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
return DistinctAwaitWithCancellation(source, keySelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new DistinctAwaitCancellation<TSource, TKey>(source, keySelector, comparer);
}
}
internal sealed class Distinct<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly IEqualityComparer<TSource> comparer;
public Distinct(IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
this.source = source;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly HashSet<TSource> set;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.set = new HashSet<TSource>(comparer);
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var v = SourceCurrent;
if (set.Add(v))
{
Current = v;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class Distinct<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly IEqualityComparer<TKey> comparer;
public Distinct(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly HashSet<TKey> set;
readonly Func<TSource, TKey> keySelector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.set = new HashSet<TKey>(comparer);
this.keySelector = keySelector;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var v = SourceCurrent;
if (set.Add(keySelector(v)))
{
Current = v;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class DistinctAwait<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TKey>> keySelector;
readonly IEqualityComparer<TKey> comparer;
public DistinctAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, TKey>
{
readonly HashSet<TKey> set;
readonly Func<TSource, UniTask<TKey>> keySelector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.set = new HashSet<TKey>(comparer);
this.keySelector = keySelector;
}
protected override UniTask<TKey> TransformAsync(TSource sourceCurrent)
{
return keySelector(sourceCurrent);
}
protected override bool TrySetCurrentCore(TKey awaitResult, out bool terminateIteration)
{
if (set.Add(awaitResult))
{
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = false;
return false;
}
}
}
}
internal sealed class DistinctAwaitCancellation<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
readonly IEqualityComparer<TKey> comparer;
public DistinctAwaitCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, TKey>
{
readonly HashSet<TKey> set;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.set = new HashSet<TKey>(comparer);
this.keySelector = keySelector;
}
protected override UniTask<TKey> TransformAsync(TSource sourceCurrent)
{
return keySelector(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(TKey awaitResult, out bool terminateIteration)
{
if (set.Add(awaitResult))
{
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = false;
return false;
}
}
}
}
}

View File

@@ -1,297 +0,0 @@
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 IUniTaskAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
return DistinctUntilChanged(source, EqualityComparer<TSource>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChanged<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new DistinctUntilChanged<TSource>(source, comparer);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
return DistinctUntilChanged(source, keySelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChanged<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new DistinctUntilChanged<TSource, TKey>(source, keySelector, comparer);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChangedAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
return DistinctUntilChangedAwait(source, keySelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChangedAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new DistinctUntilChangedAwait<TSource, TKey>(source, keySelector, comparer);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChangedAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
return DistinctUntilChangedAwaitWithCancellation(source, keySelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> DistinctUntilChangedAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new DistinctUntilChangedAwaitCancellation<TSource, TKey>(source, keySelector, comparer);
}
}
internal sealed class DistinctUntilChanged<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly IEqualityComparer<TSource> comparer;
public DistinctUntilChanged(IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer)
{
this.source = source;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly IEqualityComparer<TSource> comparer;
TSource prev;
bool first;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.comparer = comparer;
this.first = true;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var v = SourceCurrent;
if (first || !comparer.Equals(prev, v))
{
first = false;
Current = prev = v;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class DistinctUntilChanged<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly IEqualityComparer<TKey> comparer;
public DistinctUntilChanged(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly IEqualityComparer<TKey> comparer;
readonly Func<TSource, TKey> keySelector;
TKey prev;
bool first;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.comparer = comparer;
this.keySelector = keySelector;
this.first = true;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var v = SourceCurrent;
var key = keySelector(v);
if (first || !comparer.Equals(prev, key))
{
first = false;
prev = key;
Current = v;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class DistinctUntilChangedAwait<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TKey>> keySelector;
readonly IEqualityComparer<TKey> comparer;
public DistinctUntilChangedAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, TKey>
{
readonly IEqualityComparer<TKey> comparer;
readonly Func<TSource, UniTask<TKey>> keySelector;
TKey prev;
bool first;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.comparer = comparer;
this.keySelector = keySelector;
this.first = true;
}
protected override UniTask<TKey> TransformAsync(TSource sourceCurrent)
{
return keySelector(sourceCurrent);
}
protected override bool TrySetCurrentCore(TKey key, out bool terminateIteration)
{
if (first || !comparer.Equals(prev, key))
{
first = false;
prev = key;
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = false;
return false;
}
}
}
}
internal sealed class DistinctUntilChangedAwaitCancellation<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
readonly IEqualityComparer<TKey> comparer;
public DistinctUntilChangedAwaitCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, TKey>
{
readonly IEqualityComparer<TKey> comparer;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
TKey prev;
bool first;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.comparer = comparer;
this.keySelector = keySelector;
this.first = true;
}
protected override UniTask<TKey> TransformAsync(TSource sourceCurrent)
{
return keySelector(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(TKey key, out bool terminateIteration)
{
if (first || !comparer.Equals(prev, key))
{
first = false;
prev = key;
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = false;
return false;
}
}
}
}
}

View File

@@ -1,256 +0,0 @@
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Internal;
using Cysharp.Threading.Tasks.Linq;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext)
{
Error.ThrowArgumentNullException(source, nameof(source));
return source.Do(onNext, null, null);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
{
Error.ThrowArgumentNullException(source, nameof(source));
return source.Do(onNext, onError, null);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
{
Error.ThrowArgumentNullException(source, nameof(source));
return source.Do(onNext, null, onCompleted);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Do<TSource>(source, onNext, onError, onCompleted);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(observer, nameof(observer));
return source.Do(observer.OnNext, observer.OnError, observer.OnCompleted); // alloc delegate.
}
// not yet impl.
//public static IUniTaskAsyncEnumerable<TSource> DoAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Func<Exception, UniTask> onError)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Func<UniTask> onCompleted)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> onNext, Func<Exception, UniTask> onError, Func<UniTask> onCompleted)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Func<Exception, CancellationToken, UniTask> onError)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Func<CancellationToken, UniTask> onCompleted)
//{
// throw new NotImplementedException();
//}
//public static IUniTaskAsyncEnumerable<TSource> DoAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> onNext, Func<Exception, CancellationToken, UniTask> onError, Func<CancellationToken, UniTask> onCompleted)
//{
// throw new NotImplementedException();
//}
}
internal sealed class Do<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Action<TSource> onNext;
readonly Action<Exception> onError;
readonly Action onCompleted;
public Do(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
{
this.source = source;
this.onNext = onNext;
this.onError = onError;
this.onCompleted = onCompleted;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, onNext, onError, onCompleted, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Action<TSource> onNext;
readonly Action<Exception> onError;
readonly Action onCompleted;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
{
this.source = source;
this.onNext = onNext;
this.onError = onError;
this.onCompleted = onCompleted;
this.cancellationToken = cancellationToken;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
bool isCompleted = false;
try
{
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
isCompleted = awaiter.IsCompleted;
}
catch (Exception ex)
{
CallTrySetExceptionAfterNotification(ex);
return new UniTask<bool>(this, completionSource.Version);
}
if (isCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
void CallTrySetExceptionAfterNotification(Exception ex)
{
if (onError != null)
{
try
{
onError(ex);
}
catch (Exception ex2)
{
completionSource.TrySetException(ex2);
return;
}
}
completionSource.TrySetException(ex);
}
bool TryGetResultWithNotification<T>(UniTask<T>.Awaiter awaiter, out T result)
{
try
{
result = awaiter.GetResult();
return true;
}
catch (Exception ex)
{
CallTrySetExceptionAfterNotification(ex);
result = default;
return false;
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResultWithNotification(self.awaiter, out var result))
{
if (result)
{
var v = self.enumerator.Current;
if (self.onNext != null)
{
try
{
self.onNext(v);
}
catch (Exception ex)
{
self.CallTrySetExceptionAfterNotification(ex);
}
}
self.Current = v;
self.completionSource.TrySetResult(true);
}
else
{
if (self.onCompleted != null)
{
try
{
self.onCompleted();
}
catch (Exception ex)
{
self.CallTrySetExceptionAfterNotification(ex);
return;
}
}
self.completionSource.TrySetResult(false);
}
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,58 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource> ElementAtAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return ElementAt.InvokeAsync(source, index, cancellationToken, false);
}
public static UniTask<TSource> ElementAtOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return ElementAt.InvokeAsync(source, index, cancellationToken, true);
}
}
internal static class ElementAt
{
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int i = 0;
while (await e.MoveNextAsync())
{
if (i++ == index)
{
return e.Current;
}
}
if (defaultIfEmpty)
{
return default;
}
else
{
throw Error.ArgumentOutOfRange(nameof(index));
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,47 +0,0 @@
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<T> Empty<T>()
{
return Cysharp.Threading.Tasks.Linq.Empty<T>.Instance;
}
}
internal class Empty<T> : IUniTaskAsyncEnumerable<T>
{
public static readonly IUniTaskAsyncEnumerable<T> Instance = new Empty<T>();
Empty()
{
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return Enumerator.Instance;
}
class Enumerator : IUniTaskAsyncEnumerator<T>
{
public static readonly IUniTaskAsyncEnumerator<T> Instance = new Enumerator();
Enumerator()
{
}
public T Current => default;
public UniTask<bool> MoveNextAsync()
{
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,116 +0,0 @@
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 IUniTaskAsyncEnumerable<TSource> Except<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
return new Except<TSource>(first, second, EqualityComparer<TSource>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> Except<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new Except<TSource>(first, second, comparer);
}
}
internal sealed class Except<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> first;
readonly IUniTaskAsyncEnumerable<TSource> second;
readonly IEqualityComparer<TSource> comparer;
public Except(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
this.first = first;
this.second = second;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
static Action<object> HashSetAsyncCoreDelegate = HashSetAsyncCore;
readonly IEqualityComparer<TSource> comparer;
readonly IUniTaskAsyncEnumerable<TSource> second;
HashSet<TSource> set;
UniTask<HashSet<TSource>>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
: base(first, cancellationToken)
{
this.second = second;
this.comparer = comparer;
}
protected override bool OnFirstIteration()
{
if (set != null) return false;
awaiter = second.ToHashSetAsync(cancellationToken).GetAwaiter();
if (awaiter.IsCompleted)
{
set = awaiter.GetResult();
SourceMoveNext();
}
else
{
awaiter.SourceOnCompleted(HashSetAsyncCoreDelegate, this);
}
return true;
}
static void HashSetAsyncCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
self.set = result;
self.SourceMoveNext();
}
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var v = SourceCurrent;
if (set.Add(v))
{
Current = v;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
}

View File

@@ -1,200 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource> FirstAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return First.InvokeAsync(source, cancellationToken, false);
}
public static UniTask<TSource> FirstAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return First.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> FirstAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return First.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> FirstAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return First.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> FirstOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return First.InvokeAsync(source, cancellationToken, true);
}
public static UniTask<TSource> FirstOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return First.InvokeAsync(source, predicate, cancellationToken, true);
}
public static UniTask<TSource> FirstOrDefaultAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return First.InvokeAsync(source, predicate, cancellationToken, true);
}
public static UniTask<TSource> FirstOrDefaultAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return First.InvokeAsync(source, predicate, cancellationToken, true);
}
}
internal static class First
{
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
if (await e.MoveNextAsync())
{
return e.Current;
}
else
{
if (defaultIfEmpty)
{
return default;
}
else
{
throw Error.NoElements();
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
if (predicate(v))
{
return v;
}
}
if (defaultIfEmpty)
{
return default;
}
else
{
throw Error.NoElements();
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
if (await predicate(v))
{
return v;
}
}
if (defaultIfEmpty)
{
return default;
}
else
{
throw Error.NoElements();
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
if (await predicate(v, cancellationToken))
{
return v;
}
}
if (defaultIfEmpty)
{
return default;
}
else
{
throw Error.NoElements();
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,177 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask ForEachAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken);
}
public static UniTask ForEachAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource, Int32> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken);
}
public static UniTask ForEachAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask> action, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(action, nameof(action));
return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken);
}
}
internal static class ForEach
{
public static async UniTask InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
action(e.Current);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Action<TSource, Int32> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int index = 0;
while (await e.MoveNextAsync())
{
action(e.Current, checked(index++));
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
await action(e.Current);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int index = 0;
while (await e.MoveNextAsync())
{
await action(e.Current, checked(index++));
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
await action(e.Current, cancellationToken);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask InvokeAwaitWithCancellationAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask> action, CancellationToken cancellationToken)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
int index = 0;
while (await e.MoveNextAsync())
{
await action(e.Current, checked(index++), cancellationToken);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,911 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
// Ix-Async returns IGrouping but it is competely waste, use standard IGrouping.
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new GroupBy<TSource, TKey, TSource>(source, keySelector, x => x, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupBy<TSource, TKey, TSource>(source, keySelector, x => x, comparer);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return new GroupBy<TSource, TKey, TElement>(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupBy<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupBy<TSource, TKey, TSource, TResult>(source, keySelector, x => x, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupBy<TSource, TKey, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TKey, IEnumerable<TSource>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupBy<TSource, TKey, TSource, TResult>(source, keySelector, x => x, resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupBy<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupBy<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
}
// await
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TSource>> GroupByAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new GroupByAwait<TSource, TKey, TSource>(source, keySelector, x => UniTask.FromResult(x), EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TSource>> GroupByAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwait<TSource, TKey, TSource>(source, keySelector, x => UniTask.FromResult(x), comparer);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>> GroupByAwait<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return new GroupByAwait<TSource, TKey, TElement>(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>> GroupByAwait<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwait<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwait<TSource, TKey, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TKey, IEnumerable<TSource>, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupByAwait<TSource, TKey, TSource, TResult>(source, keySelector, x => UniTask.FromResult(x), resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwait<TSource, TKey, TElement, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupByAwait<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwait<TSource, TKey, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TKey, IEnumerable<TSource>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwait<TSource, TKey, TSource, TResult>(source, keySelector, x => UniTask.FromResult(x), resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwait<TSource, TKey, TElement, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwait<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
}
// with ct
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TSource>> GroupByAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new GroupByAwaitWithCancellation<TSource, TKey, TSource>(source, keySelector, (x, _) => UniTask.FromResult(x), EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TSource>> GroupByAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwaitWithCancellation<TSource, TKey, TSource>(source, keySelector, (x, _) => UniTask.FromResult(x), comparer);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>> GroupByAwaitWithCancellation<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return new GroupByAwaitWithCancellation<TSource, TKey, TElement>(source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>> GroupByAwaitWithCancellation<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwaitWithCancellation<TSource, TKey, TElement>(source, keySelector, elementSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwaitWithCancellation<TSource, TKey, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TKey, IEnumerable<TSource>, CancellationToken, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupByAwaitWithCancellation<TSource, TKey, TSource, TResult>(source, keySelector, (x, _) => UniTask.FromResult(x), resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwaitWithCancellation<TSource, TKey, TElement, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, CancellationToken, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupByAwaitWithCancellation<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwaitWithCancellation<TSource, TKey, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TKey, IEnumerable<TSource>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwaitWithCancellation<TSource, TKey, TSource, TResult>(source, keySelector, (x, _) => UniTask.FromResult(x), resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupByAwaitWithCancellation<TSource, TKey, TElement, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupByAwaitWithCancellation<TSource, TKey, TElement, TResult>(source, keySelector, elementSelector, resultSelector, comparer);
}
}
internal sealed class GroupBy<TSource, TKey, TElement> : IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly Func<TSource, TElement> elementSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupBy(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<IGrouping<TKey, TElement>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, elementSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<IGrouping<TKey, TElement>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly Func<TSource, TElement> elementSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
IEnumerator<IGrouping<TKey, TElement>> groupEnumerator;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public IGrouping<TKey, TElement> Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (groupEnumerator == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
var lookup = await source.ToLookupAsync(keySelector, elementSelector, comparer, cancellationToken);
groupEnumerator = lookup.GetEnumerator();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
if (groupEnumerator.MoveNext())
{
Current = groupEnumerator.Current as IGrouping<TKey, TElement>;
completionSource.TrySetResult(true);
}
else
{
completionSource.TrySetResult(false);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
public UniTask DisposeAsync()
{
if (groupEnumerator != null)
{
groupEnumerator.Dispose();
}
return default;
}
}
}
internal sealed class GroupBy<TSource, TKey, TElement, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly Func<TSource, TElement> elementSelector;
readonly Func<TKey, IEnumerable<TElement>, TResult> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupBy(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TKey> keySelector;
readonly Func<TSource, TElement> elementSelector;
readonly Func<TKey, IEnumerable<TElement>, TResult> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
IEnumerator<IGrouping<TKey, TElement>> groupEnumerator;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (groupEnumerator == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
var lookup = await source.ToLookupAsync(keySelector, elementSelector, comparer, cancellationToken);
groupEnumerator = lookup.GetEnumerator();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
if (groupEnumerator.MoveNext())
{
var current = groupEnumerator.Current;
Current = resultSelector(current.Key, current);
completionSource.TrySetResult(true);
}
else
{
completionSource.TrySetResult(false);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
public UniTask DisposeAsync()
{
if (groupEnumerator != null)
{
groupEnumerator.Dispose();
}
return default;
}
}
}
internal sealed class GroupByAwait<TSource, TKey, TElement> : IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TKey>> keySelector;
readonly Func<TSource, UniTask<TElement>> elementSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupByAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<IGrouping<TKey, TElement>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, elementSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<IGrouping<TKey, TElement>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TKey>> keySelector;
readonly Func<TSource, UniTask<TElement>> elementSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
IEnumerator<IGrouping<TKey, TElement>> groupEnumerator;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public IGrouping<TKey, TElement> Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (groupEnumerator == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
var lookup = await source.ToLookupAwaitAsync(keySelector, elementSelector, comparer, cancellationToken);
groupEnumerator = lookup.GetEnumerator();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
if (groupEnumerator.MoveNext())
{
Current = groupEnumerator.Current as IGrouping<TKey, TElement>;
completionSource.TrySetResult(true);
}
else
{
completionSource.TrySetResult(false);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
public UniTask DisposeAsync()
{
if (groupEnumerator != null)
{
groupEnumerator.Dispose();
}
return default;
}
}
}
internal sealed class GroupByAwait<TSource, TKey, TElement, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TKey>> keySelector;
readonly Func<TSource, UniTask<TElement>> elementSelector;
readonly Func<TKey, IEnumerable<TElement>, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupByAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
readonly static Action<object> ResultSelectCoreDelegate = ResultSelectCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TKey>> keySelector;
readonly Func<TSource, UniTask<TElement>> elementSelector;
readonly Func<TKey, IEnumerable<TElement>, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
IEnumerator<IGrouping<TKey, TElement>> groupEnumerator;
UniTask<TResult>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (groupEnumerator == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
var lookup = await source.ToLookupAwaitAsync(keySelector, elementSelector, comparer, cancellationToken);
groupEnumerator = lookup.GetEnumerator();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
if (groupEnumerator.MoveNext())
{
var current = groupEnumerator.Current;
awaiter = resultSelector(current.Key, current).GetAwaiter();
if (awaiter.IsCompleted)
{
ResultSelectCore(this);
}
else
{
awaiter.SourceOnCompleted(ResultSelectCoreDelegate, this);
}
return;
}
else
{
completionSource.TrySetResult(false);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
static void ResultSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public UniTask DisposeAsync()
{
if (groupEnumerator != null)
{
groupEnumerator.Dispose();
}
return default;
}
}
}
internal sealed class GroupByAwaitWithCancellation<TSource, TKey, TElement> : IUniTaskAsyncEnumerable<IGrouping<TKey, TElement>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
readonly Func<TSource, CancellationToken, UniTask<TElement>> elementSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupByAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<IGrouping<TKey, TElement>> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, elementSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<IGrouping<TKey, TElement>>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
readonly Func<TSource, CancellationToken, UniTask<TElement>> elementSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
IEnumerator<IGrouping<TKey, TElement>> groupEnumerator;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public IGrouping<TKey, TElement> Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (groupEnumerator == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
var lookup = await source.ToLookupAwaitWithCancellationAsync(keySelector, elementSelector, comparer, cancellationToken);
groupEnumerator = lookup.GetEnumerator();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
if (groupEnumerator.MoveNext())
{
Current = groupEnumerator.Current as IGrouping<TKey, TElement>;
completionSource.TrySetResult(true);
}
else
{
completionSource.TrySetResult(false);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
public UniTask DisposeAsync()
{
if (groupEnumerator != null)
{
groupEnumerator.Dispose();
}
return default;
}
}
}
internal sealed class GroupByAwaitWithCancellation<TSource, TKey, TElement, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
readonly Func<TSource, CancellationToken, UniTask<TElement>> elementSelector;
readonly Func<TKey, IEnumerable<TElement>, CancellationToken, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupByAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
readonly static Action<object> ResultSelectCoreDelegate = ResultSelectCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
readonly Func<TSource, CancellationToken, UniTask<TElement>> elementSelector;
readonly Func<TKey, IEnumerable<TElement>, CancellationToken, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
IEnumerator<IGrouping<TKey, TElement>> groupEnumerator;
UniTask<TResult>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, Func<TKey, IEnumerable<TElement>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.source = source;
this.keySelector = keySelector;
this.elementSelector = elementSelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (groupEnumerator == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
var lookup = await source.ToLookupAwaitWithCancellationAsync(keySelector, elementSelector, comparer, cancellationToken);
groupEnumerator = lookup.GetEnumerator();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
if (groupEnumerator.MoveNext())
{
var current = groupEnumerator.Current;
awaiter = resultSelector(current.Key, current, cancellationToken).GetAwaiter();
if (awaiter.IsCompleted)
{
ResultSelectCore(this);
}
else
{
awaiter.SourceOnCompleted(ResultSelectCoreDelegate, this);
}
return;
}
else
{
completionSource.TrySetResult(false);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
}
static void ResultSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public UniTask DisposeAsync()
{
if (groupEnumerator != null)
{
groupEnumerator.Dispose();
}
return default;
}
}
}
}

View File

@@ -1,606 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupJoin<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupJoin<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupJoinAwait<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupJoinAwait<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupJoinAwait<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupJoinAwait<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> GroupJoinAwaitWithCancellation<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, CancellationToken, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new GroupJoinWithCancellationAwait<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> GroupJoinAwaitWithCancellation<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new GroupJoinWithCancellationAwait<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
}
internal sealed class GroupJoin<TOuter, TInner, TKey, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, TKey> outerKeySelector;
readonly Func<TInner, TKey> innerKeySelector;
readonly Func<TOuter, IEnumerable<TInner>, TResult> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupJoin(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, TKey> outerKeySelector;
readonly Func<TInner, TKey> innerKeySelector;
readonly Func<TOuter, IEnumerable<TInner>, TResult> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
ILookup<TKey, TInner> lookup;
IUniTaskAsyncEnumerator<TOuter> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, IEnumerable<TInner>, TResult> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (lookup == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
lookup = await inner.ToLookupAsync(innerKeySelector, comparer, cancellationToken);
enumerator = outer.GetAsyncEnumerator(cancellationToken);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
var outer = self.enumerator.Current;
var key = self.outerKeySelector(outer);
var values = self.lookup[key];
self.Current = self.resultSelector(outer, values);
self.completionSource.TrySetResult(true);
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
internal sealed class GroupJoinAwait<TOuter, TInner, TKey, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, IEnumerable<TInner>, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupJoinAwait(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly static Action<object> ResultSelectCoreDelegate = ResultSelectCore;
readonly static Action<object> OuterKeySelectCoreDelegate = OuterKeySelectCore;
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, IEnumerable<TInner>, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
ILookup<TKey, TInner> lookup;
IUniTaskAsyncEnumerator<TOuter> enumerator;
TOuter outerValue;
UniTask<bool>.Awaiter awaiter;
UniTask<TKey>.Awaiter outerKeyAwaiter;
UniTask<TResult>.Awaiter resultAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (lookup == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
lookup = await inner.ToLookupAwaitAsync(innerKeySelector, comparer, cancellationToken);
enumerator = outer.GetAsyncEnumerator(cancellationToken);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
try
{
self.outerValue = self.enumerator.Current;
self.outerKeyAwaiter = self.outerKeySelector(self.outerValue).GetAwaiter();
if (self.outerKeyAwaiter.IsCompleted)
{
OuterKeySelectCore(self);
}
else
{
self.outerKeyAwaiter.SourceOnCompleted(OuterKeySelectCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void OuterKeySelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.outerKeyAwaiter, out var result))
{
try
{
var values = self.lookup[result];
self.resultAwaiter = self.resultSelector(self.outerValue, values).GetAwaiter();
if (self.resultAwaiter.IsCompleted)
{
ResultSelectCore(self);
}
else
{
self.resultAwaiter.SourceOnCompleted(ResultSelectCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
}
}
static void ResultSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultAwaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
internal sealed class GroupJoinWithCancellationAwait<TOuter, TInner, TKey, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, IEnumerable<TInner>, CancellationToken, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public GroupJoinWithCancellationAwait(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly static Action<object> ResultSelectCoreDelegate = ResultSelectCore;
readonly static Action<object> OuterKeySelectCoreDelegate = OuterKeySelectCore;
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, IEnumerable<TInner>, CancellationToken, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
ILookup<TKey, TInner> lookup;
IUniTaskAsyncEnumerator<TOuter> enumerator;
TOuter outerValue;
UniTask<bool>.Awaiter awaiter;
UniTask<TKey>.Awaiter outerKeyAwaiter;
UniTask<TResult>.Awaiter resultAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, IEnumerable<TInner>, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (lookup == null)
{
CreateLookup().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateLookup()
{
try
{
lookup = await inner.ToLookupAwaitWithCancellationAsync(innerKeySelector, comparer, cancellationToken);
enumerator = outer.GetAsyncEnumerator(cancellationToken);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
try
{
self.outerValue = self.enumerator.Current;
self.outerKeyAwaiter = self.outerKeySelector(self.outerValue, self.cancellationToken).GetAwaiter();
if (self.outerKeyAwaiter.IsCompleted)
{
OuterKeySelectCore(self);
}
else
{
self.outerKeyAwaiter.SourceOnCompleted(OuterKeySelectCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void OuterKeySelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.outerKeyAwaiter, out var result))
{
try
{
var values = self.lookup[result];
self.resultAwaiter = self.resultSelector(self.outerValue, values, self.cancellationToken).GetAwaiter();
if (self.resultAwaiter.IsCompleted)
{
ResultSelectCore(self);
}
else
{
self.resultAwaiter.SourceOnCompleted(ResultSelectCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
}
}
static void ResultSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultAwaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,117 +0,0 @@
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 IUniTaskAsyncEnumerable<TSource> Intersect<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
return new Intersect<TSource>(first, second, EqualityComparer<TSource>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> Intersect<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new Intersect<TSource>(first, second, comparer);
}
}
internal sealed class Intersect<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> first;
readonly IUniTaskAsyncEnumerable<TSource> second;
readonly IEqualityComparer<TSource> comparer;
public Intersect(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
this.first = first;
this.second = second;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, comparer, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
static Action<object> HashSetAsyncCoreDelegate = HashSetAsyncCore;
readonly IEqualityComparer<TSource> comparer;
readonly IUniTaskAsyncEnumerable<TSource> second;
HashSet<TSource> set;
UniTask<HashSet<TSource>>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
: base(first, cancellationToken)
{
this.second = second;
this.comparer = comparer;
}
protected override bool OnFirstIteration()
{
if (set != null) return false;
awaiter = second.ToHashSetAsync(cancellationToken).GetAwaiter();
if (awaiter.IsCompleted)
{
set = awaiter.GetResult();
SourceMoveNext();
}
else
{
awaiter.SourceOnCompleted(HashSetAsyncCoreDelegate, this);
}
return true;
}
static void HashSetAsyncCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
self.set = result;
self.SourceMoveNext();
}
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
var v = SourceCurrent;
if (set.Remove(v))
{
Current = v;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
}

View File

@@ -1,722 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new Join<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new Join<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> JoinAwait<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new JoinAwait<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> JoinAwait<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new JoinAwait<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
public static IUniTaskAsyncEnumerable<TResult> JoinAwaitWithCancellation<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, CancellationToken, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new JoinAwaitWithCancellation<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
}
public static IUniTaskAsyncEnumerable<TResult> JoinAwaitWithCancellation<TOuter, TInner, TKey, TResult>(this IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(outer, nameof(outer));
Error.ThrowArgumentNullException(inner, nameof(inner));
Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector));
Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new JoinAwaitWithCancellation<TOuter, TInner, TKey, TResult>(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer);
}
}
internal sealed class Join<TOuter, TInner, TKey, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, TKey> outerKeySelector;
readonly Func<TInner, TKey> innerKeySelector;
readonly Func<TOuter, TInner, TResult> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public Join(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, TKey> outerKeySelector;
readonly Func<TInner, TKey> innerKeySelector;
readonly Func<TOuter, TInner, TResult> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
ILookup<TKey, TInner> lookup;
IUniTaskAsyncEnumerator<TOuter> enumerator;
UniTask<bool>.Awaiter awaiter;
TOuter currentOuterValue;
IEnumerator<TInner> valueEnumerator;
bool continueNext;
public Enumerator(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (lookup == null)
{
CreateInnerHashSet().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateInnerHashSet()
{
try
{
lookup = await inner.ToLookupAsync(innerKeySelector, comparer, cancellationToken);
enumerator = outer.GetAsyncEnumerator(cancellationToken);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
LOOP:
if (valueEnumerator != null)
{
if (valueEnumerator.MoveNext())
{
Current = resultSelector(currentOuterValue, valueEnumerator.Current);
goto TRY_SET_RESULT_TRUE;
}
else
{
valueEnumerator.Dispose();
valueEnumerator = null;
}
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
return;
TRY_SET_RESULT_TRUE:
completionSource.TrySetResult(true);
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.currentOuterValue = self.enumerator.Current;
var key = self.outerKeySelector(self.currentOuterValue);
self.valueEnumerator = self.lookup[key].GetEnumerator();
if (self.continueNext)
{
return;
}
else
{
self.SourceMoveNext();
}
}
else
{
self.continueNext = false;
self.completionSource.TrySetResult(false);
}
}
else
{
self.continueNext = false;
}
}
public UniTask DisposeAsync()
{
if (valueEnumerator != null)
{
valueEnumerator.Dispose();
}
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
internal sealed class JoinAwait<TOuter, TInner, TKey, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, TInner, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public JoinAwait(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
static readonly Action<object> OuterSelectCoreDelegate = OuterSelectCore;
static readonly Action<object> ResultSelectCoreDelegate = ResultSelectCore;
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, TInner, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
ILookup<TKey, TInner> lookup;
IUniTaskAsyncEnumerator<TOuter> enumerator;
UniTask<bool>.Awaiter awaiter;
TOuter currentOuterValue;
IEnumerator<TInner> valueEnumerator;
UniTask<TResult>.Awaiter resultAwaiter;
UniTask<TKey>.Awaiter outerKeyAwaiter;
bool continueNext;
public Enumerator(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, UniTask<TKey>> outerKeySelector, Func<TInner, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (lookup == null)
{
CreateInnerHashSet().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateInnerHashSet()
{
try
{
lookup = await inner.ToLookupAwaitAsync(innerKeySelector, comparer, cancellationToken);
enumerator = outer.GetAsyncEnumerator(cancellationToken);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
LOOP:
if (valueEnumerator != null)
{
if (valueEnumerator.MoveNext())
{
resultAwaiter = resultSelector(currentOuterValue, valueEnumerator.Current).GetAwaiter();
if (resultAwaiter.IsCompleted)
{
ResultSelectCore(this);
}
else
{
resultAwaiter.SourceOnCompleted(ResultSelectCoreDelegate, this);
}
return;
}
else
{
valueEnumerator.Dispose();
valueEnumerator = null;
}
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.currentOuterValue = self.enumerator.Current;
self.outerKeyAwaiter = self.outerKeySelector(self.currentOuterValue).GetAwaiter();
if (self.outerKeyAwaiter.IsCompleted)
{
OuterSelectCore(self);
}
else
{
self.continueNext = false;
self.outerKeyAwaiter.SourceOnCompleted(OuterSelectCoreDelegate, self);
}
}
else
{
self.continueNext = false;
self.completionSource.TrySetResult(false);
}
}
else
{
self.continueNext = false;
}
}
static void OuterSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.outerKeyAwaiter, out var key))
{
self.valueEnumerator = self.lookup[key].GetEnumerator();
if (self.continueNext)
{
return;
}
else
{
self.SourceMoveNext();
}
}
else
{
self.continueNext = false;
}
}
static void ResultSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultAwaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public UniTask DisposeAsync()
{
if (valueEnumerator != null)
{
valueEnumerator.Dispose();
}
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
internal sealed class JoinAwaitWithCancellation<TOuter, TInner, TKey, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, TInner, CancellationToken, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
public JoinAwaitWithCancellation(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
static readonly Action<object> OuterSelectCoreDelegate = OuterSelectCore;
static readonly Action<object> ResultSelectCoreDelegate = ResultSelectCore;
readonly IUniTaskAsyncEnumerable<TOuter> outer;
readonly IUniTaskAsyncEnumerable<TInner> inner;
readonly Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector;
readonly Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector;
readonly Func<TOuter, TInner, CancellationToken, UniTask<TResult>> resultSelector;
readonly IEqualityComparer<TKey> comparer;
CancellationToken cancellationToken;
ILookup<TKey, TInner> lookup;
IUniTaskAsyncEnumerator<TOuter> enumerator;
UniTask<bool>.Awaiter awaiter;
TOuter currentOuterValue;
IEnumerator<TInner> valueEnumerator;
UniTask<TResult>.Awaiter resultAwaiter;
UniTask<TKey>.Awaiter outerKeyAwaiter;
bool continueNext;
public Enumerator(IUniTaskAsyncEnumerable<TOuter> outer, IUniTaskAsyncEnumerable<TInner> inner, Func<TOuter, CancellationToken, UniTask<TKey>> outerKeySelector, Func<TInner, CancellationToken, UniTask<TKey>> innerKeySelector, Func<TOuter, TInner, CancellationToken, UniTask<TResult>> resultSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
this.outer = outer;
this.inner = inner;
this.outerKeySelector = outerKeySelector;
this.innerKeySelector = innerKeySelector;
this.resultSelector = resultSelector;
this.comparer = comparer;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
if (lookup == null)
{
CreateInnerHashSet().Forget();
}
else
{
SourceMoveNext();
}
return new UniTask<bool>(this, completionSource.Version);
}
async UniTaskVoid CreateInnerHashSet()
{
try
{
lookup = await inner.ToLookupAwaitWithCancellationAsync(innerKeySelector, comparer, cancellationToken: cancellationToken);
enumerator = outer.GetAsyncEnumerator(cancellationToken);
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
SourceMoveNext();
}
void SourceMoveNext()
{
try
{
LOOP:
if (valueEnumerator != null)
{
if (valueEnumerator.MoveNext())
{
resultAwaiter = resultSelector(currentOuterValue, valueEnumerator.Current, cancellationToken).GetAwaiter();
if (resultAwaiter.IsCompleted)
{
ResultSelectCore(this);
}
else
{
resultAwaiter.SourceOnCompleted(ResultSelectCoreDelegate, this);
}
return;
}
else
{
valueEnumerator.Dispose();
valueEnumerator = null;
}
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
self.currentOuterValue = self.enumerator.Current;
self.outerKeyAwaiter = self.outerKeySelector(self.currentOuterValue, self.cancellationToken).GetAwaiter();
if (self.outerKeyAwaiter.IsCompleted)
{
OuterSelectCore(self);
}
else
{
self.continueNext = false;
self.outerKeyAwaiter.SourceOnCompleted(OuterSelectCoreDelegate, self);
}
}
else
{
self.continueNext = false;
self.completionSource.TrySetResult(false);
}
}
else
{
self.continueNext = false;
}
}
static void OuterSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.outerKeyAwaiter, out var key))
{
self.valueEnumerator = self.lookup[key].GetEnumerator();
if (self.continueNext)
{
return;
}
else
{
self.SourceMoveNext();
}
}
else
{
self.continueNext = false;
}
}
static void ResultSelectCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultAwaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public UniTask DisposeAsync()
{
if (valueEnumerator != null)
{
valueEnumerator.Dispose();
}
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,240 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource> LastAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Last.InvokeAsync(source, cancellationToken, false);
}
public static UniTask<TSource> LastAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Last.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> LastAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Last.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> LastAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Last.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> LastOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Last.InvokeAsync(source, cancellationToken, true);
}
public static UniTask<TSource> LastOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Last.InvokeAsync(source, predicate, cancellationToken, true);
}
public static UniTask<TSource> LastOrDefaultAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Last.InvokeAsync(source, predicate, cancellationToken, true);
}
public static UniTask<TSource> LastOrDefaultAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return Last.InvokeAsync(source, predicate, cancellationToken, true);
}
}
internal static class Last
{
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
if (await e.MoveNextAsync())
{
value = e.Current;
}
else
{
if (defaultIfEmpty)
{
return value;
}
else
{
throw Error.NoElements();
}
}
while (await e.MoveNextAsync())
{
value = e.Current;
}
return value;
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
bool found = false;
while (await e.MoveNextAsync())
{
var v = e.Current;
if (predicate(v))
{
found = true;
value = v;
}
}
if (defaultIfEmpty)
{
return value;
}
else
{
if (found)
{
return value;
}
else
{
throw Error.NoElements();
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
bool found = false;
while (await e.MoveNextAsync())
{
var v = e.Current;
if (await predicate(v))
{
found = true;
value = v;
}
}
if (defaultIfEmpty)
{
return value;
}
else
{
if (found)
{
return value;
}
else
{
throw Error.NoElements();
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
bool found = false;
while (await e.MoveNextAsync())
{
var v = e.Current;
if (await predicate(v, cancellationToken))
{
found = true;
value = v;
}
}
if (defaultIfEmpty)
{
return value;
}
else
{
if (found)
{
return value;
}
else
{
throw Error.NoElements();
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,144 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<long> LongCountAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return LongCount.InvokeAsync(source, cancellationToken);
}
public static UniTask<long> LongCountAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return LongCount.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<long> LongCountAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return LongCount.InvokeAsync(source, predicate, cancellationToken);
}
public static UniTask<long> LongCountAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return LongCount.InvokeAsync(source, predicate, cancellationToken);
}
}
internal static class LongCount
{
internal static async UniTask<long> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
long count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
checked { count++; }
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
internal static async UniTask<long> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken)
{
long count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (predicate(e.Current))
{
checked { count++; }
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
internal static async UniTask<long> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
long count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (await predicate(e.Current))
{
checked { count++; }
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
internal static async UniTask<long> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken)
{
long count = 0;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
if (await predicate(e.Current, cancellationToken))
{
checked { count++; }
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return count;
}
}
}

View File

@@ -1,200 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource> MaxAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Max.InvokeAsync(source, cancellationToken);
}
public static UniTask<TResult> MaxAsync<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Max.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<TResult> MaxAwaitAsync<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Max.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<TResult> MaxAwaitCancellationAsync<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Max.InvokeAsync(source, selector, cancellationToken);
}
}
internal static partial class Max
{
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
TSource value = default;
var comparer = Comparer<TSource>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = e.Current;
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = e.Current;
if (comparer.Compare(value, x) < 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<TResult> InvokeAsync<TSource, TResult>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
{
TResult value = default;
var comparer = Comparer<TResult>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = selector(e.Current);
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = selector(e.Current);
if (comparer.Compare(value, x) < 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<TResult> InvokeAsync<TSource, TResult>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken)
{
TResult value = default;
var comparer = Comparer<TResult>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current);
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current);
if (comparer.Compare(value, x) < 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<TResult> InvokeAsync<TSource, TResult>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
{
TResult value = default;
var comparer = Comparer<TResult>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current, cancellationToken);
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current, cancellationToken);
if (comparer.Compare(value, x) < 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
}
}

View File

@@ -1,200 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource> MinAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Min.InvokeAsync(source, cancellationToken);
}
public static UniTask<TResult> MinAsync<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Min.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<TResult> MinAwaitAsync<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Min.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<TResult> MinAwaitCancellationAsync<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Min.InvokeAsync(source, selector, cancellationToken);
}
}
internal static partial class Min
{
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
TSource value = default;
var comparer = Comparer<TSource>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = e.Current;
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = e.Current;
if (comparer.Compare(value, x) > 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<TResult> InvokeAsync<TSource, TResult>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
{
TResult value = default;
var comparer = Comparer<TResult>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = selector(e.Current);
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = selector(e.Current);
if (comparer.Compare(value, x) > 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<TResult> InvokeAsync<TSource, TResult>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken)
{
TResult value = default;
var comparer = Comparer<TResult>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current);
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current);
if (comparer.Compare(value, x) > 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<TResult> InvokeAsync<TSource, TResult>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
{
TResult value = default;
var comparer = Comparer<TResult>.Default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current, cancellationToken);
goto NEXT_LOOP;
}
return value;
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current, cancellationToken);
if (comparer.Compare(value, x) > 0)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,262 +0,0 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new[]
{
typeof(int),
typeof(long),
typeof(float),
typeof(double),
typeof(decimal),
typeof(int?),
typeof(long?),
typeof(float?),
typeof(double?),
typeof(decimal?),
};
Func<Type, bool> IsNullable = x => x.IsGenericType;
Func<Type, string> TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name;
Func<Type, string> WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : "";
#>
using System;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
<# foreach(var (minMax, op) in new[]{("Min",">"), ("Max", "<")}) { #>
public static partial class UniTaskAsyncEnumerable
{
<# foreach(var t in types) { #>
public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return <#= minMax #>.InvokeAsync(source, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return <#= minMax #>.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return <#= minMax #>.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return <#= minMax #>.InvokeAsync(source, selector, cancellationToken);
}
<# } #>
}
internal static partial class <#= minMax #>
{
<# foreach(var t in types) { #>
public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = e.Current;
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = e.Current;
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<<#= TypeName(t) #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = selector(e.Current);
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = selector(e.Current);
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<<#= TypeName(t) #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current);
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current);
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
public static async UniTask<<#= TypeName(t) #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> value = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
value = await selector(e.Current, cancellationToken);
<# if (IsNullable(t)) { #>
if(value == null) continue;
<# } #>
goto NEXT_LOOP;
}
<# if (IsNullable(t)) { #>
return default;
<# } else { #>
throw Error.NoElements();
<# } #>
NEXT_LOOP:
while (await e.MoveNextAsync())
{
var x = await selector(e.Current, cancellationToken);
<# if (IsNullable(t)) { #>
if( x == null) continue;
<# } #>
if (value <#= op #> x)
{
value = x;
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return value;
}
<# } #>
}
<# } #>
}

View File

@@ -1,56 +0,0 @@
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<T> Never<T>()
{
return Cysharp.Threading.Tasks.Linq.Never<T>.Instance;
}
}
internal class Never<T> : IUniTaskAsyncEnumerable<T>
{
public static readonly IUniTaskAsyncEnumerable<T> Instance = new Never<T>();
Never()
{
}
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<T>
{
CancellationToken cancellationToken;
public Enumerator(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
}
public T Current => default;
public UniTask<bool> MoveNextAsync()
{
var tcs = new UniTaskCompletionSource<bool>();
cancellationToken.Register(state =>
{
var task = (UniTaskCompletionSource<bool>)state;
task.TrySetCanceled(cancellationToken);
}, tcs);
return tcs.Task;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,61 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> OfType<TResult>(this IUniTaskAsyncEnumerable<Object> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new OfType<TResult>(source);
}
}
internal sealed class OfType<TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<object> source;
public OfType(IUniTaskAsyncEnumerable<object> source)
{
this.source = source;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<object, TResult>
{
public Enumerator(IUniTaskAsyncEnumerable<object> source, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (SourceCurrent is TResult castCurent)
{
Current = castCurent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
}

View File

@@ -1,556 +0,0 @@
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Collections.Generic;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
#region OrderBy_OrderByDescending
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, Comparer<TKey>.Default, false, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderBy<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer, false, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new OrderedAsyncEnumerableAwait<TSource, TKey>(source, keySelector, Comparer<TKey>.Default, false, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new OrderedAsyncEnumerableAwait<TSource, TKey>(source, keySelector, comparer, false, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new OrderedAsyncEnumerableAwaitWithCancellation<TSource, TKey>(source, keySelector, Comparer<TKey>.Default, false, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new OrderedAsyncEnumerableAwaitWithCancellation<TSource, TKey>(source, keySelector, comparer, false, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, Comparer<TKey>.Default, true, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByDescending<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new OrderedAsyncEnumerable<TSource, TKey>(source, keySelector, comparer, true, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByDescendingAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new OrderedAsyncEnumerableAwait<TSource, TKey>(source, keySelector, Comparer<TKey>.Default, true, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByDescendingAwait<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new OrderedAsyncEnumerableAwait<TSource, TKey>(source, keySelector, comparer, true, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByDescendingAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return new OrderedAsyncEnumerableAwaitWithCancellation<TSource, TKey>(source, keySelector, Comparer<TKey>.Default, true, null);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> OrderByDescendingAwaitWithCancellation<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return new OrderedAsyncEnumerableAwaitWithCancellation<TSource, TKey>(source, keySelector, comparer, true, null);
}
#endregion
#region ThenBy_ThenByDescending
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return source.CreateOrderedEnumerable(keySelector, Comparer<TKey>.Default, false);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return source.CreateOrderedEnumerable(keySelector, comparer, false);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByAwait<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return source.CreateOrderedEnumerable(keySelector, Comparer<TKey>.Default, false);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByAwait<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return source.CreateOrderedEnumerable(keySelector, comparer, false);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByAwaitWithCancellation<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return source.CreateOrderedEnumerable(keySelector, Comparer<TKey>.Default, false);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByAwaitWithCancellation<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return source.CreateOrderedEnumerable(keySelector, comparer, false);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByDescending<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return source.CreateOrderedEnumerable(keySelector, Comparer<TKey>.Default, true);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByDescending<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return source.CreateOrderedEnumerable(keySelector, comparer, true);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByDescendingAwait<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return source.CreateOrderedEnumerable(keySelector, Comparer<TKey>.Default, true);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByDescendingAwait<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return source.CreateOrderedEnumerable(keySelector, comparer, true);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByDescendingAwaitWithCancellation<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return source.CreateOrderedEnumerable(keySelector, Comparer<TKey>.Default, true);
}
public static IUniTaskOrderedAsyncEnumerable<TSource> ThenByDescendingAwaitWithCancellation<TSource, TKey>(this IUniTaskOrderedAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return source.CreateOrderedEnumerable(keySelector, comparer, true);
}
#endregion
}
internal abstract class AsyncEnumerableSorter<TElement>
{
internal abstract UniTask ComputeKeysAsync(TElement[] elements, int count);
internal abstract int CompareKeys(int index1, int index2);
internal async UniTask<int[]> SortAsync(TElement[] elements, int count)
{
await ComputeKeysAsync(elements, count);
int[] map = new int[count];
for (int i = 0; i < count; i++) map[i] = i;
QuickSort(map, 0, count - 1);
return map;
}
void QuickSort(int[] map, int left, int right)
{
do
{
int i = left;
int j = right;
int x = map[i + ((j - i) >> 1)];
do
{
while (i < map.Length && CompareKeys(x, map[i]) > 0) i++;
while (j >= 0 && CompareKeys(x, map[j]) < 0) j--;
if (i > j) break;
if (i < j)
{
int temp = map[i];
map[i] = map[j];
map[j] = temp;
}
i++;
j--;
} while (i <= j);
if (j - left <= right - i)
{
if (left < j) QuickSort(map, left, j);
left = i;
}
else
{
if (i < right) QuickSort(map, i, right);
right = j;
}
} while (left < right);
}
}
internal class SyncSelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorter<TElement>
{
readonly Func<TElement, TKey> keySelector;
readonly IComparer<TKey> comparer;
readonly bool descending;
readonly AsyncEnumerableSorter<TElement> next;
TKey[] keys;
internal SyncSelectorAsyncEnumerableSorter(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
{
this.keySelector = keySelector;
this.comparer = comparer;
this.descending = descending;
this.next = next;
}
internal override async UniTask ComputeKeysAsync(TElement[] elements, int count)
{
keys = new TKey[count];
for (int i = 0; i < count; i++) keys[i] = keySelector(elements[i]);
if (next != null) await next.ComputeKeysAsync(elements, count);
}
internal override int CompareKeys(int index1, int index2)
{
int c = comparer.Compare(keys[index1], keys[index2]);
if (c == 0)
{
if (next == null) return index1 - index2;
return next.CompareKeys(index1, index2);
}
return descending ? -c : c;
}
}
internal class AsyncSelectorEnumerableSorter<TElement, TKey> : AsyncEnumerableSorter<TElement>
{
readonly Func<TElement, UniTask<TKey>> keySelector;
readonly IComparer<TKey> comparer;
readonly bool descending;
readonly AsyncEnumerableSorter<TElement> next;
TKey[] keys;
internal AsyncSelectorEnumerableSorter(Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
{
this.keySelector = keySelector;
this.comparer = comparer;
this.descending = descending;
this.next = next;
}
internal override async UniTask ComputeKeysAsync(TElement[] elements, int count)
{
keys = new TKey[count];
for (int i = 0; i < count; i++) keys[i] = await keySelector(elements[i]);
if (next != null) await next.ComputeKeysAsync(elements, count);
}
internal override int CompareKeys(int index1, int index2)
{
int c = comparer.Compare(keys[index1], keys[index2]);
if (c == 0)
{
if (next == null) return index1 - index2;
return next.CompareKeys(index1, index2);
}
return descending ? -c : c;
}
}
internal class AsyncSelectorWithCancellationEnumerableSorter<TElement, TKey> : AsyncEnumerableSorter<TElement>
{
readonly Func<TElement, CancellationToken, UniTask<TKey>> keySelector;
readonly IComparer<TKey> comparer;
readonly bool descending;
readonly AsyncEnumerableSorter<TElement> next;
CancellationToken cancellationToken;
TKey[] keys;
internal AsyncSelectorWithCancellationEnumerableSorter(Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
{
this.keySelector = keySelector;
this.comparer = comparer;
this.descending = descending;
this.next = next;
this.cancellationToken = cancellationToken;
}
internal override async UniTask ComputeKeysAsync(TElement[] elements, int count)
{
keys = new TKey[count];
for (int i = 0; i < count; i++) keys[i] = await keySelector(elements[i], cancellationToken);
if (next != null) await next.ComputeKeysAsync(elements, count);
}
internal override int CompareKeys(int index1, int index2)
{
int c = comparer.Compare(keys[index1], keys[index2]);
if (c == 0)
{
if (next == null) return index1 - index2;
return next.CompareKeys(index1, index2);
}
return descending ? -c : c;
}
}
internal abstract class OrderedAsyncEnumerable<TElement> : IUniTaskOrderedAsyncEnumerable<TElement>
{
protected readonly IUniTaskAsyncEnumerable<TElement> source;
public OrderedAsyncEnumerable(IUniTaskAsyncEnumerable<TElement> source)
{
this.source = source;
}
public IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
{
return new OrderedAsyncEnumerable<TElement, TKey>(source, keySelector, comparer, descending, this);
}
public IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
{
return new OrderedAsyncEnumerableAwait<TElement, TKey>(source, keySelector, comparer, descending, this);
}
public IUniTaskOrderedAsyncEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
{
return new OrderedAsyncEnumerableAwaitWithCancellation<TElement, TKey>(source, keySelector, comparer, descending, this);
}
internal abstract AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken);
public IUniTaskAsyncEnumerator<TElement> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(this, cancellationToken);
}
class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TElement>
{
protected readonly OrderedAsyncEnumerable<TElement> parent;
CancellationToken cancellationToken;
TElement[] buffer;
int[] map;
int index;
public Enumerator(OrderedAsyncEnumerable<TElement> parent, CancellationToken cancellationToken)
{
this.parent = parent;
this.cancellationToken = cancellationToken;
}
public TElement Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (map == null)
{
completionSource.Reset();
CreateSortSource().Forget();
return new UniTask<bool>(this, completionSource.Version);
}
if (index < buffer.Length)
{
Current = buffer[map[index++]];
return CompletedTasks.True;
}
else
{
return CompletedTasks.False;
}
}
async UniTaskVoid CreateSortSource()
{
try
{
buffer = await parent.source.ToArrayAsync();
if (buffer.Length == 0)
{
completionSource.TrySetResult(false);
return;
}
var sorter = parent.GetAsyncEnumerableSorter(null, cancellationToken);
map = await sorter.SortAsync(buffer, buffer.Length);
sorter = null;
// set first value
Current = buffer[map[index++]];
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
completionSource.TrySetResult(true);
}
public UniTask DisposeAsync()
{
return default;
}
}
}
internal class OrderedAsyncEnumerable<TElement, TKey> : OrderedAsyncEnumerable<TElement>
{
readonly Func<TElement, TKey> keySelector;
readonly IComparer<TKey> comparer;
readonly bool descending;
readonly OrderedAsyncEnumerable<TElement> parent;
public OrderedAsyncEnumerable(IUniTaskAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
: base(source)
{
this.keySelector = keySelector;
this.comparer = comparer;
this.descending = descending;
this.parent = parent;
}
internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
{
AsyncEnumerableSorter<TElement> sorter = new SyncSelectorAsyncEnumerableSorter<TElement, TKey>(keySelector, comparer, descending, next);
if (parent != null) sorter = parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
return sorter;
}
}
internal class OrderedAsyncEnumerableAwait<TElement, TKey> : OrderedAsyncEnumerable<TElement>
{
readonly Func<TElement, UniTask<TKey>> keySelector;
readonly IComparer<TKey> comparer;
readonly bool descending;
readonly OrderedAsyncEnumerable<TElement> parent;
public OrderedAsyncEnumerableAwait(IUniTaskAsyncEnumerable<TElement> source, Func<TElement, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
: base(source)
{
this.keySelector = keySelector;
this.comparer = comparer;
this.descending = descending;
this.parent = parent;
}
internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
{
AsyncEnumerableSorter<TElement> sorter = new AsyncSelectorEnumerableSorter<TElement, TKey>(keySelector, comparer, descending, next);
if (parent != null) sorter = parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
return sorter;
}
}
internal class OrderedAsyncEnumerableAwaitWithCancellation<TElement, TKey> : OrderedAsyncEnumerable<TElement>
{
readonly Func<TElement, CancellationToken, UniTask<TKey>> keySelector;
readonly IComparer<TKey> comparer;
readonly bool descending;
readonly OrderedAsyncEnumerable<TElement> parent;
public OrderedAsyncEnumerableAwaitWithCancellation(IUniTaskAsyncEnumerable<TElement> source, Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
: base(source)
{
this.keySelector = keySelector;
this.comparer = comparer;
this.descending = descending;
this.parent = parent;
}
internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
{
AsyncEnumerableSorter<TElement> sorter = new AsyncSelectorWithCancellationEnumerableSorter<TElement, TKey>(keySelector, comparer, descending, next, cancellationToken);
if (parent != null) sorter = parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
return sorter;
}
}
}

View File

@@ -1,75 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<int> Range(int start, int count)
{
if (count < 0) throw Error.ArgumentOutOfRange(nameof(count));
var end = (long)start + count - 1L;
if (end > int.MaxValue) throw Error.ArgumentOutOfRange(nameof(count));
if (count == 0) UniTaskAsyncEnumerable.Empty<int>();
return new Cysharp.Threading.Tasks.Linq.Range(start, count);
}
}
internal class Range : IUniTaskAsyncEnumerable<int>
{
readonly int start;
readonly int end;
public Range(int start, int count)
{
this.start = start;
this.end = start + count;
}
public IUniTaskAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(start, end, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<int>
{
readonly int start;
readonly int end;
int current;
CancellationToken cancellationToken;
public Enumerator(int start, int end, CancellationToken cancellationToken)
{
this.start = start;
this.end = end;
this.cancellationToken = cancellationToken;
this.current = start - 1;
}
public int Current => current;
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
current++;
if (current != end)
{
return CompletedTasks.True;
}
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,68 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TElement> Repeat<TElement>(TElement element, int count)
{
if (count < 0) throw Error.ArgumentOutOfRange(nameof(count));
return new Repeat<TElement>(element, count);
}
}
internal class Repeat<TElement> : IUniTaskAsyncEnumerable<TElement>
{
readonly TElement element;
readonly int count;
public Repeat(TElement element, int count)
{
this.element = element;
this.count = count;
}
public IUniTaskAsyncEnumerator<TElement> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(element, count, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<TElement>
{
readonly TElement element;
readonly int count;
int remaining;
CancellationToken cancellationToken;
public Enumerator(TElement element, int count, CancellationToken cancellationToken)
{
this.element = element;
this.count = count;
this.cancellationToken = cancellationToken;
this.remaining = count;
}
public TElement Current => element;
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (remaining-- != 0)
{
return CompletedTasks.True;
}
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,63 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TValue> Return<TValue>(TValue value)
{
return new Return<TValue>(value);
}
}
internal class Return<TValue> : IUniTaskAsyncEnumerable<TValue>
{
readonly TValue value;
public Return(TValue value)
{
this.value = value;
}
public IUniTaskAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(value, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<TValue>
{
readonly TValue value;
CancellationToken cancellationToken;
bool called;
public Enumerator(TValue value, CancellationToken cancellationToken)
{
this.value = value;
this.cancellationToken = cancellationToken;
this.called = false;
}
public TValue Current => value;
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (!called)
{
called = true;
return CompletedTasks.True;
}
return CompletedTasks.False;
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,76 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Reverse<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Reverse<TSource>(source);
}
}
internal sealed class Reverse<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
public Reverse(IUniTaskAsyncEnumerable<TSource> source)
{
this.source = source;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
CancellationToken cancellationToken;
TSource[] array;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
this.source = source;
this.cancellationToken = cancellationToken;
}
public TSource Current { get; private set; }
// after consumed array, don't use await so allow async(not require UniTaskCompletionSourceCore).
public async UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (array == null)
{
array = await source.ToArrayAsync(cancellationToken);
index = array.Length - 1;
}
if (index != -1)
{
Current = array[index];
--index;
return true;
}
else
{
return false;
}
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,307 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> Select<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.Select<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> Select<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, TResult> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectInt<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwait<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwait<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwait<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwaitInt<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwaitWithCancellation<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwaitCancellation<TSource, TResult>(source, selector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectAwaitWithCancellation<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new Cysharp.Threading.Tasks.Linq.SelectAwaitIntCancellation<TSource, TResult>(source, selector);
}
}
internal sealed class Select<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, TResult> selector;
public Select(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TResult>
{
readonly Func<TSource, TResult> selector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
Current = selector(SourceCurrent);
result = true;
return true;
}
else
{
result = false;
return true;
}
}
}
}
internal sealed class SelectInt<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, TResult> selector;
public SelectInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TResult>
{
readonly Func<TSource, int, TResult> selector;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
Current = selector(SourceCurrent, checked(index++));
result = true;
return true;
}
else
{
result = false;
return true;
}
}
}
}
internal sealed class SelectAwait<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<TResult>> selector;
public SelectAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, UniTask<TResult>> selector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent);
}
protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{
Current = awaitResult;
terminateIteration= false;
return true;
}
}
}
internal sealed class SelectAwaitInt<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, UniTask<TResult>> selector;
public SelectAwaitInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, int, UniTask<TResult>> selector;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent, checked(index++));
}
protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{
Current = awaitResult;
terminateIteration= false;
return true;
}
}
}
internal sealed class SelectAwaitCancellation<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<TResult>> selector;
public SelectAwaitCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, CancellationToken, UniTask<TResult>> selector;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{
Current = awaitResult;
terminateIteration= false;
return true;
}
}
}
internal sealed class SelectAwaitIntCancellation<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, CancellationToken, UniTask<TResult>> selector;
public SelectAwaitIntCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<TResult>> selector)
{
this.source = source;
this.selector = selector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TResult>
{
readonly Func<TSource, int, CancellationToken, UniTask<TResult>> selector;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.selector = selector;
}
protected override UniTask<TResult> TransformAsync(TSource sourceCurrent)
{
return selector(sourceCurrent, checked(index++), cancellationToken);
}
protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{
Current = awaitResult;
terminateIteration= false;
return true;
}
}
}
}

View File

@@ -1,886 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TResult> SelectMany<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, IUniTaskAsyncEnumerable<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new SelectMany<TSource, TResult, TResult>(source, selector, (x, y) => y);
}
public static IUniTaskAsyncEnumerable<TResult> SelectMany<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, IUniTaskAsyncEnumerable<TResult>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new SelectMany<TSource, TResult, TResult>(source, selector, (x, y) => y);
}
public static IUniTaskAsyncEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, IUniTaskAsyncEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector));
return new SelectMany<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, IUniTaskAsyncEnumerable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector));
return new SelectMany<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwait<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<IUniTaskAsyncEnumerable<TResult>>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new SelectManyAwait<TSource, TResult, TResult>(source, selector, (x, y) => UniTask.FromResult(y));
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwait<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<IUniTaskAsyncEnumerable<TResult>>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new SelectManyAwait<TSource, TResult, TResult>(source, selector, (x, y) => UniTask.FromResult(y));
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwait<TSource, TCollection, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<IUniTaskAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector));
return new SelectManyAwait<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwait<TSource, TCollection, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<IUniTaskAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector));
return new SelectManyAwait<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwaitWithCancellation<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TResult>>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new SelectManyAwaitWithCancellation<TSource, TResult, TResult>(source, selector, (x, y, c) => UniTask.FromResult(y));
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwaitWithCancellation<TSource, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TResult>>> selector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new SelectManyAwaitWithCancellation<TSource, TResult, TResult>(source, selector, (x, y, c) => UniTask.FromResult(y));
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwaitWithCancellation<TSource, TCollection, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector));
return new SelectManyAwaitWithCancellation<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
public static IUniTaskAsyncEnumerable<TResult> SelectManyAwaitWithCancellation<TSource, TCollection, TResult>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> collectionSelector, Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector));
return new SelectManyAwaitWithCancellation<TSource, TCollection, TResult>(source, collectionSelector, resultSelector);
}
}
internal sealed class SelectMany<TSource, TCollection, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, IUniTaskAsyncEnumerable<TCollection>> selector1;
readonly Func<TSource, int, IUniTaskAsyncEnumerable<TCollection>> selector2;
readonly Func<TSource, TCollection, TResult> resultSelector;
public SelectMany(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, IUniTaskAsyncEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> resultSelector)
{
this.source = source;
this.selector1 = selector;
this.selector2 = null;
this.resultSelector = resultSelector;
}
public SelectMany(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, IUniTaskAsyncEnumerable<TCollection>> selector, Func<TSource, TCollection, TResult> resultSelector)
{
this.source = source;
this.selector1 = null;
this.selector2 = selector;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector1, selector2, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> sourceMoveNextCoreDelegate = SourceMoveNextCore;
static readonly Action<object> selectedSourceMoveNextCoreDelegate = SeletedSourceMoveNextCore;
static readonly Action<object> selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, IUniTaskAsyncEnumerable<TCollection>> selector1;
readonly Func<TSource, int, IUniTaskAsyncEnumerable<TCollection>> selector2;
readonly Func<TSource, TCollection, TResult> resultSelector;
CancellationToken cancellationToken;
TSource sourceCurrent;
int sourceIndex;
IUniTaskAsyncEnumerator<TSource> sourceEnumerator;
IUniTaskAsyncEnumerator<TCollection> selectedEnumerator;
UniTask<bool>.Awaiter sourceAwaiter;
UniTask<bool>.Awaiter selectedAwaiter;
UniTask.Awaiter selectedDisposeAsyncAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, IUniTaskAsyncEnumerable<TCollection>> selector1, Func<TSource, int, IUniTaskAsyncEnumerable<TCollection>> selector2, Func<TSource, TCollection, TResult> resultSelector, CancellationToken cancellationToken)
{
this.source = source;
this.selector1 = selector1;
this.selector2 = selector2;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
// iterate selected field
if (selectedEnumerator != null)
{
MoveNextSelected();
}
else
{
// iterate source field
if (sourceEnumerator == null)
{
sourceEnumerator = source.GetAsyncEnumerator(cancellationToken);
}
MoveNextSource();
}
return new UniTask<bool>(this, completionSource.Version);
}
void MoveNextSource()
{
try
{
sourceAwaiter = sourceEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (sourceAwaiter.IsCompleted)
{
SourceMoveNextCore(this);
}
else
{
sourceAwaiter.SourceOnCompleted(sourceMoveNextCoreDelegate, this);
}
}
void MoveNextSelected()
{
try
{
selectedAwaiter = selectedEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (selectedAwaiter.IsCompleted)
{
SeletedSourceMoveNextCore(this);
}
else
{
selectedAwaiter.SourceOnCompleted(selectedSourceMoveNextCoreDelegate, this);
}
}
static void SourceMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.sourceAwaiter, out var result))
{
if (result)
{
try
{
self.sourceCurrent = self.sourceEnumerator.Current;
if (self.selector1 != null)
{
self.selectedEnumerator = self.selector1(self.sourceCurrent).GetAsyncEnumerator(self.cancellationToken);
}
else
{
self.selectedEnumerator = self.selector2(self.sourceCurrent, checked(self.sourceIndex++)).GetAsyncEnumerator(self.cancellationToken);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
self.MoveNextSelected(); // iterated selected source.
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void SeletedSourceMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.selectedAwaiter, out var result))
{
if (result)
{
try
{
self.Current = self.resultSelector(self.sourceCurrent, self.selectedEnumerator.Current);
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
self.completionSource.TrySetResult(true);
}
else
{
// dispose selected source and try iterate source.
try
{
self.selectedDisposeAsyncAwaiter = self.selectedEnumerator.DisposeAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.selectedDisposeAsyncAwaiter.IsCompleted)
{
SelectedEnumeratorDisposeAsyncCore(self);
}
else
{
self.selectedDisposeAsyncAwaiter.SourceOnCompleted(selectedEnumeratorDisposeAsyncCoreDelegate, self);
}
}
}
}
static void SelectedEnumeratorDisposeAsyncCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.selectedDisposeAsyncAwaiter))
{
self.selectedEnumerator = null;
self.selectedAwaiter = default;
self.MoveNextSource(); // iterate next source
}
}
public async UniTask DisposeAsync()
{
if (selectedEnumerator != null)
{
await selectedEnumerator.DisposeAsync();
}
if (sourceEnumerator != null)
{
await sourceEnumerator.DisposeAsync();
}
}
}
}
internal sealed class SelectManyAwait<TSource, TCollection, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector1;
readonly Func<TSource, int, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector2;
readonly Func<TSource, TCollection, UniTask<TResult>> resultSelector;
public SelectManyAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector, Func<TSource, TCollection, UniTask<TResult>> resultSelector)
{
this.source = source;
this.selector1 = selector;
this.selector2 = null;
this.resultSelector = resultSelector;
}
public SelectManyAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector, Func<TSource, TCollection, UniTask<TResult>> resultSelector)
{
this.source = source;
this.selector1 = null;
this.selector2 = selector;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector1, selector2, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> sourceMoveNextCoreDelegate = SourceMoveNextCore;
static readonly Action<object> selectedSourceMoveNextCoreDelegate = SeletedSourceMoveNextCore;
static readonly Action<object> selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore;
static readonly Action<object> selectorAwaitCoreDelegate = SelectorAwaitCore;
static readonly Action<object> resultSelectorAwaitCoreDelegate = ResultSelectorAwaitCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector1;
readonly Func<TSource, int, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector2;
readonly Func<TSource, TCollection, UniTask<TResult>> resultSelector;
CancellationToken cancellationToken;
TSource sourceCurrent;
int sourceIndex;
IUniTaskAsyncEnumerator<TSource> sourceEnumerator;
IUniTaskAsyncEnumerator<TCollection> selectedEnumerator;
UniTask<bool>.Awaiter sourceAwaiter;
UniTask<bool>.Awaiter selectedAwaiter;
UniTask.Awaiter selectedDisposeAsyncAwaiter;
// await additional
UniTask<IUniTaskAsyncEnumerable<TCollection>>.Awaiter collectionSelectorAwaiter;
UniTask<TResult>.Awaiter resultSelectorAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector1, Func<TSource, int, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector2, Func<TSource, TCollection, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
{
this.source = source;
this.selector1 = selector1;
this.selector2 = selector2;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
// iterate selected field
if (selectedEnumerator != null)
{
MoveNextSelected();
}
else
{
// iterate source field
if (sourceEnumerator == null)
{
sourceEnumerator = source.GetAsyncEnumerator(cancellationToken);
}
MoveNextSource();
}
return new UniTask<bool>(this, completionSource.Version);
}
void MoveNextSource()
{
try
{
sourceAwaiter = sourceEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (sourceAwaiter.IsCompleted)
{
SourceMoveNextCore(this);
}
else
{
sourceAwaiter.SourceOnCompleted(sourceMoveNextCoreDelegate, this);
}
}
void MoveNextSelected()
{
try
{
selectedAwaiter = selectedEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (selectedAwaiter.IsCompleted)
{
SeletedSourceMoveNextCore(this);
}
else
{
selectedAwaiter.SourceOnCompleted(selectedSourceMoveNextCoreDelegate, this);
}
}
static void SourceMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.sourceAwaiter, out var result))
{
if (result)
{
try
{
self.sourceCurrent = self.sourceEnumerator.Current;
if (self.selector1 != null)
{
self.collectionSelectorAwaiter = self.selector1(self.sourceCurrent).GetAwaiter();
}
else
{
self.collectionSelectorAwaiter = self.selector2(self.sourceCurrent, checked(self.sourceIndex++)).GetAwaiter();
}
if (self.collectionSelectorAwaiter.IsCompleted)
{
SelectorAwaitCore(self);
}
else
{
self.collectionSelectorAwaiter.SourceOnCompleted(selectorAwaitCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void SeletedSourceMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.selectedAwaiter, out var result))
{
if (result)
{
try
{
self.resultSelectorAwaiter = self.resultSelector(self.sourceCurrent, self.selectedEnumerator.Current).GetAwaiter();
if (self.resultSelectorAwaiter.IsCompleted)
{
ResultSelectorAwaitCore(self);
}
else
{
self.resultSelectorAwaiter.SourceOnCompleted(resultSelectorAwaitCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
}
else
{
// dispose selected source and try iterate source.
try
{
self.selectedDisposeAsyncAwaiter = self.selectedEnumerator.DisposeAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.selectedDisposeAsyncAwaiter.IsCompleted)
{
SelectedEnumeratorDisposeAsyncCore(self);
}
else
{
self.selectedDisposeAsyncAwaiter.SourceOnCompleted(selectedEnumeratorDisposeAsyncCoreDelegate, self);
}
}
}
}
static void SelectedEnumeratorDisposeAsyncCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.selectedDisposeAsyncAwaiter))
{
self.selectedEnumerator = null;
self.selectedAwaiter = default;
self.MoveNextSource(); // iterate next source
}
}
static void SelectorAwaitCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.collectionSelectorAwaiter, out var result))
{
self.selectedEnumerator = result.GetAsyncEnumerator(self.cancellationToken);
self.MoveNextSelected(); // iterated selected source.
}
}
static void ResultSelectorAwaitCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultSelectorAwaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public async UniTask DisposeAsync()
{
if (selectedEnumerator != null)
{
await selectedEnumerator.DisposeAsync();
}
if (sourceEnumerator != null)
{
await sourceEnumerator.DisposeAsync();
}
}
}
}
internal sealed class SelectManyAwaitWithCancellation<TSource, TCollection, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector1;
readonly Func<TSource, int, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector2;
readonly Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector;
public SelectManyAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector, Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector)
{
this.source = source;
this.selector1 = selector;
this.selector2 = null;
this.resultSelector = resultSelector;
}
public SelectManyAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector, Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector)
{
this.source = source;
this.selector1 = null;
this.selector2 = selector;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, selector1, selector2, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> sourceMoveNextCoreDelegate = SourceMoveNextCore;
static readonly Action<object> selectedSourceMoveNextCoreDelegate = SeletedSourceMoveNextCore;
static readonly Action<object> selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore;
static readonly Action<object> selectorAwaitCoreDelegate = SelectorAwaitCore;
static readonly Action<object> resultSelectorAwaitCoreDelegate = ResultSelectorAwaitCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector1;
readonly Func<TSource, int, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector2;
readonly Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector;
CancellationToken cancellationToken;
TSource sourceCurrent;
int sourceIndex;
IUniTaskAsyncEnumerator<TSource> sourceEnumerator;
IUniTaskAsyncEnumerator<TCollection> selectedEnumerator;
UniTask<bool>.Awaiter sourceAwaiter;
UniTask<bool>.Awaiter selectedAwaiter;
UniTask.Awaiter selectedDisposeAsyncAwaiter;
// await additional
UniTask<IUniTaskAsyncEnumerable<TCollection>>.Awaiter collectionSelectorAwaiter;
UniTask<TResult>.Awaiter resultSelectorAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector1, Func<TSource, int, CancellationToken, UniTask<IUniTaskAsyncEnumerable<TCollection>>> selector2, Func<TSource, TCollection, CancellationToken, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
{
this.source = source;
this.selector1 = selector1;
this.selector2 = selector2;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
// iterate selected field
if (selectedEnumerator != null)
{
MoveNextSelected();
}
else
{
// iterate source field
if (sourceEnumerator == null)
{
sourceEnumerator = source.GetAsyncEnumerator(cancellationToken);
}
MoveNextSource();
}
return new UniTask<bool>(this, completionSource.Version);
}
void MoveNextSource()
{
try
{
sourceAwaiter = sourceEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (sourceAwaiter.IsCompleted)
{
SourceMoveNextCore(this);
}
else
{
sourceAwaiter.SourceOnCompleted(sourceMoveNextCoreDelegate, this);
}
}
void MoveNextSelected()
{
try
{
selectedAwaiter = selectedEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
return;
}
if (selectedAwaiter.IsCompleted)
{
SeletedSourceMoveNextCore(this);
}
else
{
selectedAwaiter.SourceOnCompleted(selectedSourceMoveNextCoreDelegate, this);
}
}
static void SourceMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.sourceAwaiter, out var result))
{
if (result)
{
try
{
self.sourceCurrent = self.sourceEnumerator.Current;
if (self.selector1 != null)
{
self.collectionSelectorAwaiter = self.selector1(self.sourceCurrent, self.cancellationToken).GetAwaiter();
}
else
{
self.collectionSelectorAwaiter = self.selector2(self.sourceCurrent, checked(self.sourceIndex++), self.cancellationToken).GetAwaiter();
}
if (self.collectionSelectorAwaiter.IsCompleted)
{
SelectorAwaitCore(self);
}
else
{
self.collectionSelectorAwaiter.SourceOnCompleted(selectorAwaitCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void SeletedSourceMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.selectedAwaiter, out var result))
{
if (result)
{
try
{
self.resultSelectorAwaiter = self.resultSelector(self.sourceCurrent, self.selectedEnumerator.Current, self.cancellationToken).GetAwaiter();
if (self.resultSelectorAwaiter.IsCompleted)
{
ResultSelectorAwaitCore(self);
}
else
{
self.resultSelectorAwaiter.SourceOnCompleted(resultSelectorAwaitCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
}
else
{
// dispose selected source and try iterate source.
try
{
self.selectedDisposeAsyncAwaiter = self.selectedEnumerator.DisposeAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.selectedDisposeAsyncAwaiter.IsCompleted)
{
SelectedEnumeratorDisposeAsyncCore(self);
}
else
{
self.selectedDisposeAsyncAwaiter.SourceOnCompleted(selectedEnumeratorDisposeAsyncCoreDelegate, self);
}
}
}
}
static void SelectedEnumeratorDisposeAsyncCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.selectedDisposeAsyncAwaiter))
{
self.selectedEnumerator = null;
self.selectedAwaiter = default;
self.MoveNextSource(); // iterate next source
}
}
static void SelectorAwaitCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.collectionSelectorAwaiter, out var result))
{
self.selectedEnumerator = result.GetAsyncEnumerator(self.cancellationToken);
self.MoveNextSelected(); // iterated selected source.
}
}
static void ResultSelectorAwaitCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultSelectorAwaiter, out var result))
{
self.Current = result;
self.completionSource.TrySetResult(true);
}
}
public async UniTask DisposeAsync()
{
if (selectedEnumerator != null)
{
await selectedEnumerator.DisposeAsync();
}
if (sourceEnumerator != null)
{
await sourceEnumerator.DisposeAsync();
}
}
}
}
}

View File

@@ -1,87 +0,0 @@
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<Boolean> SequenceEqualAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, CancellationToken cancellationToken = default)
{
return SequenceEqualAsync(first, second, EqualityComparer<TSource>.Default, cancellationToken);
}
public static UniTask<Boolean> SequenceEqualAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return SequenceEqual.InvokeAsync(first, second, comparer, cancellationToken);
}
}
internal static class SequenceEqual
{
internal static async UniTask<bool> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
{
var e1 = first.GetAsyncEnumerator(cancellationToken);
try
{
var e2 = second.GetAsyncEnumerator(cancellationToken);
try
{
while (true)
{
if (await e1.MoveNextAsync())
{
if (await e2.MoveNextAsync())
{
if (comparer.Equals(e1.Current, e2.Current))
{
continue;
}
else
{
return false;
}
}
else
{
// e2 is finished, but e1 has value
return false;
}
}
else
{
// e1 is finished, e2?
if (await e2.MoveNextAsync())
{
return false;
}
else
{
return true;
}
}
}
}
finally
{
if (e2 != null)
{
await e2.DisposeAsync();
}
}
}
finally
{
if (e1 != null)
{
await e1.DisposeAsync();
}
}
}
}
}

View File

@@ -1,230 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<TSource> SingleAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return SingleOperator.InvokeAsync(source, cancellationToken, false);
}
public static UniTask<TSource> SingleAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return SingleOperator.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> SingleAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return SingleOperator.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> SingleAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return SingleOperator.InvokeAsync(source, predicate, cancellationToken, false);
}
public static UniTask<TSource> SingleOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return SingleOperator.InvokeAsync(source, cancellationToken, true);
}
public static UniTask<TSource> SingleOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return SingleOperator.InvokeAsync(source, predicate, cancellationToken, true);
}
public static UniTask<TSource> SingleOrDefaultAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return SingleOperator.InvokeAsync(source, predicate, cancellationToken, true);
}
public static UniTask<TSource> SingleOrDefaultAwaitWithCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return SingleOperator.InvokeAsync(source, predicate, cancellationToken, true);
}
}
internal static class SingleOperator
{
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
if (await e.MoveNextAsync())
{
var v = e.Current;
if (!await e.MoveNextAsync())
{
return v;
}
throw Error.MoreThanOneElement();
}
else
{
if (defaultIfEmpty)
{
return default;
}
else
{
throw Error.NoElements();
}
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
bool found = false;
while (await e.MoveNextAsync())
{
var v = e.Current;
if (predicate(v))
{
if (found)
{
throw Error.MoreThanOneElement();
}
else
{
found = true;
value = v;
}
}
}
if (found || defaultIfEmpty)
{
return value;
}
throw Error.NoElements();
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
bool found = false;
while (await e.MoveNextAsync())
{
var v = e.Current;
if (await predicate(v))
{
if (found)
{
throw Error.MoreThanOneElement();
}
else
{
found = true;
value = v;
}
}
}
if (found || defaultIfEmpty)
{
return value;
}
throw Error.NoElements();
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
public static async UniTask<TSource> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate, CancellationToken cancellationToken, bool defaultIfEmpty)
{
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
TSource value = default;
bool found = false;
while (await e.MoveNextAsync())
{
var v = e.Current;
if (await predicate(v, cancellationToken))
{
if (found)
{
throw Error.MoreThanOneElement();
}
else
{
found = true;
value = v;
}
}
}
if (found || defaultIfEmpty)
{
return value;
}
throw Error.NoElements();
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
}
}

View File

@@ -1,69 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Skip<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Skip<TSource>(source, count);
}
}
internal sealed class Skip<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public Skip(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly int count;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.count = count;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (count <= checked(index++))
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
else
{
result = false;
return true;
}
}
}
}
}

View File

@@ -1,157 +0,0 @@
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 IUniTaskAsyncEnumerable<TSource> SkipLast<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
// non skip.
if (count <= 0)
{
return source;
}
return new SkipLast<TSource>(source, count);
}
}
internal sealed class SkipLast<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public SkipLast(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
Queue<TSource> queue;
bool continueNext;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
{
this.source = source;
this.count = count;
this.cancellationToken = cancellationToken;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
queue = new Queue<TSource>();
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
void SourceMoveNext()
{
try
{
LOOP:
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
if (self.queue.Count == self.count)
{
self.continueNext = false;
var deq = self.queue.Dequeue();
self.Current = deq;
self.queue.Enqueue(self.enumerator.Current);
self.completionSource.TrySetResult(true);
}
else
{
self.queue.Enqueue(self.enumerator.Current);
if (!self.continueNext)
{
self.SourceMoveNext();
}
}
}
else
{
self.continueNext = false;
self.completionSource.TrySetResult(false);
}
}
else
{
self.continueNext = false;
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,379 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> SkipWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new SkipWhile<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new SkipWhileInt<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new SkipWhileAwait<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new SkipWhileIntAwait<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new SkipWhileAwaitWithCancellation<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new SkipWhileIntAwaitWithCancellation<TSource>(source, predicate);
}
}
internal sealed class SkipWhile<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, bool> predicate;
public SkipWhile(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
Func<TSource, bool> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate == null || !predicate(SourceCurrent))
{
predicate = null;
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class SkipWhileInt<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, bool> predicate;
public SkipWhileInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
Func<TSource, int, bool> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate == null || !predicate(SourceCurrent, checked(index++)))
{
predicate = null;
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class SkipWhileAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<bool>> predicate;
public SkipWhileAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
Func<TSource, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
if (predicate == null)
{
return CompletedTasks.False;
}
return predicate(sourceCurrent);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
if (!awaitResult)
{
predicate = null;
Current = SourceCurrent;
terminateIteration= false;
return true;
}
else
{
terminateIteration= false;
return false;
}
}
}
}
internal sealed class SkipWhileIntAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, UniTask<bool>> predicate;
public SkipWhileIntAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
Func<TSource, int, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
if (predicate == null)
{
return CompletedTasks.False;
}
return predicate(sourceCurrent, checked(index++));
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration= false;
if (!awaitResult)
{
predicate = null;
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class SkipWhileAwaitWithCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<bool>> predicate;
public SkipWhileAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
Func<TSource, CancellationToken, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
if (predicate == null)
{
return CompletedTasks.False;
}
return predicate(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration= false;
if (!awaitResult)
{
predicate = null;
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class SkipWhileIntAwaitWithCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
public SkipWhileIntAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
if (predicate == null)
{
return CompletedTasks.False;
}
return predicate(sourceCurrent, checked(index++), cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration= false;
if (!awaitResult)
{
predicate = null;
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,167 +0,0 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#
var types = new[]
{
typeof(int),
typeof(long),
typeof(float),
typeof(double),
typeof(decimal),
typeof(int?),
typeof(long?),
typeof(float?),
typeof(double?),
typeof(decimal?),
};
Func<Type, bool> IsNullable = x => x.IsGenericType;
Func<Type, string> TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name;
Func<Type, string> WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : "";
#>
using System;
using System.Threading;
using Cysharp.Threading.Tasks.Internal;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
<# foreach(var t in types) { #>
public static UniTask<<#= TypeName(t) #>> SumAsync(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Sum.InvokeAsync(source, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> SumAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Sum.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> SumAwaitAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Sum.InvokeAsync(source, selector, cancellationToken);
}
public static UniTask<<#= TypeName(t) #>> SumAwaitCancellationAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(source, nameof(selector));
return Sum.InvokeAsync(source, selector, cancellationToken);
}
<# } #>
}
internal static class Sum
{
<# foreach(var t in types) { #>
public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += e.Current<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
public static async UniTask<<#= TypeName(t) #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, <#= TypeName(t) #>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += selector(e.Current)<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
public static async UniTask<<#= TypeName(t) #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += (await selector(e.Current))<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
public static async UniTask<<#= TypeName(t) #>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<<#= TypeName(t) #>>> selector, CancellationToken cancellationToken)
{
<#= TypeName(t) #> sum = default;
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
sum += (await selector(e.Current, cancellationToken))<#= WithSuffix(t) #>;
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return sum;
}
<# } #>
}
}

View File

@@ -1,69 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Take<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Take<TSource>(source, count);
}
}
internal sealed class Take<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public Take(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly int count;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.count = count;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (checked(index++) < count)
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = false;
return true;
}
}
else
{
result = false;
return true;
}
}
}
}
}

View File

@@ -1,173 +0,0 @@
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 IUniTaskAsyncEnumerable<TSource> TakeLast<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
// non take.
if (count <= 0)
{
return Empty<TSource>();
}
return new TakeLast<TSource>(source, count);
}
}
internal sealed class TakeLast<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public TakeLast(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
Queue<TSource> queue;
bool iterateCompleted;
bool continueNext;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
{
this.source = source;
this.count = count;
this.cancellationToken = cancellationToken;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
queue = new Queue<TSource>();
}
completionSource.Reset();
SourceMoveNext();
return new UniTask<bool>(this, completionSource.Version);
}
void SourceMoveNext()
{
if (iterateCompleted)
{
if (queue.Count > 0)
{
Current = queue.Dequeue();
completionSource.TrySetResult(true);
}
else
{
completionSource.TrySetResult(false);
}
return;
}
try
{
LOOP:
awaiter = enumerator.MoveNextAsync().GetAwaiter();
if (awaiter.IsCompleted)
{
continueNext = true;
MoveNextCore(this);
if (continueNext)
{
continueNext = false;
goto LOOP; // avoid recursive
}
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
}
catch (Exception ex)
{
completionSource.TrySetException(ex);
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.awaiter, out var result))
{
if (result)
{
if (self.queue.Count < self.count)
{
self.queue.Enqueue(self.enumerator.Current);
if (!self.continueNext)
{
self.SourceMoveNext();
}
}
else
{
self.queue.Dequeue();
self.queue.Enqueue(self.enumerator.Current);
if (!self.continueNext)
{
self.SourceMoveNext();
}
}
}
else
{
self.continueNext = false;
self.iterateCompleted = true;
self.SourceMoveNext();
}
}
else
{
self.continueNext = false;
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@@ -1,342 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> TakeWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new TakeWhile<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new TakeWhileInt<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new TakeWhileAwait<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new TakeWhileIntAwait<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new TakeWhileAwaitWithCancellation<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new TakeWhileIntAwaitWithCancellation<TSource>(source, predicate);
}
}
internal sealed class TakeWhile<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, bool> predicate;
public TakeWhile(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
Func<TSource, bool> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate(SourceCurrent))
{
Current = SourceCurrent;
result = true;
return true;
}
}
result = false;
return true;
}
}
}
internal sealed class TakeWhileInt<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, bool> predicate;
public TakeWhileInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly Func<TSource, int, bool> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate(SourceCurrent, checked(index++)))
{
Current = SourceCurrent;
result = true;
return true;
}
}
result = false;
return true;
}
}
}
internal sealed class TakeWhileAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<bool>> predicate;
public TakeWhileAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
Func<TSource, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
if (awaitResult)
{
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = true;
return false;
}
}
}
}
internal sealed class TakeWhileIntAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, UniTask<bool>> predicate;
public TakeWhileIntAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, int, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, checked(index++));
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
if (awaitResult)
{
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = true;
return false;
}
}
}
}
internal sealed class TakeWhileAwaitWithCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<bool>> predicate;
public TakeWhileAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
Func<TSource, CancellationToken, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
if (awaitResult)
{
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = true;
return false;
}
}
}
}
internal sealed class TakeWhileIntAwaitWithCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
public TakeWhileIntAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, checked(index++), cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
if (awaitResult)
{
Current = SourceCurrent;
terminateIteration = false;
return true;
}
else
{
terminateIteration = true;
return false;
}
}
}
}
}

View File

@@ -1,54 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TValue> Throw<TValue>(Exception exception)
{
return new Throw<TValue>(exception);
}
}
internal class Throw<TValue> : IUniTaskAsyncEnumerable<TValue>
{
readonly Exception exception;
public Throw(Exception exception)
{
this.exception = exception;
}
public IUniTaskAsyncEnumerator<TValue> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(exception, cancellationToken);
}
class Enumerator : IUniTaskAsyncEnumerator<TValue>
{
readonly Exception exception;
CancellationToken cancellationToken;
public Enumerator(Exception exception, CancellationToken cancellationToken)
{
this.exception = exception;
this.cancellationToken = cancellationToken;
}
public TValue Current => default;
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
return UniTask.FromException<bool>(exception);
}
public UniTask DisposeAsync()
{
return default;
}
}
}
}

View File

@@ -1,60 +0,0 @@
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<TSource[]> ToArrayAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Cysharp.Threading.Tasks.Linq.ToArray.InvokeAsync(source, cancellationToken);
}
}
internal static class ToArray
{
internal static async UniTask<TSource[]> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
TSource[] result = default;
IUniTaskAsyncEnumerator<TSource> e = default;
try
{
e = source.GetAsyncEnumerator(cancellationToken);
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
result = Array.Empty<TSource>();
}
else
{
result = new TSource[i];
Array.Copy(array, result, i);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
return result;
}
}
}

View File

@@ -1,278 +0,0 @@
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<Dictionary<TKey, TSource>> ToDictionaryAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return ToDictionary.InvokeAsync(source, keySelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<Dictionary<TKey, TSource>> ToDictionaryAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToDictionary.InvokeAsync(source, keySelector, comparer, cancellationToken);
}
public static UniTask<Dictionary<TKey, TElement>> ToDictionaryAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return ToDictionary.InvokeAsync(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<Dictionary<TKey, TElement>> ToDictionaryAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToDictionary.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken);
}
public static UniTask<Dictionary<TKey, TSource>> ToDictionaryAwaitAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return ToDictionary.InvokeAsync(source, keySelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<Dictionary<TKey, TSource>> ToDictionaryAwaitAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToDictionary.InvokeAsync(source, keySelector, comparer, cancellationToken);
}
public static UniTask<Dictionary<TKey, TElement>> ToDictionaryAwaitAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return ToDictionary.InvokeAsync(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<Dictionary<TKey, TElement>> ToDictionaryAwaitAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToDictionary.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken);
}
public static UniTask<Dictionary<TKey, TSource>> ToDictionaryAwaitWithCancellationAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return ToDictionary.InvokeAsync(source, keySelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<Dictionary<TKey, TSource>> ToDictionaryAwaitWithCancellationAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToDictionary.InvokeAsync(source, keySelector, comparer, cancellationToken);
}
public static UniTask<Dictionary<TKey, TElement>> ToDictionaryAwaitWithCancellationAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return ToDictionary.InvokeAsync(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<Dictionary<TKey, TElement>> ToDictionaryAwaitWithCancellationAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToDictionary.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken);
}
}
internal static class ToDictionary
{
internal static async UniTask<Dictionary<TKey, TSource>> InvokeAsync<TSource, TKey>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, TSource>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
var key = keySelector(v);
dict.Add(key, v);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return dict;
}
internal static async UniTask<Dictionary<TKey, TElement>> InvokeAsync<TSource, TKey, TElement>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, TElement>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
var key = keySelector(v);
var value = elementSelector(v);
dict.Add(key, value);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return dict;
}
// with await
internal static async UniTask<Dictionary<TKey, TSource>> InvokeAsync<TSource, TKey>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, TSource>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
var key = await keySelector(v);
dict.Add(key, v);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return dict;
}
internal static async UniTask<Dictionary<TKey, TElement>> InvokeAsync<TSource, TKey, TElement>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, TElement>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
var key = await keySelector(v);
var value = await elementSelector(v);
dict.Add(key, value);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return dict;
}
// with cancellation
internal static async UniTask<Dictionary<TKey, TSource>> InvokeAsync<TSource, TKey>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, TSource>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
var key = await keySelector(v, cancellationToken);
dict.Add(key, v);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return dict;
}
internal static async UniTask<Dictionary<TKey, TElement>> InvokeAsync<TSource, TKey, TElement>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, TElement>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
var v = e.Current;
var key = await keySelector(v, cancellationToken);
var value = await elementSelector(v, cancellationToken);
dict.Add(key, value);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return dict;
}
}
}

View File

@@ -1,50 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Collections.Generic;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<HashSet<TSource>> ToHashSetAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, EqualityComparer<TSource>.Default, cancellationToken);
}
public static UniTask<HashSet<TSource>> ToHashSetAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, comparer, cancellationToken);
}
}
internal static class ToHashSet
{
internal static async UniTask<HashSet<TSource>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
{
var set = new HashSet<TSource>(comparer);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
set.Add(e.Current);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return set;
}
}
}

View File

@@ -1,42 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Collections.Generic;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<List<TSource>> ToListAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
return Cysharp.Threading.Tasks.Linq.ToList.InvokeAsync(source, cancellationToken);
}
}
internal static class ToList
{
internal static async UniTask<List<TSource>> InvokeAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
var list = new List<TSource>();
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
while (await e.MoveNextAsync())
{
list.Add(e.Current);
}
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
return list;
}
}
}

View File

@@ -1,554 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static UniTask<ILookup<TKey, TSource>> ToLookupAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return ToLookup.InvokeAsync(source, keySelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<ILookup<TKey, TSource>> ToLookupAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToLookup.InvokeAsync(source, keySelector, comparer, cancellationToken);
}
public static UniTask<ILookup<TKey, TElement>> ToLookupAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return ToLookup.InvokeAsync(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<ILookup<TKey, TElement>> ToLookupAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToLookup.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken);
}
public static UniTask<ILookup<TKey, TSource>> ToLookupAwaitAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return ToLookup.InvokeAsync(source, keySelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<ILookup<TKey, TSource>> ToLookupAwaitAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToLookup.InvokeAsync(source, keySelector, comparer, cancellationToken);
}
public static UniTask<ILookup<TKey, TElement>> ToLookupAwaitAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return ToLookup.InvokeAsync(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<ILookup<TKey, TElement>> ToLookupAwaitAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToLookup.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken);
}
public static UniTask<ILookup<TKey, TSource>> ToLookupAwaitWithCancellationAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
return ToLookup.InvokeAsync(source, keySelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<ILookup<TKey, TSource>> ToLookupAwaitWithCancellationAsync<TSource, TKey>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToLookup.InvokeAsync(source, keySelector, comparer, cancellationToken);
}
public static UniTask<ILookup<TKey, TElement>> ToLookupAwaitWithCancellationAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
return ToLookup.InvokeAsync(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
}
public static UniTask<ILookup<TKey, TElement>> ToLookupAwaitWithCancellationAsync<TSource, TKey, TElement>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken = default)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(keySelector, nameof(keySelector));
Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
return ToLookup.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken);
}
}
internal static class ToLookup
{
internal static async UniTask<ILookup<TKey, TSource>> InvokeAsync<TSource, TKey>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
var e = source.GetAsyncEnumerator(cancellationToken);
try
{
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
return Lookup<TKey, TSource>.CreateEmpty();
}
else
{
return Lookup<TKey, TSource>.Create(new ArraySegment<TSource>(array, 0, i), keySelector, comparer);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<ILookup<TKey, TElement>> InvokeAsync<TSource, TKey, TElement>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
IUniTaskAsyncEnumerator<TSource> e = default;
try
{
e = source.GetAsyncEnumerator(cancellationToken);
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
return Lookup<TKey, TElement>.CreateEmpty();
}
else
{
return Lookup<TKey, TElement>.Create(new ArraySegment<TSource>(array, 0, i), keySelector, elementSelector, comparer);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
}
// with await
internal static async UniTask<ILookup<TKey, TSource>> InvokeAsync<TSource, TKey>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
IUniTaskAsyncEnumerator<TSource> e = default;
try
{
e = source.GetAsyncEnumerator(cancellationToken);
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
return Lookup<TKey, TSource>.CreateEmpty();
}
else
{
return await Lookup<TKey, TSource>.CreateAsync(new ArraySegment<TSource>(array, 0, i), keySelector, comparer);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<ILookup<TKey, TElement>> InvokeAsync<TSource, TKey, TElement>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
IUniTaskAsyncEnumerator<TSource> e = default;
try
{
e = source.GetAsyncEnumerator(cancellationToken);
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
return Lookup<TKey, TElement>.CreateEmpty();
}
else
{
return await Lookup<TKey, TElement>.CreateAsync(new ArraySegment<TSource>(array, 0, i), keySelector, elementSelector, comparer);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
}
// with cancellation
internal static async UniTask<ILookup<TKey, TSource>> InvokeAsync<TSource, TKey>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
IUniTaskAsyncEnumerator<TSource> e = default;
try
{
e = source.GetAsyncEnumerator(cancellationToken);
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
return Lookup<TKey, TSource>.CreateEmpty();
}
else
{
return await Lookup<TKey, TSource>.CreateAsync(new ArraySegment<TSource>(array, 0, i), keySelector, comparer, cancellationToken);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal static async UniTask<ILookup<TKey, TElement>> InvokeAsync<TSource, TKey, TElement>(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);
IUniTaskAsyncEnumerator<TSource> e = default;
try
{
e = source.GetAsyncEnumerator(cancellationToken);
var i = 0;
while (await e.MoveNextAsync())
{
ArrayPoolUtil.EnsureCapacity(ref array, i, pool);
array[i++] = e.Current;
}
if (i == 0)
{
return Lookup<TKey, TElement>.CreateEmpty();
}
else
{
return await Lookup<TKey, TElement>.CreateAsync(new ArraySegment<TSource>(array, 0, i), keySelector, elementSelector, comparer, cancellationToken);
}
}
finally
{
pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType<TSource>());
if (e != null)
{
await e.DisposeAsync();
}
}
}
// Lookup
class Lookup<TKey, TElement> : ILookup<TKey, TElement>
{
static readonly Lookup<TKey, TElement> empty = new Lookup<TKey, TElement>(new Dictionary<TKey, Grouping<TKey, TElement>>());
// original lookup keeps order but this impl does not(dictionary not guarantee)
readonly Dictionary<TKey, Grouping<TKey, TElement>> dict;
Lookup(Dictionary<TKey, Grouping<TKey, TElement>> dict)
{
this.dict = dict;
}
public static Lookup<TKey, TElement> CreateEmpty()
{
return empty;
}
public static Lookup<TKey, TElement> Create(ArraySegment<TElement> source, Func<TElement, TKey> keySelector, IEqualityComparer<TKey> comparer)
{
var dict = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
var arr = source.Array;
var c = source.Count;
for (int i = source.Offset; i < c; i++)
{
var key = keySelector(arr[i]);
if (!dict.TryGetValue(key, out var list))
{
list = new Grouping<TKey, TElement>(key);
dict[key] = list;
}
list.Add(arr[i]);
}
return new Lookup<TKey, TElement>(dict);
}
public static Lookup<TKey, TElement> Create<TSource>(ArraySegment<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
{
var dict = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
var arr = source.Array;
var c = source.Count;
for (int i = source.Offset; i < c; i++)
{
var key = keySelector(arr[i]);
var elem = elementSelector(arr[i]);
if (!dict.TryGetValue(key, out var list))
{
list = new Grouping<TKey, TElement>(key);
dict[key] = list;
}
list.Add(elem);
}
return new Lookup<TKey, TElement>(dict);
}
public static async UniTask<Lookup<TKey, TElement>> CreateAsync(ArraySegment<TElement> source, Func<TElement, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer)
{
var dict = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
var arr = source.Array;
var c = source.Count;
for (int i = source.Offset; i < c; i++)
{
var key = await keySelector(arr[i]);
if (!dict.TryGetValue(key, out var list))
{
list = new Grouping<TKey, TElement>(key);
dict[key] = list;
}
list.Add(arr[i]);
}
return new Lookup<TKey, TElement>(dict);
}
public static async UniTask<Lookup<TKey, TElement>> CreateAsync<TSource>(ArraySegment<TSource> source, Func<TSource, UniTask<TKey>> keySelector, Func<TSource, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer)
{
var dict = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
var arr = source.Array;
var c = source.Count;
for (int i = source.Offset; i < c; i++)
{
var key = await keySelector(arr[i]);
var elem = await elementSelector(arr[i]);
if (!dict.TryGetValue(key, out var list))
{
list = new Grouping<TKey, TElement>(key);
dict[key] = list;
}
list.Add(elem);
}
return new Lookup<TKey, TElement>(dict);
}
public static async UniTask<Lookup<TKey, TElement>> CreateAsync(ArraySegment<TElement> source, Func<TElement, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
var arr = source.Array;
var c = source.Count;
for (int i = source.Offset; i < c; i++)
{
var key = await keySelector(arr[i], cancellationToken);
if (!dict.TryGetValue(key, out var list))
{
list = new Grouping<TKey, TElement>(key);
dict[key] = list;
}
list.Add(arr[i]);
}
return new Lookup<TKey, TElement>(dict);
}
public static async UniTask<Lookup<TKey, TElement>> CreateAsync<TSource>(ArraySegment<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, Func<TSource, CancellationToken, UniTask<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
{
var dict = new Dictionary<TKey, Grouping<TKey, TElement>>(comparer);
var arr = source.Array;
var c = source.Count;
for (int i = source.Offset; i < c; i++)
{
var key = await keySelector(arr[i], cancellationToken);
var elem = await elementSelector(arr[i], cancellationToken);
if (!dict.TryGetValue(key, out var list))
{
list = new Grouping<TKey, TElement>(key);
dict[key] = list;
}
list.Add(elem);
}
return new Lookup<TKey, TElement>(dict);
}
public IEnumerable<TElement> this[TKey key] => dict.TryGetValue(key, out var g) ? g : Enumerable.Empty<TElement>();
public int Count => dict.Count;
public bool Contains(TKey key)
{
return dict.ContainsKey(key);
}
public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
{
return dict.Values.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return dict.Values.GetEnumerator();
}
}
class Grouping<TKey, TElement> : IGrouping<TKey, TElement> // , IUniTaskAsyncGrouping<TKey, TElement>
{
readonly List<TElement> elements;
public TKey Key { get; private set; }
public Grouping(TKey key)
{
this.Key = key;
this.elements = new List<TElement>();
}
public void Add(TElement value)
{
elements.Add(value);
}
public IEnumerator<TElement> GetEnumerator()
{
return elements.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return elements.GetEnumerator();
}
public IUniTaskAsyncEnumerator<TElement> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return this.ToUniTaskAsyncEnumerable().GetAsyncEnumerator(cancellationToken);
}
public override string ToString()
{
return "Key: " + Key + ", Count: " + elements.Count;
}
}
}
}

View File

@@ -1,97 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IObservable<TSource> ToObservable<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new ToObservable<TSource>(source);
}
}
internal sealed class ToObservable<T> : IObservable<T>
{
readonly IUniTaskAsyncEnumerable<T> source;
public ToObservable(IUniTaskAsyncEnumerable<T> source)
{
this.source = source;
}
public IDisposable Subscribe(IObserver<T> observer)
{
var ctd = new CancellationTokenDisposable();
RunAsync(source, observer, ctd.Token).Forget();
return ctd;
}
static async UniTaskVoid RunAsync(IUniTaskAsyncEnumerable<T> src, IObserver<T> observer, CancellationToken cancellationToken)
{
// cancellationToken.IsCancellationRequested is called when Rx's Disposed.
// when disposed, finish silently.
var e = src.GetAsyncEnumerator(cancellationToken);
try
{
bool hasNext;
do
{
try
{
hasNext = await e.MoveNextAsync();
}
catch (Exception ex)
{
if (cancellationToken.IsCancellationRequested)
{
return;
}
observer.OnError(ex);
return;
}
if (hasNext)
{
observer.OnNext(e.Current);
}
else
{
observer.OnCompleted();
return;
}
} while (!cancellationToken.IsCancellationRequested);
}
finally
{
if (e != null)
{
await e.DisposeAsync();
}
}
}
internal sealed class CancellationTokenDisposable : IDisposable
{
readonly CancellationTokenSource cts = new CancellationTokenSource();
public CancellationToken Token => cts.Token;
public void Dispose()
{
if (!cts.IsCancellationRequested)
{
cts.Cancel();
}
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,26 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System.Collections.Generic;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Union<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
return Union<TSource>(first, second, EqualityComparer<TSource>.Default);
}
public static IUniTaskAsyncEnumerable<TSource> Union<TSource>(this IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(comparer, nameof(comparer));
// improv without combinate?
return first.Concat(second).Distinct(comparer);
}
}
}

View File

@@ -1,355 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new Where<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> Where<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereInt<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwait<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwaitInt<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwaitCancellation<TSource>(source, predicate);
}
public static IUniTaskAsyncEnumerable<TSource> WhereAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(predicate, nameof(predicate));
return new WhereAwaitIntCancellation<TSource>(source, predicate);
}
}
internal sealed class Where<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, bool> predicate;
public Where(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly Func<TSource, bool> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate(SourceCurrent))
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class WhereInt<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, bool> predicate;
public WhereInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly Func<TSource, int, bool> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (predicate(SourceCurrent, checked(index++)))
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
result = false;
return true;
}
}
}
internal sealed class WhereAwait<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, UniTask<bool>> predicate;
public WhereAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration = false;
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class WhereAwaitInt<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, UniTask<bool>> predicate;
public WhereAwaitInt(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, int, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, checked(index++));
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration = false;
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class WhereAwaitCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, CancellationToken, UniTask<bool>> predicate;
public WhereAwaitCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, CancellationToken, UniTask<bool>> predicate;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration = false;
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
internal sealed class WhereAwaitIntCancellation<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
public WhereAwaitIntCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate)
{
this.source = source;
this.predicate = predicate;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, predicate, cancellationToken);
}
class Enumerator : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, bool>
{
readonly Func<TSource, int, CancellationToken, UniTask<bool>> predicate;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<bool>> predicate, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.predicate = predicate;
}
protected override UniTask<bool> TransformAsync(TSource sourceCurrent)
{
return predicate(sourceCurrent, checked(index++), cancellationToken);
}
protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{
terminateIteration = false;
if (awaitResult)
{
Current = SourceCurrent;
return true;
}
else
{
return false;
}
}
}
}
}

View File

@@ -1,535 +0,0 @@
using Cysharp.Threading.Tasks.Internal;
using System;
using System.Threading;
namespace Cysharp.Threading.Tasks.Linq
{
public static partial class UniTaskAsyncEnumerable
{
public static IUniTaskAsyncEnumerable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
return Zip(first, second, (x, y) => (x, y));
}
public static IUniTaskAsyncEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector));
return new Zip<TFirst, TSecond, TResult>(first, second, resultSelector);
}
public static IUniTaskAsyncEnumerable<TResult> ZipAwait<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new ZipAwait<TFirst, TSecond, TResult>(first, second, selector);
}
public static IUniTaskAsyncEnumerable<TResult> ZipAwaitWithCancellation<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> selector)
{
Error.ThrowArgumentNullException(first, nameof(first));
Error.ThrowArgumentNullException(second, nameof(second));
Error.ThrowArgumentNullException(selector, nameof(selector));
return new ZipAwaitWithCancellation<TFirst, TSecond, TResult>(first, second, selector);
}
}
internal sealed class Zip<TFirst, TSecond, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, TResult> resultSelector;
public Zip(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, TResult> resultSelector;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TFirst> firstEnumerator;
IUniTaskAsyncEnumerator<TSecond> secondEnumerator;
UniTask<bool>.Awaiter firstAwaiter;
UniTask<bool>.Awaiter secondAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector, CancellationToken cancellationToken)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
if (firstEnumerator == null)
{
firstEnumerator = first.GetAsyncEnumerator(cancellationToken);
secondEnumerator = second.GetAsyncEnumerator(cancellationToken);
}
firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter();
if (firstAwaiter.IsCompleted)
{
FirstMoveNextCore(this);
}
else
{
firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void FirstMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.firstAwaiter, out var result))
{
if (result)
{
try
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.secondAwaiter.IsCompleted)
{
SecondMoveNextCore(self);
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void SecondMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.secondAwaiter, out var result))
{
if (result)
{
try
{
self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current);
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(true);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
public async UniTask DisposeAsync()
{
if (firstEnumerator != null)
{
await firstEnumerator.DisposeAsync();
}
if (secondEnumerator != null)
{
await secondEnumerator.DisposeAsync();
}
}
}
}
internal sealed class ZipAwait<TFirst, TSecond, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, UniTask<TResult>> resultSelector;
public ZipAwait(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> resultSelector)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
static readonly Action<object> resultAwaitCoreDelegate = ResultAwaitCore;
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, UniTask<TResult>> resultSelector;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TFirst> firstEnumerator;
IUniTaskAsyncEnumerator<TSecond> secondEnumerator;
UniTask<bool>.Awaiter firstAwaiter;
UniTask<bool>.Awaiter secondAwaiter;
UniTask<TResult>.Awaiter resultAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
if (firstEnumerator == null)
{
firstEnumerator = first.GetAsyncEnumerator(cancellationToken);
secondEnumerator = second.GetAsyncEnumerator(cancellationToken);
}
firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter();
if (firstAwaiter.IsCompleted)
{
FirstMoveNextCore(this);
}
else
{
firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void FirstMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.firstAwaiter, out var result))
{
if (result)
{
try
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.secondAwaiter.IsCompleted)
{
SecondMoveNextCore(self);
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void SecondMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.secondAwaiter, out var result))
{
if (result)
{
try
{
self.resultAwaiter = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current).GetAwaiter();
if (self.resultAwaiter.IsCompleted)
{
ResultAwaitCore(self);
}
else
{
self.resultAwaiter.SourceOnCompleted(resultAwaitCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void ResultAwaitCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultAwaiter, out var result))
{
self.Current = result;
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(true);
}
}
}
public async UniTask DisposeAsync()
{
if (firstEnumerator != null)
{
await firstEnumerator.DisposeAsync();
}
if (secondEnumerator != null)
{
await secondEnumerator.DisposeAsync();
}
}
}
}
internal sealed class ZipAwaitWithCancellation<TFirst, TSecond, TResult> : IUniTaskAsyncEnumerable<TResult>
{
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector;
public ZipAwaitWithCancellation(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
}
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(first, second, resultSelector, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
{
static readonly Action<object> firstMoveNextCoreDelegate = FirstMoveNextCore;
static readonly Action<object> secondMoveNextCoreDelegate = SecondMoveNextCore;
static readonly Action<object> resultAwaitCoreDelegate = ResultAwaitCore;
readonly IUniTaskAsyncEnumerable<TFirst> first;
readonly IUniTaskAsyncEnumerable<TSecond> second;
readonly Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TFirst> firstEnumerator;
IUniTaskAsyncEnumerator<TSecond> secondEnumerator;
UniTask<bool>.Awaiter firstAwaiter;
UniTask<bool>.Awaiter secondAwaiter;
UniTask<TResult>.Awaiter resultAwaiter;
public Enumerator(IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> resultSelector, CancellationToken cancellationToken)
{
this.first = first;
this.second = second;
this.resultSelector = resultSelector;
this.cancellationToken = cancellationToken;
}
public TResult Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
completionSource.Reset();
if (firstEnumerator == null)
{
firstEnumerator = first.GetAsyncEnumerator(cancellationToken);
secondEnumerator = second.GetAsyncEnumerator(cancellationToken);
}
firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter();
if (firstAwaiter.IsCompleted)
{
FirstMoveNextCore(this);
}
else
{
firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
static void FirstMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.firstAwaiter, out var result))
{
if (result)
{
try
{
self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter();
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
return;
}
if (self.secondAwaiter.IsCompleted)
{
SecondMoveNextCore(self);
}
else
{
self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void SecondMoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.secondAwaiter, out var result))
{
if (result)
{
try
{
self.resultAwaiter = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current, self.cancellationToken).GetAwaiter();
if (self.resultAwaiter.IsCompleted)
{
ResultAwaitCore(self);
}
else
{
self.resultAwaiter.SourceOnCompleted(resultAwaitCoreDelegate, self);
}
}
catch (Exception ex)
{
self.completionSource.TrySetException(ex);
}
}
else
{
self.completionSource.TrySetResult(false);
}
}
}
static void ResultAwaitCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResult(self.resultAwaiter, out var result))
{
self.Current = result;
if (self.cancellationToken.IsCancellationRequested)
{
self.completionSource.TrySetCanceled(self.cancellationToken);
}
else
{
self.completionSource.TrySetResult(true);
}
}
}
public async UniTask DisposeAsync()
{
if (firstEnumerator != null)
{
await firstEnumerator.DisposeAsync();
}
if (secondEnumerator != null)
{
await secondEnumerator.DisposeAsync();
}
}
}
}
}

View File

@@ -14,54 +14,4 @@
<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" />
</ItemGroup>
<ItemGroup>
<None Include="Linq\MinMax.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>MinMax.tt</DependentUpon>
</None>
<None Include="Linq\Sum.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Sum.tt</DependentUpon>
</None>
</ItemGroup>
<ItemGroup>
<None Update="Linq\Average.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Average.cs</LastGenOutput>
</None>
<None Update="Linq\MinMax.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>MinMax.cs</LastGenOutput>
</None>
<None Update="Linq\Sum.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Sum.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Linq\Average.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Average.tt</DependentUpon>
</Compile>
<Compile Update="Linq\MinMax.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>MinMax.tt</DependentUpon>
</Compile>
<Compile Update="Linq\Sum.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Sum.tt</DependentUpon>
</Compile>
</ItemGroup>
</Project>