mirror of
https://gitee.com/jisol/jisol-game/
synced 2025-11-12 00:58:16 +00:00
提交
This commit is contained in:
318
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Aggregate.cs
Normal file
318
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Aggregate.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
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.AggregateAsync(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.AggregateAsync(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.AggregateAsync(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.AggregateAwaitAsync(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.AggregateAwaitAsync(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.AggregateAwaitAsync(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.AggregateAwaitWithCancellationAsync(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.AggregateAwaitWithCancellationAsync(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.AggregateAwaitWithCancellationAsync(source, seed, accumulator, resultSelector, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Aggregate
|
||||
{
|
||||
internal static async UniTask<TSource> AggregateAsync<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> AggregateAsync<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> AggregateAsync<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> AggregateAwaitAsync<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> AggregateAwaitAsync<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> AggregateAwaitAsync<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> AggregateAwaitWithCancellationAsync<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> AggregateAwaitWithCancellationAsync<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> AggregateAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dc68c05a4228c643937f6ebd185bcca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
108
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/All.cs
Normal file
108
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/All.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
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.AllAsync(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.AllAwaitAsync(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.AllAwaitWithCancellationAsync(source, predicate, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class All
|
||||
{
|
||||
internal static async UniTask<bool> AllAsync<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> AllAwaitAsync<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> AllAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/All.cs.meta
Normal file
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/All.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7271437e0033af2448b600ee248924dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
136
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Any.cs
Normal file
136
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Any.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
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.AnyAsync(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.AnyAsync(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.AnyAwaitAsync(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.AnyAwaitWithCancellationAsync(source, predicate, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Any
|
||||
{
|
||||
internal static async UniTask<bool> AnyAsync<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> AnyAsync<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> AnyAwaitAsync<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> AnyAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Any.cs.meta
Normal file
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Any.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2b2e65745263994fbe34f3e0ec8eb12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,151 @@
|
||||
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, false);
|
||||
}
|
||||
}
|
||||
|
||||
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 _AppendPrepend(source, element, append, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _AppendPrepend : 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 _AppendPrepend(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;
|
||||
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
completionSource.Reset();
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
if (state == State.RequirePrepend)
|
||||
{
|
||||
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 = (_AppendPrepend)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3268ec424b8055f45aa2a26d17c80468
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<TSource> AsUniTaskAsyncEnumerable<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
return source;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 69866e262589ea643bbc62a1d696077a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,356 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
// note: refactor all inherit class and should remove this.
|
||||
// see Select and Where.
|
||||
internal 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;
|
||||
TaskTracker.TrackActiveTask(this, 4);
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
internal 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;
|
||||
TaskTracker.TrackActiveTask(this, 4);
|
||||
}
|
||||
|
||||
// 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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 01ba1d3b17e13fb4c95740131c7e6e19
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
1524
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Average.cs
Normal file
1524
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Average.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 58499f95012fb3c47bb7bcbc5862e562
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
345
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Buffer.cs
Normal file
345
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Buffer.cs
Normal file
@@ -0,0 +1,345 @@
|
||||
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 _Buffer(source, count, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Buffer : 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 _Buffer(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.count = count;
|
||||
this.cancellationToken = cancellationToken;
|
||||
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_Buffer)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _BufferSkip(source, count, skip, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _BufferSkip : 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 _BufferSkip(IUniTaskAsyncEnumerable<TSource> source, int count, int skip, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.count = count;
|
||||
this.skip = skip;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_BufferSkip)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 951310243334a3148a7872977cb31c5c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
53
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Cast.cs
Normal file
53
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Cast.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
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 _Cast(source, cancellationToken);
|
||||
}
|
||||
|
||||
class _Cast : AsyncEnumeratorBase<object, TResult>
|
||||
{
|
||||
public _Cast(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edebeae8b61352b428abe9ce8f3fc71a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
11372
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/CombineLatest.cs
Normal file
11372
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/CombineLatest.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cb07f6e88287e34d9b9301a572284a5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
164
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Concat.cs
Normal file
164
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Concat.cs
Normal file
@@ -0,0 +1,164 @@
|
||||
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 _Concat(first, second, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Concat : 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 _Concat(IUniTaskAsyncEnumerable<TSource> first, IUniTaskAsyncEnumerable<TSource> second, CancellationToken cancellationToken)
|
||||
{
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.iteratingState = IteratingState.IteratingFirst;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_Concat)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cb9e19c449127a459851a135ce7d527
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
50
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Contains.cs
Normal file
50
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Contains.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
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.ContainsAsync(source, value, comparer, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Contains
|
||||
{
|
||||
internal static async UniTask<bool> ContainsAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 36ab06d30f3223048b4f676e05431a7f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
144
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Count.cs
Normal file
144
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Count.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
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.CountAsync(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.CountAsync(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.CountAwaitAsync(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.CountAwaitWithCancellationAsync(source, predicate, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Count
|
||||
{
|
||||
internal static async UniTask<int> CountAsync<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> CountAsync<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> CountAwaitAsync<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> CountAwaitWithCancellationAsync<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e606d38eed688574bb2ba89d983cc9bb
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
184
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Create.cs
Normal file
184
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Create.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<T> Create<T>(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
|
||||
{
|
||||
Error.ThrowArgumentNullException(create, nameof(create));
|
||||
return new Create<T>(create);
|
||||
}
|
||||
}
|
||||
|
||||
public interface IAsyncWriter<T>
|
||||
{
|
||||
UniTask YieldAsync(T value);
|
||||
}
|
||||
|
||||
internal sealed class Create<T> : IUniTaskAsyncEnumerable<T>
|
||||
{
|
||||
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
|
||||
|
||||
public Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create)
|
||||
{
|
||||
this.create = create;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _Create(create, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Create : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
||||
{
|
||||
readonly Func<IAsyncWriter<T>, CancellationToken, UniTask> create;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
AsyncWriter writer;
|
||||
|
||||
public _Create(Func<IAsyncWriter<T>, CancellationToken, UniTask> create, CancellationToken cancellationToken)
|
||||
{
|
||||
this.create = create;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public T Current { get; private set; }
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
writer.Dispose();
|
||||
return default;
|
||||
}
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
{
|
||||
writer = new AsyncWriter(this);
|
||||
RunWriterTask(create(writer, cancellationToken)).Forget();
|
||||
if (Volatile.Read(ref state) == -2)
|
||||
{
|
||||
return; // complete synchronously
|
||||
}
|
||||
state = 0; // wait YieldAsync, it set TrySetResult(true)
|
||||
return;
|
||||
}
|
||||
case 0:
|
||||
writer.SignalWriter();
|
||||
return;
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
|
||||
async UniTaskVoid RunWriterTask(UniTask task)
|
||||
{
|
||||
try
|
||||
{
|
||||
await task;
|
||||
goto DONE;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Volatile.Write(ref state, -2);
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
Volatile.Write(ref state, -2);
|
||||
completionSource.TrySetResult(false);
|
||||
}
|
||||
|
||||
public void SetResult(T value)
|
||||
{
|
||||
Current = value;
|
||||
completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class AsyncWriter : IUniTaskSource, IAsyncWriter<T>, IDisposable
|
||||
{
|
||||
readonly _Create enumerator;
|
||||
|
||||
UniTaskCompletionSourceCore<AsyncUnit> core;
|
||||
|
||||
public AsyncWriter(_Create enumerator)
|
||||
{
|
||||
this.enumerator = enumerator;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var status = core.GetStatus(core.Version);
|
||||
if (status == UniTaskStatus.Pending)
|
||||
{
|
||||
core.TrySetCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
public void GetResult(short token)
|
||||
{
|
||||
core.GetResult(token);
|
||||
}
|
||||
|
||||
public UniTaskStatus GetStatus(short token)
|
||||
{
|
||||
return core.GetStatus(token);
|
||||
}
|
||||
|
||||
public UniTaskStatus UnsafeGetStatus()
|
||||
{
|
||||
return core.UnsafeGetStatus();
|
||||
}
|
||||
|
||||
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||
{
|
||||
core.OnCompleted(continuation, state, token);
|
||||
}
|
||||
|
||||
public UniTask YieldAsync(T value)
|
||||
{
|
||||
core.Reset();
|
||||
enumerator.SetResult(value);
|
||||
return new UniTask(this, core.Version);
|
||||
}
|
||||
|
||||
public void SignalWriter()
|
||||
{
|
||||
core.TrySetResult(AsyncUnit.Default);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0202f723469f93945afa063bfb440d15
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,142 @@
|
||||
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 _DefaultIfEmpty(source, defaultValue, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _DefaultIfEmpty : 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 _DefaultIfEmpty(IUniTaskAsyncEnumerable<TSource> source, TSource defaultValue, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.defaultValue = defaultValue;
|
||||
this.cancellationToken = cancellationToken;
|
||||
|
||||
this.iteratingState = IteratingState.Empty;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_DefaultIfEmpty)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 19e437c039ad7e1478dbce1779ef8660
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
277
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Distinct.cs
Normal file
277
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Distinct.cs
Normal file
@@ -0,0 +1,277 @@
|
||||
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 DistinctAwaitWithCancellation<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 _Distinct(source, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
class _Distinct : AsyncEnumeratorBase<TSource, TSource>
|
||||
{
|
||||
readonly HashSet<TSource> set;
|
||||
|
||||
public _Distinct(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 _Distinct(source, keySelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
class _Distinct : AsyncEnumeratorBase<TSource, TSource>
|
||||
{
|
||||
readonly HashSet<TKey> set;
|
||||
readonly Func<TSource, TKey> keySelector;
|
||||
|
||||
public _Distinct(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 _DistinctAwait(source, keySelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
class _DistinctAwait : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, TKey>
|
||||
{
|
||||
readonly HashSet<TKey> set;
|
||||
readonly Func<TSource, UniTask<TKey>> keySelector;
|
||||
|
||||
public _DistinctAwait(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 DistinctAwaitWithCancellation<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
|
||||
readonly IEqualityComparer<TKey> comparer;
|
||||
|
||||
public DistinctAwaitWithCancellation(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 _DistinctAwaitWithCancellation(source, keySelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
class _DistinctAwaitWithCancellation : AsyncEnumeratorAwaitSelectorBase<TSource, TSource, TKey>
|
||||
{
|
||||
readonly HashSet<TKey> set;
|
||||
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
|
||||
|
||||
public _DistinctAwaitWithCancellation(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f09903be66e5d943b243d7c19cb3811
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,662 @@
|
||||
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 DistinctUntilChangedAwaitWithCancellation<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 _DistinctUntilChanged(source, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _DistinctUntilChanged : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly IEqualityComparer<TSource> comparer;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
Action moveNextAction;
|
||||
|
||||
public _DistinctUntilChanged(IUniTaskAsyncEnumerable<TSource> source, IEqualityComparer<TSource> comparer, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
REPEAT:
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = -3;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case -3: // first
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
Current = enumerator.Current;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 0: // normal
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
var v = enumerator.Current;
|
||||
if (!comparer.Equals(Current, v))
|
||||
{
|
||||
Current = v;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
goto REPEAT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case -2:
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 _DistinctUntilChanged(source, keySelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _DistinctUntilChanged : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, TKey> keySelector;
|
||||
readonly IEqualityComparer<TKey> comparer;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
Action moveNextAction;
|
||||
TKey prev;
|
||||
|
||||
public _DistinctUntilChanged(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.keySelector = keySelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
REPEAT:
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = -3;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case -3: // first
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
Current = enumerator.Current;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 0: // normal
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
var v = enumerator.Current;
|
||||
var key = keySelector(v);
|
||||
if (!comparer.Equals(prev, key))
|
||||
{
|
||||
prev = key;
|
||||
Current = v;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
goto REPEAT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case -2:
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 _DistinctUntilChangedAwait(source, keySelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _DistinctUntilChangedAwait : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, UniTask<TKey>> keySelector;
|
||||
readonly IEqualityComparer<TKey> comparer;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
UniTask<TKey>.Awaiter awaiter2;
|
||||
Action moveNextAction;
|
||||
TSource enumeratorCurrent;
|
||||
TKey prev;
|
||||
|
||||
public _DistinctUntilChangedAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.keySelector = keySelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
REPEAT:
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = -3;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case -3: // first
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
Current = enumerator.Current;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 0: // normal
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
enumeratorCurrent = enumerator.Current;
|
||||
awaiter2 = keySelector(enumeratorCurrent).GetAwaiter();
|
||||
if (awaiter2.IsCompleted)
|
||||
{
|
||||
goto case 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
awaiter2.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 2:
|
||||
var key = awaiter2.GetResult();
|
||||
if (!comparer.Equals(prev, key))
|
||||
{
|
||||
prev = key;
|
||||
Current = enumeratorCurrent;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
goto REPEAT;
|
||||
}
|
||||
case -2:
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class DistinctUntilChangedAwaitWithCancellation<TSource, TKey> : IUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
|
||||
readonly IEqualityComparer<TKey> comparer;
|
||||
|
||||
public DistinctUntilChangedAwaitWithCancellation(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 _DistinctUntilChangedAwaitWithCancellation(source, keySelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _DistinctUntilChangedAwaitWithCancellation : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, CancellationToken, UniTask<TKey>> keySelector;
|
||||
readonly IEqualityComparer<TKey> comparer;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
UniTask<TKey>.Awaiter awaiter2;
|
||||
Action moveNextAction;
|
||||
TSource enumeratorCurrent;
|
||||
TKey prev;
|
||||
|
||||
public _DistinctUntilChangedAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.keySelector = keySelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
REPEAT:
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case -3;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = -3;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case -3: // first
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
Current = enumerator.Current;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 0: // normal
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
enumeratorCurrent = enumerator.Current;
|
||||
awaiter2 = keySelector(enumeratorCurrent, cancellationToken).GetAwaiter();
|
||||
if (awaiter2.IsCompleted)
|
||||
{
|
||||
goto case 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
awaiter2.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 2:
|
||||
var key = awaiter2.GetResult();
|
||||
if (!comparer.Equals(prev, key))
|
||||
{
|
||||
prev = key;
|
||||
Current = enumeratorCurrent;
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 0;
|
||||
goto REPEAT;
|
||||
}
|
||||
case -2:
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0351f6767df7e644b935d4d599968162
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
258
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Do.cs
Normal file
258
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Do.cs
Normal file
@@ -0,0 +1,258 @@
|
||||
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 _Do(source, onNext, onError, onCompleted, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Do : 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 _Do(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_Do)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Do.cs.meta
Normal file
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Do.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd83c8e12dedf75409b829b93146d130
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,58 @@
|
||||
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.ElementAtAsync(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.ElementAtAsync(source, index, cancellationToken, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ElementAt
|
||||
{
|
||||
public static async UniTask<TSource> ElementAtAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c835bd2dd8555234c8919c7b8ef3b69a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
47
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Empty.cs
Normal file
47
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Empty.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
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 _Empty.Instance;
|
||||
}
|
||||
|
||||
class _Empty : IUniTaskAsyncEnumerator<T>
|
||||
{
|
||||
public static readonly IUniTaskAsyncEnumerator<T> Instance = new _Empty();
|
||||
|
||||
_Empty()
|
||||
{
|
||||
}
|
||||
|
||||
public T Current => default;
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
return CompletedTasks.False;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fa123ad6258abb4184721b719a13810
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
116
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Except.cs
Normal file
116
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Except.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
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 _Except(first, second, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
class _Except : 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 _Except(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 = (_Except)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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 38c1c4129f59dcb49a5b864eaf4ec63c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
200
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/First.cs
Normal file
200
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/First.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
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.FirstAsync(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.FirstAsync(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.FirstAwaitAsync(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.FirstAwaitWithCancellationAsync(source, predicate, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<TSource> FirstOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return First.FirstAsync(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.FirstAsync(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.FirstAwaitAsync(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.FirstAwaitWithCancellationAsync(source, predicate, cancellationToken, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class First
|
||||
{
|
||||
public static async UniTask<TSource> FirstAsync<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> FirstAsync<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> FirstAwaitAsync<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> FirstAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 417946e97e9eed84db6f840f57037ca6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
193
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/ForEach.cs
Normal file
193
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/ForEach.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
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.ForEachAsync(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.ForEachAsync(source, action, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>Obsolete(Error), Use Use ForEachAwaitAsync instead.</summary>
|
||||
[Obsolete("Use ForEachAwaitAsync instead.", true)]
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public static UniTask ForEachAsync<T>(this IUniTaskAsyncEnumerable<T> source, Func<T, UniTask> action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotSupportedException("Use ForEachAwaitAsync instead.");
|
||||
}
|
||||
|
||||
/// <summary>Obsolete(Error), Use Use ForEachAwaitAsync instead.</summary>
|
||||
[Obsolete("Use ForEachAwaitAsync instead.", true)]
|
||||
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
|
||||
public static UniTask ForEachAsync<T>(this IUniTaskAsyncEnumerable<T> source, Func<T, int, UniTask> action, CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new NotSupportedException("Use ForEachAwaitAsync instead.");
|
||||
}
|
||||
|
||||
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.ForEachAwaitAsync(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.ForEachAwaitAsync(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.ForEachAwaitWithCancellationAsync(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.ForEachAwaitWithCancellationAsync(source, action, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class ForEach
|
||||
{
|
||||
public static async UniTask ForEachAsync<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 ForEachAsync<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 ForEachAwaitAsync<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 ForEachAwaitAsync<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 ForEachAwaitWithCancellationAsync<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 ForEachAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca8d7f8177ba16140920af405aea3fd4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
923
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/GroupBy.cs
Normal file
923
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/GroupBy.cs
Normal file
@@ -0,0 +1,923 @@
|
||||
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 _GroupBy(source, keySelector, elementSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupBy : 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 _GroupBy(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _GroupBy(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupBy : 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 _GroupBy(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _GroupByAwait(source, keySelector, elementSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupByAwait : 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 _GroupByAwait(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _GroupByAwait(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupByAwait : 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 _GroupByAwait(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_GroupByAwait)state;
|
||||
|
||||
if (self.TryGetResult(self.awaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _GroupByAwaitWithCancellation(source, keySelector, elementSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupByAwaitWithCancellation : 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 _GroupByAwaitWithCancellation(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _GroupByAwaitWithCancellation(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupByAwaitWithCancellation : 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 _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, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.keySelector = keySelector;
|
||||
this.elementSelector = elementSelector;
|
||||
this.resultSelector = resultSelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_GroupByAwaitWithCancellation)state;
|
||||
|
||||
if (self.TryGetResult(self.awaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (groupEnumerator != null)
|
||||
{
|
||||
groupEnumerator.Dispose();
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a2de80df1cc8a1240ab0ee7badd334d0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
612
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/GroupJoin.cs
Normal file
612
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/GroupJoin.cs
Normal file
@@ -0,0 +1,612 @@
|
||||
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 GroupJoinAwaitWithCancellation<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 GroupJoinAwaitWithCancellation<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 _GroupJoin(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupJoin : 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 _GroupJoin(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_GroupJoin)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _GroupJoinAwait(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupJoinAwait : 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 _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, CancellationToken cancellationToken)
|
||||
{
|
||||
this.outer = outer;
|
||||
this.inner = inner;
|
||||
this.outerKeySelector = outerKeySelector;
|
||||
this.innerKeySelector = innerKeySelector;
|
||||
this.resultSelector = resultSelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_GroupJoinAwait)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 = (_GroupJoinAwait)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 = (_GroupJoinAwait)state;
|
||||
|
||||
if (self.TryGetResult(self.resultAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class GroupJoinAwaitWithCancellation<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 GroupJoinAwaitWithCancellation(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 _GroupJoinAwaitWithCancellation(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _GroupJoinAwaitWithCancellation : 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 _GroupJoinAwaitWithCancellation(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_GroupJoinAwaitWithCancellation)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 = (_GroupJoinAwaitWithCancellation)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 = (_GroupJoinAwaitWithCancellation)state;
|
||||
|
||||
if (self.TryGetResult(self.resultAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7bf7759d03bf3f64190d3ae83b182c2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
117
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Intersect.cs
Normal file
117
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Intersect.cs
Normal file
@@ -0,0 +1,117 @@
|
||||
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 _Intersect(first, second, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
class _Intersect : 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 _Intersect(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 = (_Intersect)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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93999a70f5d57134bbe971f3e988c4f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
728
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Join.cs
Normal file
728
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Join.cs
Normal file
@@ -0,0 +1,728 @@
|
||||
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 _Join(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Join : 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 _Join(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_Join)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _JoinAwait(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _JoinAwait : 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 _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, CancellationToken cancellationToken)
|
||||
{
|
||||
this.outer = outer;
|
||||
this.inner = inner;
|
||||
this.outerKeySelector = outerKeySelector;
|
||||
this.innerKeySelector = innerKeySelector;
|
||||
this.resultSelector = resultSelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_JoinAwait)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 = (_JoinAwait)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 = (_JoinAwait)state;
|
||||
|
||||
if (self.TryGetResult(self.resultAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _JoinAwaitWithCancellation(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _JoinAwaitWithCancellation : 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 _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, CancellationToken cancellationToken)
|
||||
{
|
||||
this.outer = outer;
|
||||
this.inner = inner;
|
||||
this.outerKeySelector = outerKeySelector;
|
||||
this.innerKeySelector = innerKeySelector;
|
||||
this.resultSelector = resultSelector;
|
||||
this.comparer = comparer;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_JoinAwaitWithCancellation)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 = (_JoinAwaitWithCancellation)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 = (_JoinAwaitWithCancellation)state;
|
||||
|
||||
if (self.TryGetResult(self.resultAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (valueEnumerator != null)
|
||||
{
|
||||
valueEnumerator.Dispose();
|
||||
}
|
||||
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc4ff8cb6d7c9a64896f2f082124d6b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
240
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Last.cs
Normal file
240
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Last.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
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.LastAsync(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.LastAsync(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.LastAwaitAsync(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.LastAwaitWithCancellationAsync(source, predicate, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<TSource> LastOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return Last.LastAsync(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.LastAsync(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.LastAwaitAsync(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.LastAwaitWithCancellationAsync(source, predicate, cancellationToken, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class Last
|
||||
{
|
||||
public static async UniTask<TSource> LastAsync<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> LastAsync<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> LastAwaitAsync<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> LastAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0ccc93be1387fa4a975f06310127c11
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
144
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/LongCount.cs
Normal file
144
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/LongCount.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
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.LongCountAsync(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.LongCountAsync(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.LongCountAwaitAsync(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.LongCountAwaitWithCancellationAsync(source, predicate, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class LongCount
|
||||
{
|
||||
internal static async UniTask<long> LongCountAsync<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> LongCountAsync<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> LongCountAwaitAsync<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> LongCountAwaitWithCancellationAsync<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 198b39e58ced3ab4f97ccbe0916787d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
200
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Max.cs
Normal file
200
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Max.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
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.MaxAsync(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.MaxAsync(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.MaxAwaitAsync(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask<TResult> MaxAwaitWithCancellationAsync<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.MaxAwaitWithCancellationAsync(source, selector, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static partial class Max
|
||||
{
|
||||
public static async UniTask<TSource> MaxAsync<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> MaxAsync<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> MaxAwaitAsync<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> MaxAwaitWithCancellationAsync<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Max.cs.meta
Normal file
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Max.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c8a118a6b664c441820b8a87d7f6e28
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
232
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Merge.cs
Normal file
232
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Merge.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second)
|
||||
{
|
||||
Error.ThrowArgumentNullException(first, nameof(first));
|
||||
Error.ThrowArgumentNullException(second, nameof(second));
|
||||
|
||||
return new Merge<T>(new [] { first, second });
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IUniTaskAsyncEnumerable<T> first, IUniTaskAsyncEnumerable<T> second, IUniTaskAsyncEnumerable<T> third)
|
||||
{
|
||||
Error.ThrowArgumentNullException(first, nameof(first));
|
||||
Error.ThrowArgumentNullException(second, nameof(second));
|
||||
Error.ThrowArgumentNullException(third, nameof(third));
|
||||
|
||||
return new Merge<T>(new[] { first, second, third });
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(this IEnumerable<IUniTaskAsyncEnumerable<T>> sources)
|
||||
{
|
||||
return new Merge<T>(sources.ToArray());
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<T> Merge<T>(params IUniTaskAsyncEnumerable<T>[] sources)
|
||||
{
|
||||
return new Merge<T>(sources);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class Merge<T> : IUniTaskAsyncEnumerable<T>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<T>[] sources;
|
||||
|
||||
public Merge(IUniTaskAsyncEnumerable<T>[] sources)
|
||||
{
|
||||
if (sources.Length <= 0)
|
||||
{
|
||||
Error.ThrowArgumentException("No source async enumerable to merge");
|
||||
}
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
=> new _Merge(sources, cancellationToken);
|
||||
|
||||
enum MergeSourceState
|
||||
{
|
||||
Pending,
|
||||
Running,
|
||||
Completed,
|
||||
}
|
||||
|
||||
sealed class _Merge : MoveNextSource, IUniTaskAsyncEnumerator<T>
|
||||
{
|
||||
static readonly Action<object> GetResultAtAction = GetResultAt;
|
||||
|
||||
readonly int length;
|
||||
readonly IUniTaskAsyncEnumerator<T>[] enumerators;
|
||||
readonly MergeSourceState[] states;
|
||||
readonly Queue<(T, Exception, bool)> queuedResult = new Queue<(T, Exception, bool)>();
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int moveNextCompleted;
|
||||
|
||||
public T Current { get; private set; }
|
||||
|
||||
public _Merge(IUniTaskAsyncEnumerable<T>[] sources, CancellationToken cancellationToken)
|
||||
{
|
||||
this.cancellationToken = cancellationToken;
|
||||
length = sources.Length;
|
||||
states = ArrayPool<MergeSourceState>.Shared.Rent(length);
|
||||
enumerators = ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Rent(length);
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
enumerators[i] = sources[i].GetAsyncEnumerator(cancellationToken);
|
||||
states[i] = (int)MergeSourceState.Pending;;
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
completionSource.Reset();
|
||||
Interlocked.Exchange(ref moveNextCompleted, 0);
|
||||
|
||||
if (HasQueuedResult() && Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||
{
|
||||
(T, Exception, bool) value;
|
||||
lock (states)
|
||||
{
|
||||
value = queuedResult.Dequeue();
|
||||
}
|
||||
var resultValue = value.Item1;
|
||||
var exception = value.Item2;
|
||||
var hasNext = value.Item3;
|
||||
if (exception != null)
|
||||
{
|
||||
completionSource.TrySetException(exception);
|
||||
}
|
||||
else
|
||||
{
|
||||
Current = resultValue;
|
||||
completionSource.TrySetResult(hasNext);
|
||||
}
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
lock (states)
|
||||
{
|
||||
if (states[i] == MergeSourceState.Pending)
|
||||
{
|
||||
states[i] = MergeSourceState.Running;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var awaiter = enumerators[i].MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
GetResultAt(i, awaiter);
|
||||
}
|
||||
else
|
||||
{
|
||||
awaiter.SourceOnCompleted(GetResultAtAction, StateTuple.Create(this, i, awaiter));
|
||||
}
|
||||
}
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
await enumerators[i].DisposeAsync();
|
||||
}
|
||||
|
||||
ArrayPool<MergeSourceState>.Shared.Return(states, true);
|
||||
ArrayPool<IUniTaskAsyncEnumerator<T>>.Shared.Return(enumerators, true);
|
||||
}
|
||||
|
||||
static void GetResultAt(object state)
|
||||
{
|
||||
using (var tuple = (StateTuple<_Merge, int, UniTask<bool>.Awaiter>)state)
|
||||
{
|
||||
tuple.Item1.GetResultAt(tuple.Item2, tuple.Item3);
|
||||
}
|
||||
}
|
||||
|
||||
void GetResultAt(int index, UniTask<bool>.Awaiter awaiter)
|
||||
{
|
||||
bool hasNext;
|
||||
bool completedAll;
|
||||
try
|
||||
{
|
||||
hasNext = awaiter.GetResult();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (states)
|
||||
{
|
||||
queuedResult.Enqueue((default, ex, default));
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
lock (states)
|
||||
{
|
||||
states[index] = hasNext ? MergeSourceState.Pending : MergeSourceState.Completed;
|
||||
completedAll = !hasNext && IsCompletedAll();
|
||||
}
|
||||
if (hasNext || completedAll)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref moveNextCompleted, 1, 0) == 0)
|
||||
{
|
||||
Current = enumerators[index].Current;
|
||||
completionSource.TrySetResult(!completedAll);
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (states)
|
||||
{
|
||||
queuedResult.Enqueue((enumerators[index].Current, null, !completedAll));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool HasQueuedResult()
|
||||
{
|
||||
lock (states)
|
||||
{
|
||||
return queuedResult.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCompletedAll()
|
||||
{
|
||||
lock (states)
|
||||
{
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
if (states[i] != MergeSourceState.Completed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca56812f160c45d0bacb4339819edf1a
|
||||
timeCreated: 1694133666
|
||||
200
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Min.cs
Normal file
200
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Min.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
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.MinAsync(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.MinAsync(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.MinAwaitAsync(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
public static UniTask<TResult> MinAwaitWithCancellationAsync<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.MinAwaitWithCancellationAsync(source, selector, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static partial class Min
|
||||
{
|
||||
public static async UniTask<TSource> MinAsync<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> MinAsync<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> MinAwaitAsync<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> MinAwaitWithCancellationAsync<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;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Min.cs.meta
Normal file
11
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Min.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 57ac9da21d3457849a8e45548290a508
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3763
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/MinMax.cs
Normal file
3763
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/MinMax.cs
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2d6da02d9ab970e4999daf7147d98e36
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
56
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Never.cs
Normal file
56
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Never.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
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 _Never(cancellationToken);
|
||||
}
|
||||
|
||||
class _Never : IUniTaskAsyncEnumerator<T>
|
||||
{
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
public _Never(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b307c3d3be71a94da251564bcdefa3d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
61
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/OfType.cs
Normal file
61
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/OfType.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
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 _OfType(source, cancellationToken);
|
||||
}
|
||||
|
||||
class _OfType : AsyncEnumeratorBase<object, TResult>
|
||||
{
|
||||
public _OfType(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 111ffe87a7d700442a9ef5af554b252c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
558
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/OrderBy.cs
Normal file
558
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/OrderBy.cs
Normal file
@@ -0,0 +1,558 @@
|
||||
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 _OrderedAsyncEnumerator(this, cancellationToken);
|
||||
}
|
||||
|
||||
class _OrderedAsyncEnumerator : MoveNextSource, IUniTaskAsyncEnumerator<TElement>
|
||||
{
|
||||
protected readonly OrderedAsyncEnumerable<TElement> parent;
|
||||
CancellationToken cancellationToken;
|
||||
TElement[] buffer;
|
||||
int[] map;
|
||||
int index;
|
||||
|
||||
public _OrderedAsyncEnumerator(OrderedAsyncEnumerable<TElement> parent, CancellationToken cancellationToken)
|
||||
{
|
||||
this.parent = parent;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 413883ceff8546143bdf200aafa4b8f7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
128
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Pairwise.cs
Normal file
128
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Pairwise.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<(TSource, TSource)> Pairwise<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return new Pairwise<TSource>(source);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class Pairwise<TSource> : IUniTaskAsyncEnumerable<(TSource, TSource)>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
|
||||
public Pairwise(IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<(TSource, TSource)> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _Pairwise(source, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Pairwise : MoveNextSource, IUniTaskAsyncEnumerator<(TSource, TSource)>
|
||||
{
|
||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
|
||||
TSource prev;
|
||||
bool isFirst;
|
||||
|
||||
public _Pairwise(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public (TSource, TSource) Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
isFirst = true;
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
}
|
||||
|
||||
completionSource.Reset();
|
||||
SourceMoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
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 = (_Pairwise)state;
|
||||
|
||||
if (self.TryGetResult(self.awaiter, out var result))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
if (self.isFirst)
|
||||
{
|
||||
self.isFirst = false;
|
||||
self.prev = self.enumerator.Current;
|
||||
self.SourceMoveNext(); // run again. okay to use recursive(only one more).
|
||||
}
|
||||
else
|
||||
{
|
||||
var p = self.prev;
|
||||
self.prev = self.enumerator.Current;
|
||||
self.Current = (p, self.prev);
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cddbf051d2a88f549986c468b23214af
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
173
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Publish.cs
Normal file
173
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Publish.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IConnectableUniTaskAsyncEnumerable<TSource> Publish<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return new Publish<TSource>(source);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class Publish<TSource> : IConnectableUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly CancellationTokenSource cancellationTokenSource;
|
||||
|
||||
TriggerEvent<TSource> trigger;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
IDisposable connectedDisposable;
|
||||
bool isCompleted;
|
||||
|
||||
public Publish(IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
public IDisposable Connect()
|
||||
{
|
||||
if (connectedDisposable != null) return connectedDisposable;
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
enumerator = source.GetAsyncEnumerator(cancellationTokenSource.Token);
|
||||
}
|
||||
|
||||
ConsumeEnumerator().Forget();
|
||||
|
||||
connectedDisposable = new ConnectDisposable(cancellationTokenSource);
|
||||
return connectedDisposable;
|
||||
}
|
||||
|
||||
async UniTaskVoid ConsumeEnumerator()
|
||||
{
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
while (await enumerator.MoveNextAsync())
|
||||
{
|
||||
trigger.SetResult(enumerator.Current);
|
||||
}
|
||||
trigger.SetCompleted();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
trigger.SetError(ex);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
isCompleted = true;
|
||||
await enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _Publish(this, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class ConnectDisposable : IDisposable
|
||||
{
|
||||
readonly CancellationTokenSource cancellationTokenSource;
|
||||
|
||||
public ConnectDisposable(CancellationTokenSource cancellationTokenSource)
|
||||
{
|
||||
this.cancellationTokenSource = cancellationTokenSource;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.cancellationTokenSource.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
sealed class _Publish : MoveNextSource, IUniTaskAsyncEnumerator<TSource>, ITriggerHandler<TSource>
|
||||
{
|
||||
static readonly Action<object> CancelDelegate = OnCanceled;
|
||||
|
||||
readonly Publish<TSource> parent;
|
||||
CancellationToken cancellationToken;
|
||||
CancellationTokenRegistration cancellationTokenRegistration;
|
||||
bool isDisposed;
|
||||
|
||||
public _Publish(Publish<TSource> parent, CancellationToken cancellationToken)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested) return;
|
||||
|
||||
this.parent = parent;
|
||||
this.cancellationToken = cancellationToken;
|
||||
|
||||
if (cancellationToken.CanBeCanceled)
|
||||
{
|
||||
this.cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(CancelDelegate, this);
|
||||
}
|
||||
|
||||
parent.trigger.Add(this);
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
ITriggerHandler<TSource> ITriggerHandler<TSource>.Prev { get; set; }
|
||||
ITriggerHandler<TSource> ITriggerHandler<TSource>.Next { get; set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (parent.isCompleted) return CompletedTasks.False;
|
||||
|
||||
completionSource.Reset();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
static void OnCanceled(object state)
|
||||
{
|
||||
var self = (_Publish)state;
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken);
|
||||
self.DisposeAsync().Forget();
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
if (!isDisposed)
|
||||
{
|
||||
isDisposed = true;
|
||||
TaskTracker.RemoveTracking(this);
|
||||
cancellationTokenRegistration.Dispose();
|
||||
parent.trigger.Remove(this);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public void OnNext(TSource value)
|
||||
{
|
||||
Current = value;
|
||||
completionSource.TrySetResult(true);
|
||||
}
|
||||
|
||||
public void OnCanceled(CancellationToken cancellationToken)
|
||||
{
|
||||
completionSource.TrySetCanceled(cancellationToken);
|
||||
}
|
||||
|
||||
public void OnCompleted()
|
||||
{
|
||||
completionSource.TrySetResult(false);
|
||||
}
|
||||
|
||||
public void OnError(Exception ex)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 93c684d1e88c09d4e89b79437d97b810
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
103
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Queue.cs
Normal file
103
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Queue.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<TSource> Queue<TSource>(this IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
return new QueueOperator<TSource>(source);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class QueueOperator<TSource> : IUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
|
||||
public QueueOperator(IUniTaskAsyncEnumerable<TSource> source)
|
||||
{
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _Queue(source, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Queue : IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
Channel<TSource> channel;
|
||||
IUniTaskAsyncEnumerator<TSource> channelEnumerator;
|
||||
IUniTaskAsyncEnumerator<TSource> sourceEnumerator;
|
||||
bool channelClosed;
|
||||
|
||||
public _Queue(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationToken = cancellationToken;
|
||||
}
|
||||
|
||||
public TSource Current => channelEnumerator.Current;
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (sourceEnumerator == null)
|
||||
{
|
||||
sourceEnumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
channel = Channel.CreateSingleConsumerUnbounded<TSource>();
|
||||
|
||||
channelEnumerator = channel.Reader.ReadAllAsync().GetAsyncEnumerator(cancellationToken);
|
||||
|
||||
ConsumeAll(this, sourceEnumerator, channel).Forget();
|
||||
}
|
||||
|
||||
return channelEnumerator.MoveNextAsync();
|
||||
}
|
||||
|
||||
static async UniTaskVoid ConsumeAll(_Queue self, IUniTaskAsyncEnumerator<TSource> enumerator, ChannelWriter<TSource> writer)
|
||||
{
|
||||
try
|
||||
{
|
||||
while (await enumerator.MoveNextAsync())
|
||||
{
|
||||
writer.TryWrite(enumerator.Current);
|
||||
}
|
||||
writer.TryComplete();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
writer.TryComplete(ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
self.channelClosed = true;
|
||||
await enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
if (sourceEnumerator != null)
|
||||
{
|
||||
await sourceEnumerator.DisposeAsync();
|
||||
}
|
||||
if (channelEnumerator != null)
|
||||
{
|
||||
await channelEnumerator.DisposeAsync();
|
||||
}
|
||||
|
||||
if (!channelClosed)
|
||||
{
|
||||
channelClosed = true;
|
||||
channel.Writer.TryComplete(new OperationCanceledException());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b7ea1bcf9dbebb042bc99c7816249e02
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
75
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Range.cs
Normal file
75
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Range.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
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 _Range(start, end, cancellationToken);
|
||||
}
|
||||
|
||||
class _Range : IUniTaskAsyncEnumerator<int>
|
||||
{
|
||||
readonly int start;
|
||||
readonly int end;
|
||||
int current;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
public _Range(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d826418a813498648b10542d0a5fb173
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
68
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Repeat.cs
Normal file
68
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Repeat.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
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 _Repeat(element, count, cancellationToken);
|
||||
}
|
||||
|
||||
class _Repeat : IUniTaskAsyncEnumerator<TElement>
|
||||
{
|
||||
readonly TElement element;
|
||||
readonly int count;
|
||||
int remaining;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
public _Repeat(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3819a3925165a674d80ee848c8600379
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
63
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Return.cs
Normal file
63
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Return.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
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 _Return(value, cancellationToken);
|
||||
}
|
||||
|
||||
class _Return : IUniTaskAsyncEnumerator<TValue>
|
||||
{
|
||||
readonly TValue value;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
bool called;
|
||||
|
||||
public _Return(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4313cd8ecf705e44f9064ce46e293c2c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
78
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Reverse.cs
Normal file
78
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Reverse.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
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 _Reverse(source, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Reverse : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken;
|
||||
|
||||
TSource[] array;
|
||||
int index;
|
||||
|
||||
public _Reverse(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b2769e65c729b4f4ca6af9826d9c7b90
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
760
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Select.cs
Normal file
760
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Select.cs
Normal file
@@ -0,0 +1,760 @@
|
||||
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.SelectIntAwait<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.SelectAwaitWithCancellation<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.SelectIntAwaitWithCancellation<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 _Select(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Select : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, TResult> selector;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
Action moveNextAction;
|
||||
|
||||
public _Select(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
goto case 0;
|
||||
case 0:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
Current = selector(enumerator.Current);
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 _Select(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Select : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, int, TResult> selector;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
Action moveNextAction;
|
||||
int index;
|
||||
|
||||
public _Select(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, TResult> selector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
goto case 0;
|
||||
case 0:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
Current = selector(enumerator.Current, checked(index++));
|
||||
goto CONTINUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 _SelectAwait(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectAwait : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, UniTask<TResult>> selector;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
UniTask<TResult>.Awaiter awaiter2;
|
||||
Action moveNextAction;
|
||||
|
||||
public _SelectAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<TResult>> selector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
goto case 0;
|
||||
case 0:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
awaiter2 = selector(enumerator.Current).GetAwaiter();
|
||||
if (awaiter2.IsCompleted)
|
||||
{
|
||||
goto case 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
awaiter2.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 2:
|
||||
Current = awaiter2.GetResult();
|
||||
goto CONTINUE;
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SelectIntAwait<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, int, UniTask<TResult>> selector;
|
||||
|
||||
public SelectIntAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<TResult>> selector)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _SelectAwait(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectAwait : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, int, UniTask<TResult>> selector;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
UniTask<TResult>.Awaiter awaiter2;
|
||||
Action moveNextAction;
|
||||
int index;
|
||||
|
||||
public _SelectAwait(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, UniTask<TResult>> selector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
goto case 0;
|
||||
case 0:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
awaiter2 = selector(enumerator.Current, checked(index++)).GetAwaiter();
|
||||
if (awaiter2.IsCompleted)
|
||||
{
|
||||
goto case 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
awaiter2.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 2:
|
||||
Current = awaiter2.GetResult();
|
||||
goto CONTINUE;
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SelectAwaitWithCancellation<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, CancellationToken, UniTask<TResult>> selector;
|
||||
|
||||
public SelectAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return new _SelectAwaitWithCancellation(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectAwaitWithCancellation : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, CancellationToken, UniTask<TResult>> selector;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
UniTask<TResult>.Awaiter awaiter2;
|
||||
Action moveNextAction;
|
||||
|
||||
public _SelectAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
goto case 0;
|
||||
case 0:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
awaiter2 = selector(enumerator.Current, cancellationToken).GetAwaiter();
|
||||
if (awaiter2.IsCompleted)
|
||||
{
|
||||
goto case 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
awaiter2.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 2:
|
||||
Current = awaiter2.GetResult();
|
||||
goto CONTINUE;
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SelectIntAwaitWithCancellation<TSource, TResult> : IUniTaskAsyncEnumerable<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, int, CancellationToken, UniTask<TResult>> selector;
|
||||
|
||||
public SelectIntAwaitWithCancellation(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 _SelectAwaitWithCancellation(source, selector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectAwaitWithCancellation : MoveNextSource, IUniTaskAsyncEnumerator<TResult>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly Func<TSource, int, CancellationToken, UniTask<TResult>> selector;
|
||||
readonly CancellationToken cancellationToken;
|
||||
|
||||
int state = -1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
UniTask<TResult>.Awaiter awaiter2;
|
||||
Action moveNextAction;
|
||||
int index;
|
||||
|
||||
public _SelectAwaitWithCancellation(IUniTaskAsyncEnumerable<TSource> source, Func<TSource, int, CancellationToken, UniTask<TResult>> selector, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.selector = selector;
|
||||
this.cancellationToken = cancellationToken;
|
||||
this.moveNextAction = MoveNext;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
public TResult Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (state == -2) return default;
|
||||
|
||||
completionSource.Reset();
|
||||
MoveNext();
|
||||
return new UniTask<bool>(this, completionSource.Version);
|
||||
}
|
||||
|
||||
void MoveNext()
|
||||
{
|
||||
try
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case -1: // init
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken);
|
||||
goto case 0;
|
||||
case 0:
|
||||
awaiter = enumerator.MoveNextAsync().GetAwaiter();
|
||||
if (awaiter.IsCompleted)
|
||||
{
|
||||
goto case 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 1;
|
||||
awaiter.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
case 1:
|
||||
if (awaiter.GetResult())
|
||||
{
|
||||
awaiter2 = selector(enumerator.Current, checked(index++), cancellationToken).GetAwaiter();
|
||||
if (awaiter2.IsCompleted)
|
||||
{
|
||||
goto case 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
state = 2;
|
||||
awaiter2.UnsafeOnCompleted(moveNextAction);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
goto DONE;
|
||||
}
|
||||
case 2:
|
||||
Current = awaiter2.GetResult();
|
||||
goto CONTINUE;
|
||||
default:
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
state = -2;
|
||||
completionSource.TrySetException(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
DONE:
|
||||
state = -2;
|
||||
completionSource.TrySetResult(false);
|
||||
return;
|
||||
|
||||
CONTINUE:
|
||||
state = 0;
|
||||
completionSource.TrySetResult(true);
|
||||
return;
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc68e598ca44a134b988dfaf5e53bfba
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
892
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/SelectMany.cs
Normal file
892
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/SelectMany.cs
Normal file
@@ -0,0 +1,892 @@
|
||||
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 _SelectMany(source, selector1, selector2, resultSelector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectMany : 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 _SelectMany(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_SelectMany)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 = (_SelectMany)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 = (_SelectMany)state;
|
||||
|
||||
if (self.TryGetResult(self.selectedDisposeAsyncAwaiter))
|
||||
{
|
||||
self.selectedEnumerator = null;
|
||||
self.selectedAwaiter = default;
|
||||
|
||||
self.MoveNextSource(); // iterate next source
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _SelectManyAwait(source, selector1, selector2, resultSelector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectManyAwait : 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 _SelectManyAwait(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_SelectManyAwait)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 = (_SelectManyAwait)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 = (_SelectManyAwait)state;
|
||||
|
||||
if (self.TryGetResult(self.selectedDisposeAsyncAwaiter))
|
||||
{
|
||||
self.selectedEnumerator = null;
|
||||
self.selectedAwaiter = default;
|
||||
|
||||
self.MoveNextSource(); // iterate next source
|
||||
}
|
||||
}
|
||||
|
||||
static void SelectorAwaitCore(object state)
|
||||
{
|
||||
var self = (_SelectManyAwait)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 = (_SelectManyAwait)state;
|
||||
|
||||
if (self.TryGetResult(self.resultSelectorAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
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 _SelectManyAwaitWithCancellation(source, selector1, selector2, resultSelector, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SelectManyAwaitWithCancellation : 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 _SelectManyAwaitWithCancellation(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;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_SelectManyAwaitWithCancellation)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 = (_SelectManyAwaitWithCancellation)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 = (_SelectManyAwaitWithCancellation)state;
|
||||
|
||||
if (self.TryGetResult(self.selectedDisposeAsyncAwaiter))
|
||||
{
|
||||
self.selectedEnumerator = null;
|
||||
self.selectedAwaiter = default;
|
||||
|
||||
self.MoveNextSource(); // iterate next source
|
||||
}
|
||||
}
|
||||
|
||||
static void SelectorAwaitCore(object state)
|
||||
{
|
||||
var self = (_SelectManyAwaitWithCancellation)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 = (_SelectManyAwaitWithCancellation)state;
|
||||
|
||||
if (self.TryGetResult(self.resultSelectorAwaiter, out var result))
|
||||
{
|
||||
self.Current = result;
|
||||
self.completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (selectedEnumerator != null)
|
||||
{
|
||||
await selectedEnumerator.DisposeAsync();
|
||||
}
|
||||
if (sourceEnumerator != null)
|
||||
{
|
||||
await sourceEnumerator.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d81862f0eb12680479ccaaf2ac319d24
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,87 @@
|
||||
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.SequenceEqualAsync(first, second, comparer, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SequenceEqual
|
||||
{
|
||||
internal static async UniTask<bool> SequenceEqualAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b382772aba6128842928cdb6b2e034b0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
230
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Single.cs
Normal file
230
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Single.cs
Normal file
@@ -0,0 +1,230 @@
|
||||
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.SingleAsync(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.SingleAsync(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.SingleAwaitAsync(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.SingleAwaitWithCancellationAsync(source, predicate, cancellationToken, false);
|
||||
}
|
||||
|
||||
public static UniTask<TSource> SingleOrDefaultAsync<TSource>(this IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return SingleOperator.SingleAsync(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.SingleAsync(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.SingleAwaitAsync(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.SingleAwaitWithCancellationAsync(source, predicate, cancellationToken, true);
|
||||
}
|
||||
}
|
||||
|
||||
internal static class SingleOperator
|
||||
{
|
||||
public static async UniTask<TSource> SingleAsync<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> SingleAsync<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> SingleAwaitAsync<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> SingleAwaitWithCancellationAsync<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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1bcd3928b90472e43a3a92c3ba708967
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
69
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Skip.cs
Normal file
69
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/Skip.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
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 _Skip(source, count, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _Skip : AsyncEnumeratorBase<TSource, TSource>
|
||||
{
|
||||
readonly int count;
|
||||
|
||||
int index;
|
||||
|
||||
public _Skip(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9c46b6c7dce0cb049a73c81084c75154
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
159
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/SkipLast.cs
Normal file
159
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/SkipLast.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
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 _SkipLast(source, count, cancellationToken);
|
||||
}
|
||||
|
||||
sealed class _SkipLast : 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 _SkipLast(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
this.source = source;
|
||||
this.count = count;
|
||||
this.cancellationToken = cancellationToken;
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
}
|
||||
|
||||
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 = (_SkipLast)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()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df1d7f44d4fe7754f972c9e0b6fa72d5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
187
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/SkipUntil.cs
Normal file
187
JNFrame/Assets/Game/Plugins/UniTask/Runtime/Linq/SkipUntil.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using Cysharp.Threading.Tasks.Internal;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Cysharp.Threading.Tasks.Linq
|
||||
{
|
||||
public static partial class UniTaskAsyncEnumerable
|
||||
{
|
||||
public static IUniTaskAsyncEnumerable<TSource> SkipUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, UniTask other)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
|
||||
return new SkipUntil<TSource>(source, other, null);
|
||||
}
|
||||
|
||||
public static IUniTaskAsyncEnumerable<TSource> SkipUntil<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<CancellationToken, UniTask> other)
|
||||
{
|
||||
Error.ThrowArgumentNullException(source, nameof(source));
|
||||
Error.ThrowArgumentNullException(source, nameof(other));
|
||||
|
||||
return new SkipUntil<TSource>(source, default, other);
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class SkipUntil<TSource> : IUniTaskAsyncEnumerable<TSource>
|
||||
{
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
readonly UniTask other;
|
||||
readonly Func<CancellationToken, UniTask> other2;
|
||||
|
||||
public SkipUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, Func<CancellationToken, UniTask> other2)
|
||||
{
|
||||
this.source = source;
|
||||
this.other = other;
|
||||
this.other2 = other2;
|
||||
}
|
||||
|
||||
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (other2 != null)
|
||||
{
|
||||
return new _SkipUntil(source, this.other2(cancellationToken), cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new _SkipUntil(source, this.other, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
sealed class _SkipUntil : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
|
||||
{
|
||||
static readonly Action<object> CancelDelegate1 = OnCanceled1;
|
||||
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
|
||||
|
||||
readonly IUniTaskAsyncEnumerable<TSource> source;
|
||||
CancellationToken cancellationToken1;
|
||||
|
||||
bool completed;
|
||||
CancellationTokenRegistration cancellationTokenRegistration1;
|
||||
IUniTaskAsyncEnumerator<TSource> enumerator;
|
||||
UniTask<bool>.Awaiter awaiter;
|
||||
bool continueNext;
|
||||
Exception exception;
|
||||
|
||||
public _SkipUntil(IUniTaskAsyncEnumerable<TSource> source, UniTask other, CancellationToken cancellationToken1)
|
||||
{
|
||||
this.source = source;
|
||||
this.cancellationToken1 = cancellationToken1;
|
||||
if (cancellationToken1.CanBeCanceled)
|
||||
{
|
||||
this.cancellationTokenRegistration1 = cancellationToken1.RegisterWithoutCaptureExecutionContext(CancelDelegate1, this);
|
||||
}
|
||||
|
||||
TaskTracker.TrackActiveTask(this, 3);
|
||||
RunOther(other).Forget();
|
||||
}
|
||||
|
||||
public TSource Current { get; private set; }
|
||||
|
||||
public UniTask<bool> MoveNextAsync()
|
||||
{
|
||||
if (exception != null)
|
||||
{
|
||||
return UniTask.FromException<bool>(exception);
|
||||
}
|
||||
|
||||
if (cancellationToken1.IsCancellationRequested)
|
||||
{
|
||||
return UniTask.FromCanceled<bool>(cancellationToken1);
|
||||
}
|
||||
|
||||
if (enumerator == null)
|
||||
{
|
||||
enumerator = source.GetAsyncEnumerator(cancellationToken1);
|
||||
}
|
||||
completionSource.Reset();
|
||||
|
||||
if (completed)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void MoveNextCore(object state)
|
||||
{
|
||||
var self = (_SkipUntil)state;
|
||||
|
||||
if (self.TryGetResult(self.awaiter, out var result))
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
self.Current = self.enumerator.Current;
|
||||
self.completionSource.TrySetResult(true);
|
||||
if (self.continueNext)
|
||||
{
|
||||
self.SourceMoveNext();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.completionSource.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async UniTaskVoid RunOther(UniTask other)
|
||||
{
|
||||
try
|
||||
{
|
||||
await other;
|
||||
completed = true;
|
||||
SourceMoveNext();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
completionSource.TrySetException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static void OnCanceled1(object state)
|
||||
{
|
||||
var self = (_SkipUntil)state;
|
||||
self.completionSource.TrySetCanceled(self.cancellationToken1);
|
||||
}
|
||||
|
||||
public UniTask DisposeAsync()
|
||||
{
|
||||
TaskTracker.RemoveTracking(this);
|
||||
cancellationTokenRegistration1.Dispose();
|
||||
if (enumerator != null)
|
||||
{
|
||||
return enumerator.DisposeAsync();
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: de932d79c8d9f3841a066d05ff29edc9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user