From 61b798b6e954c5da24a773173c214194c29a2d24 Mon Sep 17 00:00:00 2001 From: neuecc Date: Fri, 8 May 2020 03:23:14 +0900 Subject: [PATCH 01/31] start to implements async linq --- src/UniTask.NetCore/IAsyncEnumerable.cs | 20 + src/UniTask.NetCore/Linq/All.cs | 775 +++++ src/UniTask.NetCore/Linq/Any.cs | 775 +++++ src/UniTask.NetCore/Linq/Append.cs | 775 +++++ src/UniTask.NetCore/Linq/AsEnumerable.cs | 775 +++++ .../Linq/AsyncEnumeratorBase.cs | 357 +++ src/UniTask.NetCore/Linq/Average.cs | 775 +++++ src/UniTask.NetCore/Linq/Cast.cs | 775 +++++ src/UniTask.NetCore/Linq/Concat.cs | 775 +++++ src/UniTask.NetCore/Linq/Contains.cs | 775 +++++ src/UniTask.NetCore/Linq/Count.cs | 775 +++++ src/UniTask.NetCore/Linq/Create.cs | 775 +++++ src/UniTask.NetCore/Linq/DefaultIfEmpty.cs | 775 +++++ src/UniTask.NetCore/Linq/Distinct.cs | 775 +++++ src/UniTask.NetCore/Linq/ElementAt.cs | 775 +++++ .../Linq/ElementAtOrDefault.cs | 775 +++++ src/UniTask.NetCore/Linq/Empty.cs | 48 + src/UniTask.NetCore/Linq/Except.cs | 775 +++++ src/UniTask.NetCore/Linq/First.cs | 775 +++++ src/UniTask.NetCore/Linq/FirstOrDefault.cs | 775 +++++ src/UniTask.NetCore/Linq/ForEach.cs | 177 ++ src/UniTask.NetCore/Linq/GroupBy.cs | 775 +++++ src/UniTask.NetCore/Linq/GroupJoin.cs | 775 +++++ src/UniTask.NetCore/Linq/Intersect.cs | 775 +++++ src/UniTask.NetCore/Linq/Join.cs | 775 +++++ src/UniTask.NetCore/Linq/Last.cs | 775 +++++ src/UniTask.NetCore/Linq/LastOrDefault.cs | 775 +++++ src/UniTask.NetCore/Linq/LongCount.cs | 775 +++++ src/UniTask.NetCore/Linq/Max.cs | 775 +++++ src/UniTask.NetCore/Linq/Min.cs | 775 +++++ src/UniTask.NetCore/Linq/OfType.cs | 775 +++++ src/UniTask.NetCore/Linq/OrderBy.cs | 775 +++++ src/UniTask.NetCore/Linq/OrderByDescending.cs | 775 +++++ src/UniTask.NetCore/Linq/Prepend.cs | 775 +++++ src/UniTask.NetCore/Linq/Range.cs | 76 + src/UniTask.NetCore/Linq/Repeat.cs | 69 + src/UniTask.NetCore/Linq/Reverse.cs | 775 +++++ src/UniTask.NetCore/Linq/Select.cs | 309 ++ src/UniTask.NetCore/Linq/SelectMany.cs | 775 +++++ src/UniTask.NetCore/Linq/SequenceEqual.cs | 775 +++++ src/UniTask.NetCore/Linq/Single.cs | 775 +++++ src/UniTask.NetCore/Linq/SingleOrDefault.cs | 775 +++++ src/UniTask.NetCore/Linq/Skip.cs | 775 +++++ src/UniTask.NetCore/Linq/SkipLast.cs | 775 +++++ src/UniTask.NetCore/Linq/SkipWhile.cs | 775 +++++ src/UniTask.NetCore/Linq/Sum.cs | 775 +++++ src/UniTask.NetCore/Linq/Take.cs | 775 +++++ src/UniTask.NetCore/Linq/TakeLast.cs | 775 +++++ src/UniTask.NetCore/Linq/TakeWhile.cs | 775 +++++ src/UniTask.NetCore/Linq/ThenBy.cs | 775 +++++ src/UniTask.NetCore/Linq/ThenByDescending.cs | 775 +++++ src/UniTask.NetCore/Linq/ToArray.cs | 57 + src/UniTask.NetCore/Linq/ToDictionary.cs | 775 +++++ src/UniTask.NetCore/Linq/ToEnumerable.cs | 775 +++++ src/UniTask.NetCore/Linq/ToHashSet.cs | 775 +++++ src/UniTask.NetCore/Linq/ToList.cs | 775 +++++ src/UniTask.NetCore/Linq/ToLookup.cs | 775 +++++ src/UniTask.NetCore/Linq/ToObservable.cs | 775 +++++ src/UniTask.NetCore/Linq/Union.cs | 775 +++++ src/UniTask.NetCore/Linq/Where.cs | 116 + src/UniTask.NetCore/Linq/Zip.cs | 308 ++ src/UniTask.NetCore/Linq/_FileMaker.cs | 2643 +++++++++++++++++ src/UniTask.NetCore/UniTask.NetCore.csproj | 20 +- src/UniTask.NetCoreSandbox/Program.cs | 223 +- .../UniTask.NetCoreSandbox.csproj | 4 + src/UniTask.NetCoreTests/UnitTest1.cs | 5 + .../Assets/Plugins/UniTask/Internal/Error.cs | 6 + src/UniTask/Assets/Scenes/SandboxMain.cs | 16 +- src/UniTask/Packages/manifest.json | 2 +- .../ProjectSettings/ProjectVersion.txt | 4 +- 70 files changed, 43940 insertions(+), 45 deletions(-) create mode 100644 src/UniTask.NetCore/IAsyncEnumerable.cs create mode 100644 src/UniTask.NetCore/Linq/All.cs create mode 100644 src/UniTask.NetCore/Linq/Any.cs create mode 100644 src/UniTask.NetCore/Linq/Append.cs create mode 100644 src/UniTask.NetCore/Linq/AsEnumerable.cs create mode 100644 src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs create mode 100644 src/UniTask.NetCore/Linq/Average.cs create mode 100644 src/UniTask.NetCore/Linq/Cast.cs create mode 100644 src/UniTask.NetCore/Linq/Concat.cs create mode 100644 src/UniTask.NetCore/Linq/Contains.cs create mode 100644 src/UniTask.NetCore/Linq/Count.cs create mode 100644 src/UniTask.NetCore/Linq/Create.cs create mode 100644 src/UniTask.NetCore/Linq/DefaultIfEmpty.cs create mode 100644 src/UniTask.NetCore/Linq/Distinct.cs create mode 100644 src/UniTask.NetCore/Linq/ElementAt.cs create mode 100644 src/UniTask.NetCore/Linq/ElementAtOrDefault.cs create mode 100644 src/UniTask.NetCore/Linq/Empty.cs create mode 100644 src/UniTask.NetCore/Linq/Except.cs create mode 100644 src/UniTask.NetCore/Linq/First.cs create mode 100644 src/UniTask.NetCore/Linq/FirstOrDefault.cs create mode 100644 src/UniTask.NetCore/Linq/ForEach.cs create mode 100644 src/UniTask.NetCore/Linq/GroupBy.cs create mode 100644 src/UniTask.NetCore/Linq/GroupJoin.cs create mode 100644 src/UniTask.NetCore/Linq/Intersect.cs create mode 100644 src/UniTask.NetCore/Linq/Join.cs create mode 100644 src/UniTask.NetCore/Linq/Last.cs create mode 100644 src/UniTask.NetCore/Linq/LastOrDefault.cs create mode 100644 src/UniTask.NetCore/Linq/LongCount.cs create mode 100644 src/UniTask.NetCore/Linq/Max.cs create mode 100644 src/UniTask.NetCore/Linq/Min.cs create mode 100644 src/UniTask.NetCore/Linq/OfType.cs create mode 100644 src/UniTask.NetCore/Linq/OrderBy.cs create mode 100644 src/UniTask.NetCore/Linq/OrderByDescending.cs create mode 100644 src/UniTask.NetCore/Linq/Prepend.cs create mode 100644 src/UniTask.NetCore/Linq/Range.cs create mode 100644 src/UniTask.NetCore/Linq/Repeat.cs create mode 100644 src/UniTask.NetCore/Linq/Reverse.cs create mode 100644 src/UniTask.NetCore/Linq/Select.cs create mode 100644 src/UniTask.NetCore/Linq/SelectMany.cs create mode 100644 src/UniTask.NetCore/Linq/SequenceEqual.cs create mode 100644 src/UniTask.NetCore/Linq/Single.cs create mode 100644 src/UniTask.NetCore/Linq/SingleOrDefault.cs create mode 100644 src/UniTask.NetCore/Linq/Skip.cs create mode 100644 src/UniTask.NetCore/Linq/SkipLast.cs create mode 100644 src/UniTask.NetCore/Linq/SkipWhile.cs create mode 100644 src/UniTask.NetCore/Linq/Sum.cs create mode 100644 src/UniTask.NetCore/Linq/Take.cs create mode 100644 src/UniTask.NetCore/Linq/TakeLast.cs create mode 100644 src/UniTask.NetCore/Linq/TakeWhile.cs create mode 100644 src/UniTask.NetCore/Linq/ThenBy.cs create mode 100644 src/UniTask.NetCore/Linq/ThenByDescending.cs create mode 100644 src/UniTask.NetCore/Linq/ToArray.cs create mode 100644 src/UniTask.NetCore/Linq/ToDictionary.cs create mode 100644 src/UniTask.NetCore/Linq/ToEnumerable.cs create mode 100644 src/UniTask.NetCore/Linq/ToHashSet.cs create mode 100644 src/UniTask.NetCore/Linq/ToList.cs create mode 100644 src/UniTask.NetCore/Linq/ToLookup.cs create mode 100644 src/UniTask.NetCore/Linq/ToObservable.cs create mode 100644 src/UniTask.NetCore/Linq/Union.cs create mode 100644 src/UniTask.NetCore/Linq/Where.cs create mode 100644 src/UniTask.NetCore/Linq/Zip.cs create mode 100644 src/UniTask.NetCore/Linq/_FileMaker.cs diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask.NetCore/IAsyncEnumerable.cs new file mode 100644 index 0000000..9c67692 --- /dev/null +++ b/src/UniTask.NetCore/IAsyncEnumerable.cs @@ -0,0 +1,20 @@ +using System.Threading; + +namespace Cysharp.Threading.Tasks +{ + public interface IUniTaskAsyncEnumerable + { + IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default); + } + + public interface IUniTaskAsyncEnumerator : IUniTaskAsyncDisposable + { + T Current { get; } + UniTask MoveNextAsync(); + } + + public interface IUniTaskAsyncDisposable + { + UniTask DisposeAsync(); + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/All.cs b/src/UniTask.NetCore/Linq/All.cs new file mode 100644 index 0000000..bc15cec --- /dev/null +++ b/src/UniTask.NetCore/Linq/All.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class All + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Any.cs b/src/UniTask.NetCore/Linq/Any.cs new file mode 100644 index 0000000..b614c81 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Any.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Any + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Append.cs b/src/UniTask.NetCore/Linq/Append.cs new file mode 100644 index 0000000..4d22846 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Append.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Append + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/AsEnumerable.cs b/src/UniTask.NetCore/Linq/AsEnumerable.cs new file mode 100644 index 0000000..4877fa5 --- /dev/null +++ b/src/UniTask.NetCore/Linq/AsEnumerable.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class AsEnumerable + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs new file mode 100644 index 0000000..2818715 --- /dev/null +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -0,0 +1,357 @@ +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public abstract class MoveNextSource : IUniTaskSource + { + protected UniTaskCompletionSourceCore completionSource; + + public bool GetResult(short token) + { + return completionSource.GetResult(token); + } + + public UniTaskStatus GetStatus(short token) + { + return completionSource.GetStatus(token); + } + + public void OnCompleted(Action continuation, object state, short token) + { + completionSource.OnCompleted(continuation, state, token); + } + + public UniTaskStatus UnsafeGetStatus() + { + return completionSource.UnsafeGetStatus(); + } + + void IUniTaskSource.GetResult(short token) + { + completionSource.GetResult(token); + } + } + + + public abstract class AsyncEnumeratorBase : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action moveNextCallbackDelegate = MoveNextCallBack; + + readonly IUniTaskAsyncEnumerable source; + protected CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter sourceMoveNext; + + public AsyncEnumeratorBase(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + } + + // abstract + + /// + /// If return value is false, continue source.MoveNext. + /// + protected abstract bool TryMoveNextCore(bool sourceHasCurrent, out bool result); + + // Util + protected TSource SourceCurrent => enumerator.Current; + + // IUniTaskAsyncEnumerator + + public TResult Current { get; protected set; } + + public UniTask MoveNextAsync() + { + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + } + + completionSource.Reset(); + SourceMoveNext(); + return new UniTask(this, completionSource.Version); + } + + 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)state; + bool result; + try + { + if (!self.TryMoveNextCore(self.sourceMoveNext.GetResult(), out result)) + { + self.SourceMoveNext(); + return; + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + + if (self.cancellationToken.IsCancellationRequested) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + else + { + self.completionSource.TrySetResult(result); + } + } + + // if require additional resource to dispose, override and call base.DisposeAsync. + public virtual UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + + public abstract class AsyncEnumeratorAwaitSelectorBase : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action moveNextCallbackDelegate = MoveNextCallBack; + + readonly IUniTaskAsyncEnumerable source; + protected CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter sourceMoveNext; + + UniTask.Awaiter resultAwaiter; + + public AsyncEnumeratorAwaitSelectorBase(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + } + + // abstract + + protected abstract UniTask TransformAsync(TSource sourceCurrent); + protected abstract bool TrySetCurrentCore(TAwait awaitResult); + + // Util + protected TSource SourceCurrent => enumerator.Current; + + 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 + + public TResult Current { get; protected set; } + + public UniTask MoveNextAsync() + { + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + } + + completionSource.Reset(); + SourceMoveNext(); + return new UniTask(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) + { + var task = TransformAsync(enumerator.Current); + if (UnwarapTask(task, out var taskResult)) + { + return ActionCompleted(TrySetCurrentCore(taskResult), out result); + } + else + { + return WaitAwaitCallback(out result); + } + } + + return IterateFinished(out result); + } + + protected bool UnwarapTask(UniTask taskResult, out TAwait result) + { + resultAwaiter = taskResult.GetAwaiter(); + + if (resultAwaiter.IsCompleted) + { + result = resultAwaiter.GetResult(); + return true; + } + else + { + resultAwaiter.SourceOnCompleted(SetCurrentCallBack, this); // TODO:cache + result = default; + return false; + } + } + + static void MoveNextCallBack(object state) + { + var self = (AsyncEnumeratorAwaitSelectorBase)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)state; + + bool doneSetCurrent; + try + { + var result = self.resultAwaiter.GetResult(); + doneSetCurrent = self.TrySetCurrentCore(result); + } + 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 + { + self.SourceMoveNext(); + } + } + } + + // if require additional resource to dispose, override and call base.DisposeAsync. + public virtual UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Average.cs b/src/UniTask.NetCore/Linq/Average.cs new file mode 100644 index 0000000..a4c0f1e --- /dev/null +++ b/src/UniTask.NetCore/Linq/Average.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Average + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Cast.cs b/src/UniTask.NetCore/Linq/Cast.cs new file mode 100644 index 0000000..413d127 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Cast.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Cast + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Concat.cs b/src/UniTask.NetCore/Linq/Concat.cs new file mode 100644 index 0000000..327ac6f --- /dev/null +++ b/src/UniTask.NetCore/Linq/Concat.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Concat + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Contains.cs b/src/UniTask.NetCore/Linq/Contains.cs new file mode 100644 index 0000000..b9d1b90 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Contains.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Contains + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Count.cs b/src/UniTask.NetCore/Linq/Count.cs new file mode 100644 index 0000000..a95f9bc --- /dev/null +++ b/src/UniTask.NetCore/Linq/Count.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Count + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Create.cs b/src/UniTask.NetCore/Linq/Create.cs new file mode 100644 index 0000000..d853334 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Create.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Create + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs b/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs new file mode 100644 index 0000000..49ca694 --- /dev/null +++ b/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class DefaultIfEmpty + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Distinct.cs b/src/UniTask.NetCore/Linq/Distinct.cs new file mode 100644 index 0000000..980cae0 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Distinct.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Distinct + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ElementAt.cs b/src/UniTask.NetCore/Linq/ElementAt.cs new file mode 100644 index 0000000..d92970a --- /dev/null +++ b/src/UniTask.NetCore/Linq/ElementAt.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ElementAt + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ElementAtOrDefault.cs b/src/UniTask.NetCore/Linq/ElementAtOrDefault.cs new file mode 100644 index 0000000..929c9c5 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ElementAtOrDefault.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ElementAtOrDefault + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Empty.cs b/src/UniTask.NetCore/Linq/Empty.cs new file mode 100644 index 0000000..8d2f288 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Empty.cs @@ -0,0 +1,48 @@ +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Empty() + { + return Cysharp.Threading.Tasks.Linq.Empty.Instance; + } + } + + internal class Empty : IUniTaskAsyncEnumerable + { + public static readonly IUniTaskAsyncEnumerable Instance = new Empty(); + + Empty() + { + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return Enumerator.Instance; + } + + class Enumerator : IUniTaskAsyncEnumerator + { + public static readonly IUniTaskAsyncEnumerator Instance = new Enumerator(); + + Enumerator() + { + } + + public T Current => default; + + public UniTask MoveNextAsync() + { + return CompletedTasks.False; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Except.cs b/src/UniTask.NetCore/Linq/Except.cs new file mode 100644 index 0000000..db2aa41 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Except.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Except + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/First.cs b/src/UniTask.NetCore/Linq/First.cs new file mode 100644 index 0000000..ebc630c --- /dev/null +++ b/src/UniTask.NetCore/Linq/First.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class First + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/FirstOrDefault.cs b/src/UniTask.NetCore/Linq/FirstOrDefault.cs new file mode 100644 index 0000000..8766cab --- /dev/null +++ b/src/UniTask.NetCore/Linq/FirstOrDefault.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class FirstOrDefault + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ForEach.cs b/src/UniTask.NetCore/Linq/ForEach.cs new file mode 100644 index 0000000..956c319 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ForEach.cs @@ -0,0 +1,177 @@ +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static UniTask ForEachAsync(this IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(action, nameof(action)); + + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); + } + + public static UniTask ForEachAsync(this IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(action, nameof(action)); + + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); + } + + public static UniTask ForEachAwaitAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(action, nameof(action)); + + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); + } + + public static UniTask ForEachAwaitAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(action, nameof(action)); + + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); + } + + public static UniTask ForEachAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(action, nameof(action)); + + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); + } + + public static UniTask ForEachAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(action, nameof(action)); + + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); + } + } + + internal static class ForEach + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + action(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + int index = 0; + while (await e.MoveNextAsync()) + { + action(e.Current, checked(index++)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + await action(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + int index = 0; + while (await e.MoveNextAsync()) + { + await action(e.Current, checked(index++)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + await action(e.Current, cancellationToken); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/GroupBy.cs b/src/UniTask.NetCore/Linq/GroupBy.cs new file mode 100644 index 0000000..46629e6 --- /dev/null +++ b/src/UniTask.NetCore/Linq/GroupBy.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class GroupBy + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/GroupJoin.cs b/src/UniTask.NetCore/Linq/GroupJoin.cs new file mode 100644 index 0000000..ddaeaf7 --- /dev/null +++ b/src/UniTask.NetCore/Linq/GroupJoin.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class GroupJoin + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Intersect.cs b/src/UniTask.NetCore/Linq/Intersect.cs new file mode 100644 index 0000000..4207678 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Intersect.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Intersect + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask.NetCore/Linq/Join.cs new file mode 100644 index 0000000..1b1aa09 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Join.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Join + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Last.cs b/src/UniTask.NetCore/Linq/Last.cs new file mode 100644 index 0000000..940b967 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Last.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Last + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/LastOrDefault.cs b/src/UniTask.NetCore/Linq/LastOrDefault.cs new file mode 100644 index 0000000..b18f736 --- /dev/null +++ b/src/UniTask.NetCore/Linq/LastOrDefault.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class LastOrDefault + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/LongCount.cs b/src/UniTask.NetCore/Linq/LongCount.cs new file mode 100644 index 0000000..9abb9a2 --- /dev/null +++ b/src/UniTask.NetCore/Linq/LongCount.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class LongCount + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Max.cs b/src/UniTask.NetCore/Linq/Max.cs new file mode 100644 index 0000000..78520f5 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Max.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Max + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Min.cs b/src/UniTask.NetCore/Linq/Min.cs new file mode 100644 index 0000000..02294af --- /dev/null +++ b/src/UniTask.NetCore/Linq/Min.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Min + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/OfType.cs b/src/UniTask.NetCore/Linq/OfType.cs new file mode 100644 index 0000000..b49404c --- /dev/null +++ b/src/UniTask.NetCore/Linq/OfType.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class OfType + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/OrderBy.cs b/src/UniTask.NetCore/Linq/OrderBy.cs new file mode 100644 index 0000000..e661ad2 --- /dev/null +++ b/src/UniTask.NetCore/Linq/OrderBy.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class OrderBy + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/OrderByDescending.cs b/src/UniTask.NetCore/Linq/OrderByDescending.cs new file mode 100644 index 0000000..309a0f2 --- /dev/null +++ b/src/UniTask.NetCore/Linq/OrderByDescending.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class OrderByDescending + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Prepend.cs b/src/UniTask.NetCore/Linq/Prepend.cs new file mode 100644 index 0000000..b5d7d8c --- /dev/null +++ b/src/UniTask.NetCore/Linq/Prepend.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Prepend + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Range.cs b/src/UniTask.NetCore/Linq/Range.cs new file mode 100644 index 0000000..c48e2da --- /dev/null +++ b/src/UniTask.NetCore/Linq/Range.cs @@ -0,0 +1,76 @@ +using Cysharp.Threading.Tasks.Internal; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable 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(); + + return new Cysharp.Threading.Tasks.Linq.Range(start, count); + } + } + + internal class Range : IUniTaskAsyncEnumerable + { + readonly int start; + readonly int end; + + public Range(int start, int count) + { + this.start = start; + this.end = start + count; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(start, end, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly int start; + readonly int end; + int current; + CancellationToken cancellationToken; + + public Enumerator(int start, int end, CancellationToken cancellationToken) + { + this.start = start; + this.end = end; + this.cancellationToken = cancellationToken; + + this.current = 0; + } + + public int Current => current; + + public UniTask MoveNextAsync() + { + if (cancellationToken.IsCancellationRequested) return CompletedTasks.False; + + current++; + + if (current != end) + { + return CompletedTasks.True; + } + + return CompletedTasks.False; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Repeat.cs b/src/UniTask.NetCore/Linq/Repeat.cs new file mode 100644 index 0000000..a4f6415 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Repeat.cs @@ -0,0 +1,69 @@ +using Cysharp.Threading.Tasks.Internal; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Repeat(TResult element, int count) + { + if (count < 0) throw Error.ArgumentOutOfRange(nameof(count)); + + return new Repeat(element, count); + } + } + + internal class Repeat : IUniTaskAsyncEnumerable + { + readonly TResult element; + readonly int count; + + public Repeat(TResult element, int count) + { + this.element = element; + this.count = count; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(element, count, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly TResult element; + readonly int count; + int remaining; + CancellationToken cancellationToken; + + public Enumerator(TResult element, int count, CancellationToken cancellationToken) + { + this.element = element; + this.count = count; + this.cancellationToken = cancellationToken; + + this.remaining = count; + } + + public TResult Current => element; + + public UniTask MoveNextAsync() + { + if (cancellationToken.IsCancellationRequested) return CompletedTasks.False; + + if (remaining-- != 0) + { + return CompletedTasks.True; + } + + return CompletedTasks.False; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Reverse.cs b/src/UniTask.NetCore/Linq/Reverse.cs new file mode 100644 index 0000000..c59f44b --- /dev/null +++ b/src/UniTask.NetCore/Linq/Reverse.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Reverse + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Select.cs b/src/UniTask.NetCore/Linq/Select.cs new file mode 100644 index 0000000..eff3144 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Select.cs @@ -0,0 +1,309 @@ +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Select(this IUniTaskAsyncEnumerable source, Func selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new Cysharp.Threading.Tasks.Linq.Select(source, selector); + } + + public static IUniTaskAsyncEnumerable Select(this IUniTaskAsyncEnumerable source, Func selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new Cysharp.Threading.Tasks.Linq.SelectInt(source, selector); + } + + public static IUniTaskAsyncEnumerable SelectAwait(this IUniTaskAsyncEnumerable source, Func> selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new Cysharp.Threading.Tasks.Linq.SelectAwait(source, selector); + } + + public static IUniTaskAsyncEnumerable SelectAwait(this IUniTaskAsyncEnumerable source, Func> selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new Cysharp.Threading.Tasks.Linq.SelectAwaitInt(source, selector); + } + + public static IUniTaskAsyncEnumerable SelectAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new Cysharp.Threading.Tasks.Linq.SelectAwaitCancellation(source, selector); + } + + public static IUniTaskAsyncEnumerable SelectAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new Cysharp.Threading.Tasks.Linq.SelectAwaitIntCancellation(source, selector); + } + } + + internal sealed class Select : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func selector; + + public Select(IUniTaskAsyncEnumerable source, Func selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorBase + { + readonly Func selector; + + public Enumerator(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.selector = selector; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + Current = selector(SourceCurrent); + result = true; + return true; + } + else + { + result = false; + return true; + } + } + } + } + + internal sealed class SelectInt : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func selector; + + public SelectInt(IUniTaskAsyncEnumerable source, Func selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorBase + { + readonly Func selector; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.selector = selector; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + Current = selector(SourceCurrent, checked(index++)); + result = true; + return true; + } + else + { + result = false; + return true; + } + } + } + } + + internal sealed class SelectAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> selector; + + public SelectAwait(IUniTaskAsyncEnumerable source, Func> selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> selector; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.selector = selector; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return selector(sourceCurrent); + } + + protected override bool TrySetCurrentCore(TResult awaitResult) + { + Current = awaitResult; + return true; + } + } + } + + internal sealed class SelectAwaitInt : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> selector; + + public SelectAwaitInt(IUniTaskAsyncEnumerable source, Func> selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> selector; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.selector = selector; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return selector(sourceCurrent, checked(index++)); + } + + protected override bool TrySetCurrentCore(TResult awaitResult) + { + Current = awaitResult; + return true; + } + } + } + + internal sealed class SelectAwaitCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> selector; + + public SelectAwaitCancellation(IUniTaskAsyncEnumerable source, Func> selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> selector; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.selector = selector; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return selector(sourceCurrent, cancellationToken); + } + + protected override bool TrySetCurrentCore(TResult awaitResult) + { + Current = awaitResult; + return true; + } + } + } + + internal sealed class SelectAwaitIntCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> selector; + + public SelectAwaitIntCancellation(IUniTaskAsyncEnumerable source, Func> selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> selector; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.selector = selector; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return selector(sourceCurrent, checked(index++), cancellationToken); + } + + protected override bool TrySetCurrentCore(TResult awaitResult) + { + Current = awaitResult; + return true; + } + } + } + +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/SelectMany.cs b/src/UniTask.NetCore/Linq/SelectMany.cs new file mode 100644 index 0000000..6f5ceee --- /dev/null +++ b/src/UniTask.NetCore/Linq/SelectMany.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class SelectMany + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/SequenceEqual.cs b/src/UniTask.NetCore/Linq/SequenceEqual.cs new file mode 100644 index 0000000..a297a45 --- /dev/null +++ b/src/UniTask.NetCore/Linq/SequenceEqual.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class SequenceEqual + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Single.cs b/src/UniTask.NetCore/Linq/Single.cs new file mode 100644 index 0000000..7bc0d69 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Single.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Single + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/SingleOrDefault.cs b/src/UniTask.NetCore/Linq/SingleOrDefault.cs new file mode 100644 index 0000000..ffec4ca --- /dev/null +++ b/src/UniTask.NetCore/Linq/SingleOrDefault.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class SingleOrDefault + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Skip.cs b/src/UniTask.NetCore/Linq/Skip.cs new file mode 100644 index 0000000..2ba8c9e --- /dev/null +++ b/src/UniTask.NetCore/Linq/Skip.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Skip + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/SkipLast.cs b/src/UniTask.NetCore/Linq/SkipLast.cs new file mode 100644 index 0000000..5f79cf2 --- /dev/null +++ b/src/UniTask.NetCore/Linq/SkipLast.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class SkipLast + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/SkipWhile.cs b/src/UniTask.NetCore/Linq/SkipWhile.cs new file mode 100644 index 0000000..cedbcef --- /dev/null +++ b/src/UniTask.NetCore/Linq/SkipWhile.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class SkipWhile + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Sum.cs b/src/UniTask.NetCore/Linq/Sum.cs new file mode 100644 index 0000000..d0636c3 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Sum.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Sum + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Take.cs b/src/UniTask.NetCore/Linq/Take.cs new file mode 100644 index 0000000..901720e --- /dev/null +++ b/src/UniTask.NetCore/Linq/Take.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Take + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/TakeLast.cs b/src/UniTask.NetCore/Linq/TakeLast.cs new file mode 100644 index 0000000..4b4d955 --- /dev/null +++ b/src/UniTask.NetCore/Linq/TakeLast.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class TakeLast + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/TakeWhile.cs b/src/UniTask.NetCore/Linq/TakeWhile.cs new file mode 100644 index 0000000..4445869 --- /dev/null +++ b/src/UniTask.NetCore/Linq/TakeWhile.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class TakeWhile + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ThenBy.cs b/src/UniTask.NetCore/Linq/ThenBy.cs new file mode 100644 index 0000000..71dfe81 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ThenBy.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ThenBy + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ThenByDescending.cs b/src/UniTask.NetCore/Linq/ThenByDescending.cs new file mode 100644 index 0000000..aadc421 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ThenByDescending.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ThenByDescending + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ToArray.cs b/src/UniTask.NetCore/Linq/ToArray.cs new file mode 100644 index 0000000..0410232 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToArray.cs @@ -0,0 +1,57 @@ +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 ToArrayAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + return Cysharp.Threading.Tasks.Linq.ToArray.InvokeAsync(source, cancellationToken); + } + } + + internal static class ToArray + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + TSource[] result = default; + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + result = Array.Empty(); + } + else + { + result = new TSource[i]; + Array.Copy(array, result, i); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + + return result; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToDictionary.cs b/src/UniTask.NetCore/Linq/ToDictionary.cs new file mode 100644 index 0000000..c24c914 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToDictionary.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ToDictionary + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ToEnumerable.cs b/src/UniTask.NetCore/Linq/ToEnumerable.cs new file mode 100644 index 0000000..64f1070 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToEnumerable.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ToEnumerable + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ToHashSet.cs b/src/UniTask.NetCore/Linq/ToHashSet.cs new file mode 100644 index 0000000..5787c40 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToHashSet.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ToHashSet + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ToList.cs b/src/UniTask.NetCore/Linq/ToList.cs new file mode 100644 index 0000000..0a6dabb --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToList.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ToList + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ToLookup.cs b/src/UniTask.NetCore/Linq/ToLookup.cs new file mode 100644 index 0000000..e205e65 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToLookup.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ToLookup + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/ToObservable.cs b/src/UniTask.NetCore/Linq/ToObservable.cs new file mode 100644 index 0000000..1f15910 --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToObservable.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class ToObservable + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Union.cs b/src/UniTask.NetCore/Linq/Union.cs new file mode 100644 index 0000000..3413223 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Union.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class Union + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/Where.cs b/src/UniTask.NetCore/Linq/Where.cs new file mode 100644 index 0000000..6d2a07d --- /dev/null +++ b/src/UniTask.NetCore/Linq/Where.cs @@ -0,0 +1,116 @@ +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) + { + return new Cysharp.Threading.Tasks.Linq.Where(source, predicate); + } + + public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + return new Cysharp.Threading.Tasks.Linq.WhereAwait(source, predicate); + } + } + + internal sealed class Where : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func predicate; + + public Where(IUniTaskAsyncEnumerable source, Func predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly Func predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (predicate(SourceCurrent)) + { + Current = SourceCurrent; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } + + internal sealed class WhereAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public WhereAwait(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent); + } + + protected override bool TrySetCurrentCore(bool awaitResult) + { + if (awaitResult) + { + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } + +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Zip.cs b/src/UniTask.NetCore/Linq/Zip.cs new file mode 100644 index 0000000..31dd547 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Zip.cs @@ -0,0 +1,308 @@ +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + + public static IUniTaskAsyncEnumerable<(TFirst First, TSecond Second)> Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + return Zip(first, second, (x, y) => (x, y)); + } + + public static IUniTaskAsyncEnumerable Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func resultSelector) + { + return new Cysharp.Threading.Tasks.Linq.Zip(first, second, resultSelector); + } + } + + internal sealed class Zip : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly Func resultSelector; + + public Zip(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func resultSelector) + { + this.first = first; + this.second = second; + this.resultSelector = resultSelector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, resultSelector, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action firstMoveNextCoreDelegate = FirstMoveNextCore; + static readonly Action secondMoveNextCoreDelegate = SecondMoveNextCore; + + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly Func resultSelector; + + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator firstEnumerator; + IUniTaskAsyncEnumerator secondEnumerator; + + UniTask.Awaiter firstAwaiter; + UniTask.Awaiter secondAwaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func resultSelector, CancellationToken cancellationToken) + { + this.first = first; + this.second = second; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + completionSource.Reset(); + + if (firstEnumerator == null) + { + firstEnumerator = first.GetAsyncEnumerator(cancellationToken); + secondEnumerator = second.GetAsyncEnumerator(cancellationToken); + } + + firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter(); + + if (firstAwaiter.IsCompleted) + { + FirstMoveNextCore(this); + } + else + { + firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this); + } + + return new UniTask(this, completionSource.Version); + } + + static void FirstMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.firstAwaiter.GetResult()) + { + self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); + if (self.secondAwaiter.IsCompleted) + { + SecondMoveNextCore(self); + } + else + { + self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + + static void SecondMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.secondAwaiter.GetResult()) + { + try + { + self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + + if (self.cancellationToken.IsCancellationRequested) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + else + { + self.completionSource.TrySetResult(true); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + + public async UniTask DisposeAsync() + { + if (firstEnumerator != null) + { + await firstEnumerator.DisposeAsync(); + } + if (secondEnumerator != null) + { + await secondEnumerator.DisposeAsync(); + } + } + } + } + + internal sealed class ZipAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly Func> resultSelector; + + public ZipAwait(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> resultSelector) + { + this.first = first; + this.second = second; + this.resultSelector = resultSelector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, resultSelector, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action firstMoveNextCoreDelegate = FirstMoveNextCore; + static readonly Action secondMoveNextCoreDelegate = SecondMoveNextCore; + static readonly Action unwrapResultTaskDelegate = UnwrapResultTask; + + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly Func> resultSelector; + + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator firstEnumerator; + IUniTaskAsyncEnumerator secondEnumerator; + + UniTask.Awaiter firstAwaiter; + UniTask.Awaiter secondAwaiter; + UniTask.Awaiter resultAwaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> resultSelector, CancellationToken cancellationToken) + { + this.first = first; + this.second = second; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + completionSource.Reset(); + + if (firstEnumerator == null) + { + firstEnumerator = first.GetAsyncEnumerator(cancellationToken); + secondEnumerator = second.GetAsyncEnumerator(cancellationToken); + } + + firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter(); + + if (firstAwaiter.IsCompleted) + { + FirstMoveNextCore(this); + } + else + { + firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this); + } + + return new UniTask(this, completionSource.Version); + } + + static void FirstMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.firstAwaiter.GetResult()) + { + self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); + if (self.secondAwaiter.IsCompleted) + { + SecondMoveNextCore(self); + } + else + { + self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + + static void SecondMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.secondAwaiter.GetResult()) + { + var task = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current); + self.resultAwaiter = task.GetAwaiter(); + if (self.resultAwaiter.IsCompleted) + { + UnwrapResultTask(self); + } + else + { + self.resultAwaiter.SourceOnCompleted(unwrapResultTaskDelegate, self); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + + static void UnwrapResultTask(object state) + { + var self = (Enumerator)state; + + try + { + self.Current = self.resultAwaiter.GetResult(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + + if (self.cancellationToken.IsCancellationRequested) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + else + { + self.completionSource.TrySetResult(true); + } + } + + public async UniTask DisposeAsync() + { + if (firstEnumerator != null) + { + await firstEnumerator.DisposeAsync(); + } + if (secondEnumerator != null) + { + await secondEnumerator.DisposeAsync(); + } + } + } + } + +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs new file mode 100644 index 0000000..1dfe395 --- /dev/null +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -0,0 +1,2643 @@ +using Cysharp.Threading.Tasks; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace ___Dummy +{ + + public interface IAsyncGrouping + { + } + + + public interface IOrderedAsyncEnumerable + { + + } + public static partial class _FileMaker + { + // Buffer,Distinct, DistinctUntilChanged, Do, MaxBy, MinBy, Never,Return, Throw + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AllAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AllAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AllAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AnyAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AnyAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AnyAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AnyAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Append(this IUniTaskAsyncEnumerable source, TSource element) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable AsAsyncEnumerable(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Cast(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Concat(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + throw new NotImplementedException(); + } + + public static UniTask ContainsAsync(this IUniTaskAsyncEnumerable source, TSource value, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask ContainsAsync(this IUniTaskAsyncEnumerable source, TSource value, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask CountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask CountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source, TSource defaultValue) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static UniTask ElementAtAsync(this IUniTaskAsyncEnumerable source, Int32 index, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask ElementAtOrDefaultAsync(this IUniTaskAsyncEnumerable source, Int32 index, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static UniTask FirstAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask FirstOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable JoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable JoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable JoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable JoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static UniTask LastAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LastOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LongCountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask LongCountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable OfType(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Prepend(this IUniTaskAsyncEnumerable source, TSource element) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Reverse(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static UniTask SequenceEqualAsync(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SequenceEqualAsync(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SingleOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Skip(this IUniTaskAsyncEnumerable source, Int32 count) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipLast(this IUniTaskAsyncEnumerable source, Int32 count) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Take(this IUniTaskAsyncEnumerable source, Int32 count) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeLast(this IUniTaskAsyncEnumerable source, Int32 count) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByAwait(this IOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByAwait(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByDescending(this IOrderedAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByDescending(this IOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByDescendingAwait(this IOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByDescendingAwait(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable ToAsyncEnumerable(this IEnumerable source) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable ToAsyncEnumerable(this IObservable source) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable ToAsyncEnumerable(this Task task) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IEnumerable ToEnumerable(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToListAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + throw new NotImplementedException(); + } + + public static IObservable ToObservable(this IUniTaskAsyncEnumerable source) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable WhereAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable WhereAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable> Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable ZipAwait(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable ZipAwaitWithCancellation(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> selector) + { + throw new NotImplementedException(); + } + + + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/UniTask.NetCore.csproj b/src/UniTask.NetCore/UniTask.NetCore.csproj index 512edf9..22e739d 100644 --- a/src/UniTask.NetCore/UniTask.NetCore.csproj +++ b/src/UniTask.NetCore/UniTask.NetCore.csproj @@ -7,25 +7,7 @@ - + diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index d982b12..3d797d3 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -1,46 +1,227 @@ using Cysharp.Threading.Tasks; + +using System.Linq; using System; +using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; +using System.Collections; +using System.Text; +using System.Text.RegularExpressions; +using System.Runtime.CompilerServices; +using Cysharp.Threading.Tasks.Linq; namespace NetCoreSandbox { class Program { + static string FlattenGenArgs(Type type) + { + if (type.IsGenericType) + { + var t = string.Join(", ", type.GetGenericArguments().Select(x => FlattenGenArgs(x))); + return Regex.Replace(type.Name, "`.+", "") + "<" + t + ">"; + } + //x.ReturnType.GetGenericArguments() + else + { + return type.Name; + } + } + + static async Task Main(string[] args) { - Console.WriteLine("Foo"); - var v = await outer().AsTask(); - Console.WriteLine("Bar:" + v); + + + + await UniTaskAsyncEnumerable.Range(1, 3).ForEachAsync(x => + { + if (x == 2) throw new Exception(); + + Console.WriteLine(x); + }); + + + + + + } - static async UniTask outer() + + + void Foo() { - //await Task.WhenAll(); + // AsyncEnumerable.t + + var sb = new StringBuilder(); + sb.AppendLine(@"using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ +"); + + + + var chako = typeof(AsyncEnumerable).GetMethods() + .OrderBy(x => x.Name) + .Select(x => + { + var ret = FlattenGenArgs(x.ReturnType); + + + var generics = string.Join(", ", x.GetGenericArguments().Select(x => x.Name)); + + if (x.GetParameters().Length == 0) return ""; + + var self = x.GetParameters().First(); + if (x.GetCustomAttributes(typeof(ExtensionAttribute), true).Length == 0) + { + return ""; + } + + var arg1Type = FlattenGenArgs(x.GetParameters().First().ParameterType); + + var others = string.Join(", ", x.GetParameters().Skip(1).Select(y => FlattenGenArgs(y.ParameterType) + " " + y.Name)); + + if (!string.IsNullOrEmpty(others)) + { + others = ", " + others; + } + + var template = $"public static {ret} {x.Name}<{generics}>(this {arg1Type} {self.Name}{others})"; + + + + return template.Replace("ValueTask", "UniTask").Replace("IAsyncEnumerable", "IUniTaskAsyncEnumerable").Replace("<>", ""); + }) + .Where(x => x != "") + .Select(x => x + "\r\n{\r\n throw new NotImplementedException();\r\n}") + .ToArray(); + + var huga = string.Join("\r\n\r\n", chako); + + + + + foreach (var item in typeof(AsyncEnumerable).GetMethods().Select(x => x.Name).Distinct()) + { + if (item.EndsWith("AwaitAsync") || item.EndsWith("AwaitWithCancellationAsync") || item.EndsWith("WithCancellation")) + { + continue; + } + + var item2 = item.Replace("Async", ""); + item2 = item2.Replace("Await", ""); + + var format = @" + internal sealed class {0} + {{ + }} +"; + + sb.Append(string.Format(format, item2)); + + } + + sb.Append("}"); + + + Console.WriteLine(sb.ToString()); - //var foo = await Task.WhenAny(Array.Empty>()); - await UniTask.WhenAny(new UniTask[0]); - return 10; - //var v = await DoAsync(); - //return v; } - static async UniTask DoAsync() + public static async IAsyncEnumerable AsyncGen() { - var tcs = new UniTaskCompletionSource(); - - tcs.TrySetResult(100); - - - var v = await tcs.Task; - - return v; + await UniTask.SwitchToThreadPool(); + yield return 10; + await UniTask.SwitchToThreadPool(); + yield return 100; } - - } + + class MyEnumerable : IEnumerable + { + public IEnumerator GetEnumerator() + { + return new MyEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + throw new NotImplementedException(); + } + } + + class MyEnumerator : IEnumerator + { + public int Current => throw new NotImplementedException(); + + object IEnumerator.Current => throw new NotImplementedException(); + + public void Dispose() + { + Console.WriteLine("Called Dispose"); + } + + public bool MoveNext() + { + throw new NotImplementedException(); + } + + public void Reset() + { + throw new NotImplementedException(); + } + } + + + + public class MyClass + { + public CustomAsyncEnumerator GetAsyncEnumerator() + { + //IAsyncEnumerable + return new CustomAsyncEnumerator(); + } + } + + + public struct CustomAsyncEnumerator + { + int count; + + public T Current + { + get + { + return default; + } + } + + public UniTask MoveNextAsync() + { + if (count++ == 3) + { + return UniTask.FromResult(false); + //return false; + } + return UniTask.FromResult(true); + } + + public UniTask DisposeAsync() + { + return default; + } + } + + + } diff --git a/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj b/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj index 86d58b5..34f4ac4 100644 --- a/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj +++ b/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj @@ -6,6 +6,10 @@ NetCoreSandbox + + + + diff --git a/src/UniTask.NetCoreTests/UnitTest1.cs b/src/UniTask.NetCoreTests/UnitTest1.cs index 1d51046..6ee36ce 100644 --- a/src/UniTask.NetCoreTests/UnitTest1.cs +++ b/src/UniTask.NetCoreTests/UnitTest1.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Xunit; namespace UniTask.NetCoreTests @@ -10,5 +11,9 @@ namespace UniTask.NetCoreTests { } + + } + + } diff --git a/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs b/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs index c02e541..9b584c2 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs @@ -20,6 +20,12 @@ namespace Cysharp.Threading.Tasks.Internal throw new ArgumentNullException(paramName); } + [MethodImpl(MethodImplOptions.NoInlining)] + internal static Exception ArgumentOutOfRange(string paramName) + { + throw new ArgumentOutOfRangeException(paramName); + } + [MethodImpl(MethodImplOptions.NoInlining)] public static void ThrowArgumentException(string message) { diff --git a/src/UniTask/Assets/Scenes/SandboxMain.cs b/src/UniTask/Assets/Scenes/SandboxMain.cs index 2b33874..728483f 100644 --- a/src/UniTask/Assets/Scenes/SandboxMain.cs +++ b/src/UniTask/Assets/Scenes/SandboxMain.cs @@ -32,7 +32,7 @@ public struct MyJob : IJob public enum MyEnum { - A,B,C + A, B, C } public class SandboxMain : MonoBehaviour @@ -85,6 +85,18 @@ public class SandboxMain : MonoBehaviour job.inOut.Dispose(); } + + async UniTaskVoid Update2() + { + + + async foreach (var _ in this.GetAsyncUpdateTrigger()) + { + // do anything + } + + } + void Start() { Application.SetStackTraceLogType(LogType.Error, StackTraceLogType.Full); @@ -144,7 +156,7 @@ public class SandboxMain : MonoBehaviour UniTask foo = UniTask.FromResult(10); // foo.Status.IsCanceled - + Foo(foo); diff --git a/src/UniTask/Packages/manifest.json b/src/UniTask/Packages/manifest.json index c55fa3f..caf0872 100644 --- a/src/UniTask/Packages/manifest.json +++ b/src/UniTask/Packages/manifest.json @@ -1,7 +1,7 @@ { "dependencies": { "com.unity.addressables": "1.8.3", - "com.unity.ads": "2.0.8", + "com.unity.ads": "3.4.4", "com.unity.analytics": "3.3.5", "com.unity.collab-proxy": "1.2.16", "com.unity.ext.nunit": "1.0.0", diff --git a/src/UniTask/ProjectSettings/ProjectVersion.txt b/src/UniTask/ProjectSettings/ProjectVersion.txt index 2873a29..c7d3fa9 100644 --- a/src/UniTask/ProjectSettings/ProjectVersion.txt +++ b/src/UniTask/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2019.3.9f1 -m_EditorVersionWithRevision: 2019.3.9f1 (e6e740a1c473) +m_EditorVersion: 2019.3.11f1 +m_EditorVersionWithRevision: 2019.3.11f1 (ceef2d848e70) From 856a049dd084cddc3a326750db3dc466ed3bbe9c Mon Sep 17 00:00:00 2001 From: neuecc Date: Fri, 8 May 2020 03:48:46 +0900 Subject: [PATCH 02/31] WithCancellation --- src/UniTask.NetCore/IAsyncEnumerable.cs | 54 ++++++++++++++++++++++++- src/UniTask.NetCore/Linq/Range.cs | 2 +- src/UniTask.NetCore/Linq/Repeat.cs | 2 +- src/UniTask.NetCoreSandbox/Program.cs | 11 ++++- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask.NetCore/IAsyncEnumerable.cs index 9c67692..dfc88e1 100644 --- a/src/UniTask.NetCore/IAsyncEnumerable.cs +++ b/src/UniTask.NetCore/IAsyncEnumerable.cs @@ -1,4 +1,5 @@ -using System.Threading; +using System.Runtime.InteropServices; +using System.Threading; namespace Cysharp.Threading.Tasks { @@ -17,4 +18,55 @@ namespace Cysharp.Threading.Tasks { UniTask DisposeAsync(); } + + public static class UniTaskAsyncEnumerableExtensions + { + public static UniTaskCancelableAsyncEnumerable WithCancellation(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + return new UniTaskCancelableAsyncEnumerable(source, cancellationToken); + } + } + + [StructLayout(LayoutKind.Auto)] + public readonly struct UniTaskCancelableAsyncEnumerable + { + private readonly IUniTaskAsyncEnumerable enumerable; + private readonly CancellationToken cancellationToken; + + internal UniTaskCancelableAsyncEnumerable(IUniTaskAsyncEnumerable enumerable, CancellationToken cancellationToken) + { + this.enumerable = enumerable; + this.cancellationToken = cancellationToken; + } + + public Enumerator GetAsyncEnumerator() + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(enumerable.GetAsyncEnumerator(cancellationToken)); + } + + [StructLayout(LayoutKind.Auto)] + public readonly struct Enumerator + { + private readonly IUniTaskAsyncEnumerator enumerator; + + internal Enumerator(IUniTaskAsyncEnumerator enumerator) + { + this.enumerator = enumerator; + } + + public T Current => enumerator.Current; + + public UniTask MoveNextAsync() + { + return enumerator.MoveNextAsync(); + } + + + public UniTask DisposeAsync() + { + return enumerator.DisposeAsync(); + } + } + } } \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Range.cs b/src/UniTask.NetCore/Linq/Range.cs index c48e2da..d07e7d6 100644 --- a/src/UniTask.NetCore/Linq/Range.cs +++ b/src/UniTask.NetCore/Linq/Range.cs @@ -55,7 +55,7 @@ namespace Cysharp.Threading.Tasks.Linq public UniTask MoveNextAsync() { - if (cancellationToken.IsCancellationRequested) return CompletedTasks.False; + cancellationToken.ThrowIfCancellationRequested(); current++; diff --git a/src/UniTask.NetCore/Linq/Repeat.cs b/src/UniTask.NetCore/Linq/Repeat.cs index a4f6415..42cdc10 100644 --- a/src/UniTask.NetCore/Linq/Repeat.cs +++ b/src/UniTask.NetCore/Linq/Repeat.cs @@ -50,7 +50,7 @@ namespace Cysharp.Threading.Tasks.Linq public UniTask MoveNextAsync() { - if (cancellationToken.IsCancellationRequested) return CompletedTasks.False; + cancellationToken.ThrowIfCancellationRequested(); if (remaining-- != 0) { diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 3d797d3..2aa34f9 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -32,17 +32,24 @@ namespace NetCoreSandbox static async Task Main(string[] args) { + var cts = new CancellationTokenSource(); + await foreach (var item in UniTaskAsyncEnumerable.Range(1, 3).WithCancellation(cts.Token)) + { + Console.WriteLine(item); + cts.Cancel(); + } - await UniTaskAsyncEnumerable.Range(1, 3).ForEachAsync(x => + /* + .ForEachAsync(x => { if (x == 2) throw new Exception(); Console.WriteLine(x); }); - + */ From ed0990e402d73fb21cb9b31dc8392a729d30b755 Mon Sep 17 00:00:00 2001 From: neuecc Date: Fri, 8 May 2020 12:08:15 +0900 Subject: [PATCH 03/31] generator and tests --- src/UniTask.NetCore/Linq/Count.cs | 911 ++------ src/UniTask.NetCore/Linq/Range.cs | 2 +- src/UniTask.NetCore/Linq/Repeat.cs | 20 +- src/UniTask.NetCore/Linq/Return.cs | 64 + src/UniTask.NetCore/Linq/Single.cs | 3 +- src/UniTask.NetCore/Linq/Sum.cs | 2007 ++++++++++------- src/UniTask.NetCore/Linq/Sum.tt | 167 ++ src/UniTask.NetCore/Linq/_FileMaker.cs | 1026 +-------- src/UniTask.NetCore/UniTask.NetCore.csproj | 27 + src/UniTask.NetCoreSandbox/Program.cs | 23 +- src/UniTask.NetCoreTests/Linq/Factory.cs | 65 + .../UniTask.NetCoreTests.csproj | 15 +- src/UniTask.NetCoreTests/UnitTest1.cs | 19 - 13 files changed, 1763 insertions(+), 2586 deletions(-) create mode 100644 src/UniTask.NetCore/Linq/Return.cs create mode 100644 src/UniTask.NetCore/Linq/Sum.tt create mode 100644 src/UniTask.NetCoreTests/Linq/Factory.cs delete mode 100644 src/UniTask.NetCoreTests/UnitTest1.cs diff --git a/src/UniTask.NetCore/Linq/Count.cs b/src/UniTask.NetCore/Linq/Count.cs index a95f9bc..659fee7 100644 --- a/src/UniTask.NetCore/Linq/Count.cs +++ b/src/UniTask.NetCore/Linq/Count.cs @@ -1,775 +1,144 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Count + public static partial class UniTaskAsyncEnumerable { + public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Count.InvokeAsync(source, cancellationToken); + } + + public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Count.InvokeAsync(source, cancellationToken); + } + + public static UniTask CountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Count.InvokeAsync(source, cancellationToken); + } + + public static UniTask CountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Count.InvokeAsync(source, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class Count + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Range.cs b/src/UniTask.NetCore/Linq/Range.cs index d07e7d6..35a4713 100644 --- a/src/UniTask.NetCore/Linq/Range.cs +++ b/src/UniTask.NetCore/Linq/Range.cs @@ -48,7 +48,7 @@ namespace Cysharp.Threading.Tasks.Linq this.end = end; this.cancellationToken = cancellationToken; - this.current = 0; + this.current = start - 1; } public int Current => current; diff --git a/src/UniTask.NetCore/Linq/Repeat.cs b/src/UniTask.NetCore/Linq/Repeat.cs index 42cdc10..405a96f 100644 --- a/src/UniTask.NetCore/Linq/Repeat.cs +++ b/src/UniTask.NetCore/Linq/Repeat.cs @@ -5,39 +5,39 @@ namespace Cysharp.Threading.Tasks.Linq { public static partial class UniTaskAsyncEnumerable { - public static IUniTaskAsyncEnumerable Repeat(TResult element, int count) + public static IUniTaskAsyncEnumerable Repeat(TElement element, int count) { if (count < 0) throw Error.ArgumentOutOfRange(nameof(count)); - return new Repeat(element, count); + return new Repeat(element, count); } } - internal class Repeat : IUniTaskAsyncEnumerable + internal class Repeat : IUniTaskAsyncEnumerable { - readonly TResult element; + readonly TElement element; readonly int count; - public Repeat(TResult element, int count) + public Repeat(TElement element, int count) { this.element = element; this.count = count; } - public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(element, count, cancellationToken); } - class Enumerator : IUniTaskAsyncEnumerator + class Enumerator : IUniTaskAsyncEnumerator { - readonly TResult element; + readonly TElement element; readonly int count; int remaining; CancellationToken cancellationToken; - public Enumerator(TResult element, int count, CancellationToken cancellationToken) + public Enumerator(TElement element, int count, CancellationToken cancellationToken) { this.element = element; this.count = count; @@ -46,7 +46,7 @@ namespace Cysharp.Threading.Tasks.Linq this.remaining = count; } - public TResult Current => element; + public TElement Current => element; public UniTask MoveNextAsync() { diff --git a/src/UniTask.NetCore/Linq/Return.cs b/src/UniTask.NetCore/Linq/Return.cs new file mode 100644 index 0000000..e7308f7 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Return.cs @@ -0,0 +1,64 @@ +using Cysharp.Threading.Tasks.Internal; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Return(TValue value) + { + return new Return(value); + } + } + + internal class Return : IUniTaskAsyncEnumerable + { + readonly TValue value; + + public Return(TValue value) + { + this.value = value; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(value, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly TValue value; + CancellationToken cancellationToken; + + bool called; + + public Enumerator(TValue value, CancellationToken cancellationToken) + { + this.value = value; + this.cancellationToken = cancellationToken; + this.called = false; + } + + public TValue Current => value; + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (!called) + { + called = true; + return CompletedTasks.True; + } + + return CompletedTasks.False; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Single.cs b/src/UniTask.NetCore/Linq/Single.cs index 7bc0d69..8fd06ae 100644 --- a/src/UniTask.NetCore/Linq/Single.cs +++ b/src/UniTask.NetCore/Linq/Single.cs @@ -1,6 +1,7 @@ namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Single + // avoid conflicts with System.Single + internal sealed class SingleOperator { } diff --git a/src/UniTask.NetCore/Linq/Sum.cs b/src/UniTask.NetCore/Linq/Sum.cs index d0636c3..c2a92ce 100644 --- a/src/UniTask.NetCore/Linq/Sum.cs +++ b/src/UniTask.NetCore/Linq/Sum.cs @@ -1,775 +1,1244 @@ -namespace Cysharp.Threading.Tasks.Linq +using System; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Sum + public static partial class UniTaskAsyncEnumerable { + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + } + internal static class Sum + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int32 sum = default; + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int32 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int64 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int64 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64 sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Single sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Single sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Double sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Double sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Decimal sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Decimal sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int32? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current.GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int32? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int64? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current.GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int64? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Single? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current.GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Single? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Double? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current.GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Double? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Decimal? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current.GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Decimal? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal? sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken)).GetValueOrDefault(); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/Sum.tt b/src/UniTask.NetCore/Linq/Sum.tt new file mode 100644 index 0000000..afc23bc --- /dev/null +++ b/src/UniTask.NetCore/Linq/Sum.tt @@ -0,0 +1,167 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + var types = new[] + { + typeof(int), + typeof(long), + typeof(float), + typeof(double), + typeof(decimal), + + typeof(int?), + typeof(long?), + typeof(float?), + typeof(double?), + typeof(decimal?), + }; + + Func IsNullable = x => x.IsGenericType; + Func TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name; + Func WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : ""; +#> +using System; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { +<# foreach(var t in types) { #> + public static UniTask<<#= TypeName(t) #>> SumAsync(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Sum.InvokeAsync(source, cancellationToken); + } + + public static UniTask<<#= TypeName(t) #>> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask<<#= TypeName(t) #>> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask<<#= TypeName(t) #>> SumAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Sum.InvokeAsync(source, selector, cancellationToken); + } + +<# } #> + } + + internal static class Sum + { +<# foreach(var t in types) { #> + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken) + { + <#= TypeName(t) #> sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += e.Current<#= WithSuffix(t) #>; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + <#= TypeName(t) #> sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += selector(e.Current)<#= WithSuffix(t) #>; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken) + { + <#= TypeName(t) #> sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current))<#= WithSuffix(t) #>; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken) + { + <#= TypeName(t) #> sum = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + sum += (await selector(e.Current, cancellationToken))<#= WithSuffix(t) #>; + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum; + } + +<# } #> + } +} diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 1dfe395..2fdc08d 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -161,22 +161,22 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -191,12 +191,12 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -236,12 +236,12 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -251,7 +251,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -286,12 +286,12 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -301,7 +301,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -331,26 +331,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask CountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask CountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source) { throw new NotImplementedException(); @@ -727,12 +707,12 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -817,7 +797,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -872,7 +852,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -907,12 +887,12 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -1047,7 +1027,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -1082,7 +1062,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) { throw new NotImplementedException(); } @@ -1349,206 +1329,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SumAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Take(this IUniTaskAsyncEnumerable source, Int32 count) { throw new NotImplementedException(); @@ -1875,769 +1655,3 @@ namespace ___Dummy } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/UniTask.NetCore.csproj b/src/UniTask.NetCore/UniTask.NetCore.csproj index 22e739d..c8c503d 100644 --- a/src/UniTask.NetCore/UniTask.NetCore.csproj +++ b/src/UniTask.NetCore/UniTask.NetCore.csproj @@ -10,4 +10,31 @@ + + + True + True + Sum.tt + + + + + + TextTemplatingFileGenerator + Sum.cs + + + + + + + + + + True + True + Sum.tt + + + diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 2aa34f9..1c671b9 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -32,14 +32,27 @@ namespace NetCoreSandbox static async Task Main(string[] args) { + var xs = await UniTaskAsyncEnumerable.Range(0, 0).ToArrayAsync(); + + Console.WriteLine(xs); + var cts = new CancellationTokenSource(); + // Enumerable.Sum( - await foreach (var item in UniTaskAsyncEnumerable.Range(1, 3).WithCancellation(cts.Token)) - { - Console.WriteLine(item); - cts.Cancel(); - } + + //await foreach (var item in UniTaskAsyncEnumerable.Range(1, 3).WithCancellation(cts.Token)) + //{ + // Console.WriteLine(item); + // cts.Cancel(); + //} + + + //AsyncEnumerable.SumAsync( + + + var a = await UniTaskAsyncEnumerable.Range(1, 100).SumAsync(); + Console.WriteLine(a); /* diff --git a/src/UniTask.NetCoreTests/Linq/Factory.cs b/src/UniTask.NetCoreTests/Linq/Factory.cs new file mode 100644 index 0000000..7d82724 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Factory.cs @@ -0,0 +1,65 @@ +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace UniTask.NetCoreTests.Linq +{ + public class Factory + { + [Theory] + [InlineData(0, 10)] + [InlineData(0, 0)] + [InlineData(1, 5)] + [InlineData(1, 0)] + [InlineData(0, 11)] + [InlineData(1, 11)] + public async Task RangeTest(int start, int count) + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).ToArrayAsync(); + var ys = Enumerable.Range(start, count).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Theory] + [InlineData("foo", 0)] + [InlineData("bar", 1)] + [InlineData("baz", 3)] + [InlineData("foobar", 10)] + [InlineData("foobarbaz", 11)] + public async Task RepeatTest(string value, int count) + { + var xs = await UniTaskAsyncEnumerable.Repeat(value, count).ToArrayAsync(); + var ys = Enumerable.Repeat(value, count).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task EmptyTest() + { + var xs = await UniTaskAsyncEnumerable.Empty().ToArrayAsync(); + var ys = Enumerable.Empty().ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Theory] + [InlineData(100)] + [InlineData((string)null)] + [InlineData("foo")] + public async Task ReturnTest(T value) + { + var xs = await UniTaskAsyncEnumerable.Return(value).ToArrayAsync(); + + xs.Length.Should().Be(1); + xs[0].Should().Be(value); + } + } + + +} diff --git a/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj b/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj index 3c86681..4fae4ea 100644 --- a/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj +++ b/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj @@ -9,10 +9,17 @@ - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/src/UniTask.NetCoreTests/UnitTest1.cs b/src/UniTask.NetCoreTests/UnitTest1.cs deleted file mode 100644 index 6ee36ce..0000000 --- a/src/UniTask.NetCoreTests/UnitTest1.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using Xunit; - -namespace UniTask.NetCoreTests -{ - public class UnitTest1 - { - [Fact] - public void Test1() - { - - } - - - } - - -} From c16433e0fea9f0e59fd17eaf426d9d48e564a916 Mon Sep 17 00:00:00 2001 From: neuecc Date: Fri, 8 May 2020 15:16:43 +0900 Subject: [PATCH 04/31] Never --- src/UniTask.NetCore/Linq/Never.cs | 57 ++++++++++++++++++++++++ src/UniTask.NetCoreTests/Linq/Factory.cs | 1 + 2 files changed, 58 insertions(+) create mode 100644 src/UniTask.NetCore/Linq/Never.cs diff --git a/src/UniTask.NetCore/Linq/Never.cs b/src/UniTask.NetCore/Linq/Never.cs new file mode 100644 index 0000000..88a1e00 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Never.cs @@ -0,0 +1,57 @@ +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Never() + { + return Cysharp.Threading.Tasks.Linq.Never.Instance; + } + } + + internal class Never : IUniTaskAsyncEnumerable + { + public static readonly IUniTaskAsyncEnumerable Instance = new Never(); + + Never() + { + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + CancellationToken cancellationToken; + + public Enumerator(CancellationToken cancellationToken) + { + this.cancellationToken = cancellationToken; + } + + public T Current => default; + + public UniTask MoveNextAsync() + { + var tcs = new UniTaskCompletionSource(); + + cancellationToken.Register(state => + { + var task = (UniTaskCompletionSource)state; + task.TrySetCanceled(cancellationToken); + }, tcs); + + return tcs.Task; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCoreTests/Linq/Factory.cs b/src/UniTask.NetCoreTests/Linq/Factory.cs index 7d82724..c2da016 100644 --- a/src/UniTask.NetCoreTests/Linq/Factory.cs +++ b/src/UniTask.NetCoreTests/Linq/Factory.cs @@ -59,6 +59,7 @@ namespace UniTask.NetCoreTests.Linq xs.Length.Should().Be(1); xs[0].Should().Be(value); } + } From d4511c0f677dacfc603a3e5a1890a40e8ddc07df Mon Sep 17 00:00:00 2001 From: neuecc Date: Sat, 9 May 2020 15:33:46 +0900 Subject: [PATCH 05/31] Average, MinMax, and others --- src/UniTask.NetCore/Linq/Average.cs | 2287 ++++++---- src/UniTask.NetCore/Linq/Average.tt | 237 ++ src/UniTask.NetCore/Linq/Max.cs | 2 +- src/UniTask.NetCore/Linq/Min.cs | 2 +- src/UniTask.NetCore/Linq/MinMax.cs | 3758 +++++++++++++++++ src/UniTask.NetCore/Linq/MinMax.tt | 261 ++ .../Linq/ToUniTaskAsyncEnumerable.cs | 1103 +++++ src/UniTask.NetCore/Linq/_Aggregate.cs | 775 ++++ src/UniTask.NetCore/Linq/_FileMaker.cs | 638 --- .../NetCore/UniTask.AsValueTask.cs | 122 + src/UniTask.NetCore/NetCore/UniTask.Run.cs | 112 + src/UniTask.NetCore/NetCore/UniTask.Yield.cs | 55 + src/UniTask.NetCore/UniTask.NetCore.csproj | 59 +- src/UniTask.NetCoreSandbox/Program.cs | 43 +- .../UniTask.NetCoreSandbox.csproj | 1 + src/UniTask.NetCoreTests/Linq/Aggregate.cs | 122 + src/UniTask.NetCoreTests/Linq/Convert.cs | 79 + src/UniTask.NetCoreTests/Linq/Factory.cs | 2 +- .../UniTask.NetCoreTests.csproj | 1 + .../Assets/Plugins/UniTask/Internal/Error.cs | 8 +- 20 files changed, 8208 insertions(+), 1459 deletions(-) create mode 100644 src/UniTask.NetCore/Linq/Average.tt create mode 100644 src/UniTask.NetCore/Linq/MinMax.cs create mode 100644 src/UniTask.NetCore/Linq/MinMax.tt create mode 100644 src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs create mode 100644 src/UniTask.NetCore/Linq/_Aggregate.cs create mode 100644 src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs create mode 100644 src/UniTask.NetCore/NetCore/UniTask.Run.cs create mode 100644 src/UniTask.NetCore/NetCore/UniTask.Yield.cs create mode 100644 src/UniTask.NetCoreTests/Linq/Aggregate.cs create mode 100644 src/UniTask.NetCoreTests/Linq/Convert.cs diff --git a/src/UniTask.NetCore/Linq/Average.cs b/src/UniTask.NetCore/Linq/Average.cs index a4c0f1e..975fba8 100644 --- a/src/UniTask.NetCore/Linq/Average.cs +++ b/src/UniTask.NetCore/Linq/Average.cs @@ -1,775 +1,1524 @@ -namespace Cysharp.Threading.Tasks.Linq +using System; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Average + public static partial class UniTaskAsyncEnumerable { + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + } + internal static class Average + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Int32 sum = 0; + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += e.Current; + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Int32 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int32 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int32 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current, cancellationToken); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Int64 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += e.Current; + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Int64 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int64 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int64 sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current, cancellationToken); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Single sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += e.Current; + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Single sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Single sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Single sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current, cancellationToken); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Double sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += e.Current; + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Double sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Double sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Double sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current, cancellationToken); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Decimal sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += e.Current; + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Decimal sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Decimal sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Decimal sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + checked + { + sum += await selector(e.Current, cancellationToken); + count++; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Int32? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Int32? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int32? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int32? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current, cancellationToken); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Int64? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Int64? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int64? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Int64? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current, cancellationToken); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (double)sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Single? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Single? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Single? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Single? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current, cancellationToken); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return (float)(sum / count); + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Double? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Double? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Double? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Double? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current, cancellationToken); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + long count = 0; + Decimal? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + long count = 0; + Decimal? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Decimal? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + Decimal? sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = await selector(e.Current, cancellationToken); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return sum / count; + } + + } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/Average.tt b/src/UniTask.NetCore/Linq/Average.tt new file mode 100644 index 0000000..003094e --- /dev/null +++ b/src/UniTask.NetCore/Linq/Average.tt @@ -0,0 +1,237 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + var types = new[] + { + (typeof(int), "double"), + (typeof(long), "double"), + (typeof(float),"float"), + (typeof(double),"double"), + (typeof(decimal),"decimal"), + + (typeof(int?),"double?"), + (typeof(long?),"double?"), + (typeof(float?),"float?"), + (typeof(double?),"double?"), + (typeof(decimal?),"decimal?"), + }; + + Func IsNullable = x => x.IsGenericType; + Func ElementType = x => IsNullable(x) ? x.GetGenericArguments()[0] : x; + Func TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name; + Func WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : ""; + Func CalcResult = x => { var e = ElementType(x); return (e == typeof(int) || e == typeof(long)) ? "(double)sum / count" : (e == typeof(float)) ? "(float)(sum / count)" : "sum / count"; }; +#> +using System; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { +<# foreach(var (t, ret) in types) { #> + public static UniTask<<#= ret #>> AverageAsync(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Average.InvokeAsync(source, cancellationToken); + } + + public static UniTask<<#= ret #>> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask<<#= ret #>> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask<<#= ret #>> AverageAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Average.InvokeAsync(source, selector, cancellationToken); + } + +<# } #> + } + + internal static class Average + { +<# foreach(var (t, ret) in types) { #> + public static async UniTask<<#= ret #>> InvokeAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken) + { + long count = 0; + <#= TypeName(t) #> sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { +<# if (IsNullable(t)) { #> + var v = e.Current; + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } +<# } else { #> + checked + { + sum += e.Current; + count++; + } +<# } #> + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return <#= CalcResult(t) #>; + } + + public static async UniTask<<#= ret #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + long count = 0; + <#= TypeName(t) #> sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { +<# if (IsNullable(t)) { #> + var v = selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } +<# } else { #> + checked + { + sum += selector(e.Current); + count++; + } +<# } #> + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return <#= CalcResult(t) #>; + } + + public static async UniTask<<#= ret #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken) + { + long count = 0; + <#= TypeName(t) #> sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { +<# if (IsNullable(t)) { #> + var v = await selector(e.Current); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } +<# } else { #> + checked + { + sum += await selector(e.Current); + count++; + } +<# } #> + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return <#= CalcResult(t) #>; + } + + public static async UniTask<<#= ret #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken) + { + long count = 0; + <#= TypeName(t) #> sum = 0; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { +<# if (IsNullable(t)) { #> + var v = await selector(e.Current, cancellationToken); + if (v.HasValue) + { + checked + { + sum += v.Value; + count++; + } + } +<# } else { #> + checked + { + sum += await selector(e.Current, cancellationToken); + count++; + } +<# } #> + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return <#= CalcResult(t) #>; + } + +<# } #> + } +} diff --git a/src/UniTask.NetCore/Linq/Max.cs b/src/UniTask.NetCore/Linq/Max.cs index 78520f5..08d8450 100644 --- a/src/UniTask.NetCore/Linq/Max.cs +++ b/src/UniTask.NetCore/Linq/Max.cs @@ -1,6 +1,6 @@ namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Max + internal static partial class Max { } diff --git a/src/UniTask.NetCore/Linq/Min.cs b/src/UniTask.NetCore/Linq/Min.cs index 02294af..e57270b 100644 --- a/src/UniTask.NetCore/Linq/Min.cs +++ b/src/UniTask.NetCore/Linq/Min.cs @@ -1,6 +1,6 @@ namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Min + internal static partial class Min { } diff --git a/src/UniTask.NetCore/Linq/MinMax.cs b/src/UniTask.NetCore/Linq/MinMax.cs new file mode 100644 index 0000000..d0c8102 --- /dev/null +++ b/src/UniTask.NetCore/Linq/MinMax.cs @@ -0,0 +1,3758 @@ +using System; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + } + + internal static partial class Min + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value < x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + } + + internal static partial class Max + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64 value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + + goto NEXT_LOOP; + } + + throw Error.NoElements(); + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int32? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Int64? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Single? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Double? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + Decimal? value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); + if(value == null) continue; + + goto NEXT_LOOP; + } + + return default; + + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); + if( x == null) continue; + if (value > x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + } +} diff --git a/src/UniTask.NetCore/Linq/MinMax.tt b/src/UniTask.NetCore/Linq/MinMax.tt new file mode 100644 index 0000000..c79ad3e --- /dev/null +++ b/src/UniTask.NetCore/Linq/MinMax.tt @@ -0,0 +1,261 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ assembly name="System.Core" #> +<#@ import namespace="System.Linq" #> +<#@ import namespace="System.Text" #> +<#@ import namespace="System.Collections.Generic" #> +<#@ output extension=".cs" #> +<# + var types = new[] + { + typeof(int), + typeof(long), + typeof(float), + typeof(double), + typeof(decimal), + + typeof(int?), + typeof(long?), + typeof(float?), + typeof(double?), + typeof(decimal?), + }; + + Func IsNullable = x => x.IsGenericType; + Func TypeName = x => IsNullable(x) ? x.GetGenericArguments()[0].Name + "?" : x.Name; + Func WithSuffix = x => IsNullable(x) ? ".GetValueOrDefault()" : ""; +#> +using System; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { +<# foreach(var (minMax, op) in new[]{("Min","<"), ("Max", ">")}) { #> +<# foreach(var t in types) { #> + public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return <#= minMax #>.InvokeAsync(source, cancellationToken); + } + + public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return <#= minMax #>.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return <#= minMax #>.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask<<#= TypeName(t) #>> <#= minMax #>AwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return <#= minMax #>.InvokeAsync(source, selector, cancellationToken); + } + +<# } #> + } + + internal static partial class <#= minMax #> + { +<# foreach(var t in types) { #> + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken) + { + <#= TypeName(t) #> value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = e.Current; +<# if (IsNullable(t)) { #> + if(value == null) continue; +<# } #> + goto NEXT_LOOP; + } + +<# if (IsNullable(t)) { #> + return default; +<# } else { #> + throw Error.NoElements(); +<# } #> + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = e.Current; +<# if (IsNullable(t)) { #> + if( x == null) continue; +<# } #> + if (value <#= op #> x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + <#= TypeName(t) #> value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = selector(e.Current); +<# if (IsNullable(t)) { #> + if(value == null) continue; +<# } #> + goto NEXT_LOOP; + } + +<# if (IsNullable(t)) { #> + return default; +<# } else { #> + throw Error.NoElements(); +<# } #> + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = selector(e.Current); +<# if (IsNullable(t)) { #> + if( x == null) continue; +<# } #> + if (value <#= op #> x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken) + { + <#= TypeName(t) #> value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current); +<# if (IsNullable(t)) { #> + if(value == null) continue; +<# } #> + goto NEXT_LOOP; + } + +<# if (IsNullable(t)) { #> + return default; +<# } else { #> + throw Error.NoElements(); +<# } #> + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current); +<# if (IsNullable(t)) { #> + if( x == null) continue; +<# } #> + if (value <#= op #> x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + + public static async UniTask<<#= TypeName(t) #>> InvokeAsync(IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken) + { + <#= TypeName(t) #> value = default; + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + value = await selector(e.Current, cancellationToken); +<# if (IsNullable(t)) { #> + if(value == null) continue; +<# } #> + goto NEXT_LOOP; + } + +<# if (IsNullable(t)) { #> + return default; +<# } else { #> + throw Error.NoElements(); +<# } #> + NEXT_LOOP: + + while (await e.MoveNextAsync()) + { + var x = await selector(e.Current, cancellationToken); +<# if (IsNullable(t)) { #> + if( x == null) continue; +<# } #> + if (value <#= op #> x) + { + value = x; + } + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return value; + } + +<# } #> +<# } #> + } +} diff --git a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs new file mode 100644 index 0000000..067738d --- /dev/null +++ b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs @@ -0,0 +1,1103 @@ +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; +using System.Threading; +using System.Threading.Tasks; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable ToUniTaskAsyncEnumerable(this IEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new ToUniTaskAsyncEnumerable(source); + } + + public static IUniTaskAsyncEnumerable ToUniTaskAsyncEnumerable(this Task source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new ToUniTaskAsyncEnumerableTask(source); + } + + public static IUniTaskAsyncEnumerable ToUniTaskAsyncEnumerable(this UniTask source) + { + return new ToUniTaskAsyncEnumerableUniTask(source); + } + + public static IUniTaskAsyncEnumerable ToUniTaskAsyncEnumerable(this IObservable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new ToUniTaskAsyncEnumerableObservable(source); + } + } + + internal class ToUniTaskAsyncEnumerable : IUniTaskAsyncEnumerable + { + readonly IEnumerable source; + + public ToUniTaskAsyncEnumerable(IEnumerable source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly IEnumerable source; + CancellationToken cancellationToken; + + IEnumerator enumerator; + + public Enumerator(IEnumerable source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + } + + public T Current => enumerator.Current; + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (enumerator == null) + { + enumerator = source.GetEnumerator(); + } + + if (enumerator.MoveNext()) + { + return CompletedTasks.True; + } + + return CompletedTasks.False; + } + + public UniTask DisposeAsync() + { + enumerator.Dispose(); + return default; + } + } + } + + internal class ToUniTaskAsyncEnumerableTask : IUniTaskAsyncEnumerable + { + readonly Task source; + + public ToUniTaskAsyncEnumerableTask(Task source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly Task source; + CancellationToken cancellationToken; + + T current; + bool called; + + public Enumerator(Task source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + + this.called = false; + } + + public T Current => current; + + public async UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (called) + { + return false; + } + called = true; + + current = await source; + return true; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } + + internal class ToUniTaskAsyncEnumerableUniTask : IUniTaskAsyncEnumerable + { + readonly UniTask source; + + public ToUniTaskAsyncEnumerableUniTask(UniTask source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly UniTask source; + CancellationToken cancellationToken; + + T current; + bool called; + + public Enumerator(UniTask source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + + this.called = false; + } + + public T Current => current; + + public async UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (called) + { + return false; + } + called = true; + + current = await source; + return true; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } + + internal class ToUniTaskAsyncEnumerableObservable : IUniTaskAsyncEnumerable + { + readonly IObservable source; + + public ToUniTaskAsyncEnumerableObservable(IObservable source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + return new Enumerator(source, cancellationToken); + } + + class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator, IObserver + { + static readonly Action OnCanceledDelegate = OnCanceled; + + readonly IObservable source; + CancellationToken cancellationToken; + + + bool subscribeCompleted; + readonly Queue queuedResult; + Exception error; + IDisposable subscription; + CancellationTokenRegistration cancellationTokenRegistration; + + public Enumerator(IObservable source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + this.queuedResult = new Queue(); + + if (cancellationToken.CanBeCanceled) + { + cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(OnCanceledDelegate, this); + } + } + + public T Current + { + get + { + if (error != null) + { + ExceptionDispatchInfo.Capture(error).Throw(); + } + + return queuedResult.Dequeue(); + } + } + + public UniTask MoveNextAsync() + { + lock (queuedResult) + { + if (cancellationToken.IsCancellationRequested) + { + return UniTask.FromCanceled(cancellationToken); + } + + if (subscription == null) + { + subscription = source.Subscribe(this); + } + + if (error != null) + { + return UniTask.FromException(error); + } + + if (queuedResult.Count != 0) + { + return CompletedTasks.True; + } + + if (subscribeCompleted) + { + return CompletedTasks.False; + } + + completionSource.Reset(); + return new UniTask(this, completionSource.Version); + } + } + + public UniTask DisposeAsync() + { + subscription.Dispose(); + cancellationTokenRegistration.Dispose(); + completionSource.Reset(); + return default; + } + + public void OnCompleted() + { + lock (queuedResult) + { + subscribeCompleted = true; + completionSource.TrySetResult(false); + } + } + + public void OnError(Exception error) + { + lock (queuedResult) + { + this.error = error; + completionSource.TrySetException(error); + } + } + + public void OnNext(T value) + { + lock (queuedResult) + { + queuedResult.Enqueue(value); + completionSource.TrySetResult(true); // include callback execution, too long lock? + } + } + + static void OnCanceled(object state) + { + var self = (Enumerator)state; + lock (self.queuedResult) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + } + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/_Aggregate.cs b/src/UniTask.NetCore/Linq/_Aggregate.cs new file mode 100644 index 0000000..388148b --- /dev/null +++ b/src/UniTask.NetCore/Linq/_Aggregate.cs @@ -0,0 +1,775 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + internal sealed class _Aggregate + { + } + + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 2fdc08d..0f3fd29 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -111,205 +111,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> AverageAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable Cast(this IUniTaskAsyncEnumerable source) { @@ -662,445 +463,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MaxAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable> source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func>> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask MinAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable OfType(this IUniTaskAsyncEnumerable source) { diff --git a/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs b/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs new file mode 100644 index 0000000..1c7a4e5 --- /dev/null +++ b/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs @@ -0,0 +1,122 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using System.Threading.Tasks.Sources; + +namespace Cysharp.Threading.Tasks +{ + public static class UniTaskValueTaskExtensions + { + public static ValueTask AsValueTask(this UniTask task) + { + ref var core = ref Unsafe.As(ref task); + if (core.source == null) + { + return default; + } + + return new ValueTask(new UniTaskValueTaskSource(core.source), core.token); + } + + public static ValueTask AsValueTask(this UniTask task) + { + ref var core = ref Unsafe.As, UniTaskToValueTask>(ref task); + if (core.source == null) + { + return new ValueTask(core.result); + } + + return new ValueTask(new UniTaskValueTaskSource(core.source), core.token); + } + + struct UniTaskToValueTask + { + public IUniTaskSource source; + public short token; + } + + class UniTaskValueTaskSource : IValueTaskSource + { + readonly IUniTaskSource source; + + public UniTaskValueTaskSource(IUniTaskSource source) + { + this.source = source; + } + + public void GetResult(short token) + { + source.GetResult(token); + } + + public ValueTaskSourceStatus GetStatus(short token) + { + var status = source.GetStatus(token); + switch (status) + { + case UniTaskStatus.Pending: + return ValueTaskSourceStatus.Pending; + case UniTaskStatus.Succeeded: + return ValueTaskSourceStatus.Succeeded; + case UniTaskStatus.Faulted: + return ValueTaskSourceStatus.Faulted; + case UniTaskStatus.Canceled: + return ValueTaskSourceStatus.Canceled; + default: + return (ValueTaskSourceStatus)status; + } + } + + public void OnCompleted(Action continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) + { + source.OnCompleted(continuation, state, token); + } + } + + struct UniTaskToValueTask + { + + public IUniTaskSource source; + public T result; + public short token; + } + + class UniTaskValueTaskSource : IValueTaskSource + { + readonly IUniTaskSource source; + + public UniTaskValueTaskSource(IUniTaskSource source) + { + this.source = source; + } + + public T GetResult(short token) + { + return source.GetResult(token); + } + + public ValueTaskSourceStatus GetStatus(short token) + { + var status = source.GetStatus(token); + switch (status) + { + case UniTaskStatus.Pending: + return ValueTaskSourceStatus.Pending; + case UniTaskStatus.Succeeded: + return ValueTaskSourceStatus.Succeeded; + case UniTaskStatus.Faulted: + return ValueTaskSourceStatus.Faulted; + case UniTaskStatus.Canceled: + return ValueTaskSourceStatus.Canceled; + default: + return (ValueTaskSourceStatus)status; + } + } + + public void OnCompleted(Action continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) + { + source.OnCompleted(continuation, state, token); + } + } + } +} diff --git a/src/UniTask.NetCore/NetCore/UniTask.Run.cs b/src/UniTask.NetCore/NetCore/UniTask.Run.cs new file mode 100644 index 0000000..16fe48a --- /dev/null +++ b/src/UniTask.NetCore/NetCore/UniTask.Run.cs @@ -0,0 +1,112 @@ +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks +{ + public partial struct UniTask + { + /// Run action on the threadPool and return to current SynchronizationContext if configureAwait = true. + public static async UniTask Run(Action action, bool configureAwait = true) + { + if (configureAwait) + { + var current = SynchronizationContext.Current; + await UniTask.SwitchToThreadPool(); + try + { + action(); + } + finally + { + if (current != null) + { + await UniTask.SwitchToSynchronizationContext(current); + } + } + } + else + { + await UniTask.SwitchToThreadPool(); + action(); + } + } + + /// Run action on the threadPool and return to current SynchronizationContext if configureAwait = true. + public static async UniTask Run(Action action, object state, bool configureAwait = true) + { + if (configureAwait) + { + var current = SynchronizationContext.Current; + await UniTask.SwitchToThreadPool(); + try + { + action(state); + } + finally + { + if (current != null) + { + await UniTask.SwitchToSynchronizationContext(current); + } + } + } + else + { + await UniTask.SwitchToThreadPool(); + action(state); + } + } + + /// Run action on the threadPool and return to current SynchronizationContext if configureAwait = true. + public static async UniTask Run(Func func, bool configureAwait = true) + { + if (configureAwait) + { + var current = SynchronizationContext.Current; + await UniTask.SwitchToThreadPool(); + try + { + return func(); + } + finally + { + if (current != null) + { + await UniTask.SwitchToSynchronizationContext(current); + } + } + } + else + { + await UniTask.SwitchToThreadPool(); + return func(); + } + } + + /// Run action on the threadPool and return to current SynchronizationContext if configureAwait = true. + public static async UniTask Run(Func func, object state, bool configureAwait = true) + { + if (configureAwait) + { + var current = SynchronizationContext.Current; + await UniTask.SwitchToThreadPool(); + try + { + return func(state); + } + finally + { + if (current != null) + { + await UniTask.SwitchToSynchronizationContext(current); + } + } + } + else + { + await UniTask.SwitchToThreadPool(); + return func(state); + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/NetCore/UniTask.Yield.cs b/src/UniTask.NetCore/NetCore/UniTask.Yield.cs new file mode 100644 index 0000000..1931f4e --- /dev/null +++ b/src/UniTask.NetCore/NetCore/UniTask.Yield.cs @@ -0,0 +1,55 @@ +using System; +using System.Runtime.CompilerServices; +using System.Threading; + +namespace Cysharp.Threading.Tasks +{ + public partial struct UniTask + { + public static UniTask.YieldAwaitable Yield() + { + return default; + } + + public readonly struct YieldAwaitable + { + public Awaiter GetAwaiter() + { + return default; + } + + public readonly struct Awaiter : ICriticalNotifyCompletion + { + static readonly SendOrPostCallback SendOrPostCallbackDelegate = Continuation; + static readonly WaitCallback WaitCallbackDelegate = Continuation; + + public bool IsCompleted => false; + + public void GetResult() { } + + public void OnCompleted(Action continuation) + { + UnsafeOnCompleted(continuation); + } + + public void UnsafeOnCompleted(Action continuation) + { + var syncContext = SynchronizationContext.Current; + if (syncContext != null) + { + syncContext.Post(SendOrPostCallbackDelegate, continuation); + } + else + { + ThreadPool.UnsafeQueueUserWorkItem(WaitCallbackDelegate, continuation); + } + } + + static void Continuation(object state) + { + ((Action)state).Invoke(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/UniTask.NetCore.csproj b/src/UniTask.NetCore/UniTask.NetCore.csproj index c8c503d..027b681 100644 --- a/src/UniTask.NetCore/UniTask.NetCore.csproj +++ b/src/UniTask.NetCore/UniTask.NetCore.csproj @@ -7,34 +7,61 @@ - + - - True - True - Sum.tt - + - - TextTemplatingFileGenerator - Sum.cs - + + True + True + MinMax.tt + + + True + True + Sum.tt + - + + TextTemplatingFileGenerator + Average.cs + + + TextTemplatingFileGenerator + MinMax.cs + + + TextTemplatingFileGenerator + Sum.cs + - - True - True - Sum.tt - + + + + + + True + True + Average.tt + + + True + True + MinMax.tt + + + True + True + Sum.tt + diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 1c671b9..ca07a99 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -10,6 +10,8 @@ using System.Text; using System.Text.RegularExpressions; using System.Runtime.CompilerServices; using Cysharp.Threading.Tasks.Linq; +using System.Reactive.Linq; +using System.Reactive.Concurrency; namespace NetCoreSandbox { @@ -32,41 +34,18 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - var xs = await UniTaskAsyncEnumerable.Range(0, 0).ToArrayAsync(); - - Console.WriteLine(xs); - - var cts = new CancellationTokenSource(); - - // Enumerable.Sum( - - - //await foreach (var item in UniTaskAsyncEnumerable.Range(1, 3).WithCancellation(cts.Token)) - //{ - // Console.WriteLine(item); - // cts.Cancel(); - //} - - - //AsyncEnumerable.SumAsync( - - - var a = await UniTaskAsyncEnumerable.Range(1, 100).SumAsync(); - Console.WriteLine(a); - - - /* - .ForEachAsync(x => - { - if (x == 2) throw new Exception(); - - Console.WriteLine(x); - }); - */ - + int? foo = null; + if (foo > 100) + { + Console.WriteLine("Under Foo"); + } + else + { + Console.WriteLine("??"); + } } diff --git a/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj b/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj index 34f4ac4..c7cf11b 100644 --- a/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj +++ b/src/UniTask.NetCoreSandbox/UniTask.NetCoreSandbox.csproj @@ -8,6 +8,7 @@ + diff --git a/src/UniTask.NetCoreTests/Linq/Aggregate.cs b/src/UniTask.NetCoreTests/Linq/Aggregate.cs new file mode 100644 index 0000000..0962b2f --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Aggregate.cs @@ -0,0 +1,122 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetCoreTests.Linq +{ + public class Aggregate + { + [Theory] + [InlineData(0, 10)] + [InlineData(0, 1)] + [InlineData(10, 0)] + [InlineData(1, 11)] + public async Task Sum(int start, int count) + { + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).SumAsync(); + var ys = Enumerable.Range(start, count).Sum(); + xs.Should().Be(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).SumAsync(x => x * 2); + var ys = Enumerable.Range(start, count).Sum(x => x * 2); + xs.Should().Be(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).SumAwaitAsync(x => UniTask.Run(() => x)); + var ys = Enumerable.Range(start, count).Sum(x => x); + xs.Should().Be(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).SumAwaitCancellationAsync((x, _) => UniTask.Run(() => x)); + var ys = Enumerable.Range(start, count).Sum(x => x); + xs.Should().Be(ys); + } + } + + public static IEnumerable array1 = new object[][] + { + new object[]{new int[] { 1, 10, 100 } }, + new object[]{new int?[] { 1, null, 100 } }, + new object[]{new float[] { 1, 10, 100 } }, + new object[]{new float?[] { 1, null, 100 } }, + new object[]{new double[] { 1, 10, 100 } }, + new object[]{new double?[] { 1, null, 100 } }, + new object[]{new decimal[] { 1, 10, 100 } }, + new object[]{new decimal?[] { 1, null, 100 } }, + }; + + [Theory] + [MemberData(nameof(array1))] + public async Task Average(T arr) + { + switch (arr) + { + case int[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case int?[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case float[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case float?[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case double[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case double?[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case decimal[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + case decimal?[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().AverageAsync(); + var ys = array.Average(); + xs.Should().Be(ys); + } + break; + default: + break; + } + } + } +} diff --git a/src/UniTask.NetCoreTests/Linq/Convert.cs b/src/UniTask.NetCoreTests/Linq/Convert.cs new file mode 100644 index 0000000..b4fb59a --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Convert.cs @@ -0,0 +1,79 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetCoreTests.Linq +{ + public class Convert + { + [Fact] + public async Task ToAsyncEnumerable() + { + { + var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToArrayAsync(); + + xs.Length.Should().Be(100); + } + { + var xs = await Enumerable.Empty().ToUniTaskAsyncEnumerable().ToArrayAsync(); + + xs.Length.Should().Be(0); + } + } + + [Fact] + public async Task ToAsyncEnumerableTask() + { + var t = Task.FromResult(100); + var xs = await t.ToUniTaskAsyncEnumerable().ToArrayAsync(); + + xs.Length.Should().Be(1); + xs[0].Should().Be(100); + } + + [Fact] + public async Task ToAsyncEnumerableUniTask() + { + var t = UniTask.FromResult(100); + var xs = await t.ToUniTaskAsyncEnumerable().ToArrayAsync(); + + xs.Length.Should().Be(1); + xs[0].Should().Be(100); + } + + [Fact] + public async Task ToAsyncEnumerableObservable() + { + { + var xs = await Observable.Range(1, 100).ToUniTaskAsyncEnumerable().ToArrayAsync(); + var ys = await Observable.Range(1, 100).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + { + var xs = await Observable.Range(1, 100, ThreadPoolScheduler.Instance).ToUniTaskAsyncEnumerable().ToArrayAsync(); + var ys = await Observable.Range(1, 100, ThreadPoolScheduler.Instance).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + { + var xs = await Observable.Empty(ThreadPoolScheduler.Instance).ToUniTaskAsyncEnumerable().ToArrayAsync(); + var ys = await Observable.Empty(ThreadPoolScheduler.Instance).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + } + + } + + +} diff --git a/src/UniTask.NetCoreTests/Linq/Factory.cs b/src/UniTask.NetCoreTests/Linq/Factory.cs index c2da016..fb753e6 100644 --- a/src/UniTask.NetCoreTests/Linq/Factory.cs +++ b/src/UniTask.NetCoreTests/Linq/Factory.cs @@ -6,7 +6,7 @@ using System.Linq; using System.Threading.Tasks; using Xunit; -namespace UniTask.NetCoreTests.Linq +namespace NetCoreTests.Linq { public class Factory { diff --git a/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj b/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj index 4fae4ea..240d795 100644 --- a/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj +++ b/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj @@ -11,6 +11,7 @@ + all diff --git a/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs b/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs index 9b584c2..2ceae96 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs @@ -23,7 +23,13 @@ namespace Cysharp.Threading.Tasks.Internal [MethodImpl(MethodImplOptions.NoInlining)] internal static Exception ArgumentOutOfRange(string paramName) { - throw new ArgumentOutOfRangeException(paramName); + return new ArgumentOutOfRangeException(paramName); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + internal static Exception NoElements() + { + throw new InvalidOperationException("Source sequence doesn't contain any elements."); } [MethodImpl(MethodImplOptions.NoInlining)] From dd6a8da96fde31439049dd954b38b58b09b53740 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sat, 9 May 2020 22:06:51 +0900 Subject: [PATCH 06/31] generics MinMax and tests --- src/UniTask.NetCore/Linq/Max.cs | 967 +++++---------------- src/UniTask.NetCore/Linq/Min.cs | 967 +++++---------------- src/UniTask.NetCore/Linq/MinMax.cs | 165 ++-- src/UniTask.NetCore/Linq/MinMax.tt | 5 +- src/UniTask.NetCoreSandbox/Program.cs | 15 +- src/UniTask.NetCoreTests/Linq/Aggregate.cs | 227 +++++ 6 files changed, 711 insertions(+), 1635 deletions(-) diff --git a/src/UniTask.NetCore/Linq/Max.cs b/src/UniTask.NetCore/Linq/Max.cs index 08d8450..703226d 100644 --- a/src/UniTask.NetCore/Linq/Max.cs +++ b/src/UniTask.NetCore/Linq/Max.cs @@ -1,775 +1,200 @@ -namespace Cysharp.Threading.Tasks.Linq +using System; +using System.Collections.Generic; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq { - internal static partial class Max + public static partial class UniTaskAsyncEnumerable { + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Max.InvokeAsync(source, cancellationToken); + } + + public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MaxAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Max.InvokeAsync(source, selector, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static partial class Max + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + TSource value = default; + var comparer = Comparer.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 InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + TResult value = default; + var comparer = Comparer.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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + TResult value = default; + var comparer = Comparer.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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + TResult value = default; + var comparer = Comparer.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; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Min.cs b/src/UniTask.NetCore/Linq/Min.cs index e57270b..c54aaf9 100644 --- a/src/UniTask.NetCore/Linq/Min.cs +++ b/src/UniTask.NetCore/Linq/Min.cs @@ -1,775 +1,200 @@ -namespace Cysharp.Threading.Tasks.Linq +using System; +using System.Collections.Generic; +using System.Threading; +using Cysharp.Threading.Tasks.Internal; + +namespace Cysharp.Threading.Tasks.Linq { - internal static partial class Min + public static partial class UniTaskAsyncEnumerable { + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Min.InvokeAsync(source, cancellationToken); + } + + public static UniTask MinAsync(this IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } + + public static UniTask MinAwaitCancellationAsync(this IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(source, nameof(selector)); + + return Min.InvokeAsync(source, selector, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static partial class Min + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + TSource value = default; + var comparer = Comparer.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 InvokeAsync(IUniTaskAsyncEnumerable source, Func selector, CancellationToken cancellationToken) + { + TResult value = default; + var comparer = Comparer.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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + TResult value = default; + var comparer = Comparer.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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + TResult value = default; + var comparer = Comparer.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; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/MinMax.cs b/src/UniTask.NetCore/Linq/MinMax.cs index d0c8102..61f4c7f 100644 --- a/src/UniTask.NetCore/Linq/MinMax.cs +++ b/src/UniTask.NetCore/Linq/MinMax.cs @@ -341,7 +341,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value < x) + if (value > x) { value = x; } @@ -379,7 +379,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -417,7 +417,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -455,7 +455,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value < x) + if (value > x) { value = x; } @@ -493,7 +493,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value < x) + if (value > x) { value = x; } @@ -531,7 +531,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -569,7 +569,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -607,7 +607,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value < x) + if (value > x) { value = x; } @@ -645,7 +645,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value < x) + if (value > x) { value = x; } @@ -683,7 +683,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -721,7 +721,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -759,7 +759,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value < x) + if (value > x) { value = x; } @@ -797,7 +797,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value < x) + if (value > x) { value = x; } @@ -835,7 +835,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -873,7 +873,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -911,7 +911,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value < x) + if (value > x) { value = x; } @@ -949,7 +949,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value < x) + if (value > x) { value = x; } @@ -987,7 +987,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -1025,7 +1025,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value < x) + if (value > x) { value = x; } @@ -1063,7 +1063,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value < x) + if (value > x) { value = x; } @@ -1103,7 +1103,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1143,7 +1143,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1183,7 +1183,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1223,7 +1223,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1263,7 +1263,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1303,7 +1303,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1343,7 +1343,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1383,7 +1383,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1423,7 +1423,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1463,7 +1463,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1503,7 +1503,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1543,7 +1543,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1583,7 +1583,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1623,7 +1623,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1663,7 +1663,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1703,7 +1703,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1743,7 +1743,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1783,7 +1783,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1823,7 +1823,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1863,7 +1863,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value < x) + if (value > x) { value = x; } @@ -1880,6 +1880,10 @@ namespace Cysharp.Threading.Tasks.Linq return value; } + } + + public static partial class UniTaskAsyncEnumerable + { public static UniTask MaxAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) { Error.ThrowArgumentNullException(source, nameof(source)); @@ -2215,7 +2219,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value > x) + if (value < x) { value = x; } @@ -2253,7 +2257,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2291,7 +2295,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2329,7 +2333,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value > x) + if (value < x) { value = x; } @@ -2367,7 +2371,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value > x) + if (value < x) { value = x; } @@ -2405,7 +2409,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2443,7 +2447,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2481,7 +2485,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value > x) + if (value < x) { value = x; } @@ -2519,7 +2523,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value > x) + if (value < x) { value = x; } @@ -2557,7 +2561,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2595,7 +2599,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2633,7 +2637,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value > x) + if (value < x) { value = x; } @@ -2671,7 +2675,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value > x) + if (value < x) { value = x; } @@ -2709,7 +2713,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2747,7 +2751,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2785,7 +2789,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value > x) + if (value < x) { value = x; } @@ -2823,7 +2827,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = e.Current; - if (value > x) + if (value < x) { value = x; } @@ -2861,7 +2865,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2899,7 +2903,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current); - if (value > x) + if (value < x) { value = x; } @@ -2937,7 +2941,7 @@ namespace Cysharp.Threading.Tasks.Linq while (await e.MoveNextAsync()) { var x = await selector(e.Current, cancellationToken); - if (value > x) + if (value < x) { value = x; } @@ -2977,7 +2981,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3017,7 +3021,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3057,7 +3061,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3097,7 +3101,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3137,7 +3141,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3177,7 +3181,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3217,7 +3221,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3257,7 +3261,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3297,7 +3301,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3337,7 +3341,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3377,7 +3381,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3417,7 +3421,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3457,7 +3461,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3497,7 +3501,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3537,7 +3541,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3577,7 +3581,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3617,7 +3621,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = e.Current; if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3657,7 +3661,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3697,7 +3701,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3737,7 +3741,7 @@ namespace Cysharp.Threading.Tasks.Linq { var x = await selector(e.Current, cancellationToken); if( x == null) continue; - if (value > x) + if (value < x) { value = x; } @@ -3755,4 +3759,5 @@ namespace Cysharp.Threading.Tasks.Linq } } + } diff --git a/src/UniTask.NetCore/Linq/MinMax.tt b/src/UniTask.NetCore/Linq/MinMax.tt index c79ad3e..ef4f0f8 100644 --- a/src/UniTask.NetCore/Linq/MinMax.tt +++ b/src/UniTask.NetCore/Linq/MinMax.tt @@ -30,9 +30,9 @@ using Cysharp.Threading.Tasks.Internal; namespace Cysharp.Threading.Tasks.Linq { +<# foreach(var (minMax, op) in new[]{("Min",">"), ("Max", "<")}) { #> public static partial class UniTaskAsyncEnumerable { -<# foreach(var (minMax, op) in new[]{("Min","<"), ("Max", ">")}) { #> <# foreach(var t in types) { #> public static UniTask<<#= TypeName(t) #>> <#= minMax #>Async(this IUniTaskAsyncEnumerable<<#= TypeName(t) #>> source, CancellationToken cancellationToken = default) { @@ -255,7 +255,8 @@ namespace Cysharp.Threading.Tasks.Linq return value; } -<# } #> <# } #> } + +<# } #> } diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index ca07a99..fe5fb5f 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -34,18 +34,11 @@ namespace NetCoreSandbox static async Task Main(string[] args) { + var x = await new[] { 110, 50, 200 }.ToUniTaskAsyncEnumerable().MinAsync(); + Console.WriteLine(x); + // new object[] { }.Min( - int? foo = null; - - - if (foo > 100) - { - Console.WriteLine("Under Foo"); - } - else - { - Console.WriteLine("??"); - } + // AsyncEnumerable.MinAwaitAsync( } diff --git a/src/UniTask.NetCoreTests/Linq/Aggregate.cs b/src/UniTask.NetCoreTests/Linq/Aggregate.cs index 0962b2f..53fafb5 100644 --- a/src/UniTask.NetCoreTests/Linq/Aggregate.cs +++ b/src/UniTask.NetCoreTests/Linq/Aggregate.cs @@ -3,6 +3,7 @@ using Cysharp.Threading.Tasks.Linq; using FluentAssertions; using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using Xunit; @@ -118,5 +119,231 @@ namespace NetCoreTests.Linq break; } } + + + public static IEnumerable array2 = new object[][] + { + new object[]{new int[] { } }, + new object[]{new int[] { 5 } }, + new object[]{new int[] { 5, 10, 100 } }, + new object[]{new int[] { 10, 5,100 } }, + new object[]{new int[] { 100, 10, 5 } }, + + new object[]{new int?[] { } }, + new object[]{new int?[] { 5 } }, + new object[]{new int?[] { null, null, null } }, + new object[]{new int?[] { null, 5, 10, 100 } }, + new object[]{new int?[] { 10, 5,100, null } }, + new object[]{new int?[] { 100, 10, 5 } }, + + new object[]{new X[] { } }, + new object[]{new X[] { new X(5) } }, + new object[]{new X[] { new X(5), new X(10), new X(100) } }, + new object[]{new X[] { new X(10),new X( 5),new X(100) } }, + new object[]{new X[] { new X(100), new X(10),new X(5) } }, + + new object[]{new XX[] { } }, + new object[]{new XX[] { new XX(new X(5)) } }, + new object[]{new XX[] { new XX(new X(5)), new XX(new X(10)), new XX(new X(100)) } }, + new object[]{new XX[] { new XX(new X(10)),new XX(new X( 5)),new XX(new X(100)) } }, + new object[]{new XX[] { new XX(new X(100)), new XX(new X(10)),new XX(new X(5)) } }, + }; + + [Theory] + [MemberData(nameof(array2))] + public async Task Min(T arr) + { + switch (arr) + { + case int[] array: + { + { + if (array.Length == 0) + { + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().MinAsync()); + Assert.Throws(() => array.Min()); + } + else + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(); + var ys = array.Min(); + xs.Should().Be(ys); + } + } + { + if (array.Length == 0) + { + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().MinAsync(x => x * 2)); + Assert.Throws(() => array.Min(x => x * 2)); + } + else + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(x => x * 2); + var ys = array.Min(x => x * 2); + xs.Should().Be(ys); + } + } + } + break; + case int?[] array: + { + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(); + var ys = array.Min(); + xs.Should().Be(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(x => x); + var ys = array.Min(x => x); + xs.Should().Be(ys); + } + } + break; + case X[] array: + { + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(); + var ys = array.Min(); + xs.Should().Be(ys); + } + { + + if (array.Length == 0) + { + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().MinAsync(x => x.Value)); + Assert.Throws(() => array.Min(x => x.Value)); + } + else + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(x => x.Value); + var ys = array.Min(x => x.Value); + xs.Should().Be(ys); + } + } + } + break; + case XX[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().MinAsync(x => x.Value); + var ys = array.Min(x => x.Value); + xs.Should().Be(ys); + } + break; + default: + break; + } + } + + + + [Theory] + [MemberData(nameof(array2))] + public async Task Max(T arr) + { + switch (arr) + { + case int[] array: + { + { + if (array.Length == 0) + { + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().MaxAsync()); + Assert.Throws(() => array.Max()); + } + else + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(); + var ys = array.Max(); + xs.Should().Be(ys); + } + } + { + if (array.Length == 0) + { + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().MaxAsync(x => x * 2)); + Assert.Throws(() => array.Max(x => x * 2)); + } + else + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(x => x * 2); + var ys = array.Max(x => x * 2); + xs.Should().Be(ys); + } + } + } + break; + case int?[] array: + { + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(); + var ys = array.Max(); + xs.Should().Be(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(x => x); + var ys = array.Max(x => x); + xs.Should().Be(ys); + } + } + break; + case X[] array: + { + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(); + var ys = array.Max(); + xs.Should().Be(ys); + } + { + + if (array.Length == 0) + { + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().MaxAsync(x => x.Value)); + Assert.Throws(() => array.Max(x => x.Value)); + } + else + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(x => x.Value); + var ys = array.Max(x => x.Value); + xs.Should().Be(ys); + } + } + } + break; + case XX[] array: + { + var xs = await array.ToUniTaskAsyncEnumerable().MaxAsync(x => x.Value); + var ys = array.Max(x => x.Value); + xs.Should().Be(ys); + } + break; + default: + break; + } + } + + public class XX + { + public readonly X Value; + + public XX(X value) + { + this.Value = value; + } + } + + public class X : IComparable + { + public readonly int Value; + + public X(int value) + { + Value = value; + } + + public int CompareTo([AllowNull] X other) + { + return Comparer.Default.Compare(Value, other.Value); + } + } } } From aa8cb80866d8335d758218ee4cbef2694ba828cd Mon Sep 17 00:00:00 2001 From: neuecc Date: Sat, 9 May 2020 23:22:51 +0900 Subject: [PATCH 07/31] First, Last, Single, ElementAt --- src/UniTask.NetCore/Linq/ElementAt.cs | 825 +------------- .../Linq/ElementAtOrDefault.cs | 775 ------------- src/UniTask.NetCore/Linq/First.cs | 967 ++++------------ src/UniTask.NetCore/Linq/FirstOrDefault.cs | 775 ------------- src/UniTask.NetCore/Linq/Last.cs | 1007 ++++------------- src/UniTask.NetCore/Linq/LastOrDefault.cs | 775 ------------- src/UniTask.NetCore/Linq/Single.cs | 998 ++++------------ src/UniTask.NetCore/Linq/SingleOrDefault.cs | 775 ------------- .../Linq/ToUniTaskAsyncEnumerable.cs | 13 +- src/UniTask.NetCore/Linq/_FileMaker.cs | 119 +- .../NetCore/UniTask.AsValueTask.cs | 5 +- src/UniTask.NetCoreSandbox/Program.cs | 9 +- src/UniTask.NetCoreTests/Linq/FirstLast.cs | 258 +++++ .../Assets/Plugins/UniTask/Internal/Error.cs | 16 +- 14 files changed, 1002 insertions(+), 6315 deletions(-) delete mode 100644 src/UniTask.NetCore/Linq/ElementAtOrDefault.cs delete mode 100644 src/UniTask.NetCore/Linq/FirstOrDefault.cs delete mode 100644 src/UniTask.NetCore/Linq/LastOrDefault.cs delete mode 100644 src/UniTask.NetCore/Linq/SingleOrDefault.cs create mode 100644 src/UniTask.NetCoreTests/Linq/FirstLast.cs diff --git a/src/UniTask.NetCore/Linq/ElementAt.cs b/src/UniTask.NetCore/Linq/ElementAt.cs index d92970a..03450f4 100644 --- a/src/UniTask.NetCore/Linq/ElementAt.cs +++ b/src/UniTask.NetCore/Linq/ElementAt.cs @@ -1,775 +1,58 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class ElementAt + public static partial class UniTaskAsyncEnumerable { + public static UniTask ElementAtAsync(this IUniTaskAsyncEnumerable source, int index, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return ElementAt.InvokeAsync(source, index, cancellationToken, false); + } + + public static UniTask ElementAtOrDefaultAsync(this IUniTaskAsyncEnumerable source, int index, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return ElementAt.InvokeAsync(source, index, cancellationToken, true); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class ElementAt + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ElementAtOrDefault.cs b/src/UniTask.NetCore/Linq/ElementAtOrDefault.cs deleted file mode 100644 index 929c9c5..0000000 --- a/src/UniTask.NetCore/Linq/ElementAtOrDefault.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class ElementAtOrDefault - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/First.cs b/src/UniTask.NetCore/Linq/First.cs index ebc630c..9cbb2e0 100644 --- a/src/UniTask.NetCore/Linq/First.cs +++ b/src/UniTask.NetCore/Linq/First.cs @@ -1,775 +1,200 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class First + public static partial class UniTaskAsyncEnumerable { + public static UniTask FirstAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return First.InvokeAsync(source, cancellationToken, false); + } + + public static UniTask FirstAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return First.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask FirstAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return First.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask FirstAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return First.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask FirstOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return First.InvokeAsync(source, cancellationToken, true); + } + + public static UniTask FirstOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return First.InvokeAsync(source, predicate, cancellationToken, true); + } + + public static UniTask FirstOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return First.InvokeAsync(source, predicate, cancellationToken, true); + } + + public static UniTask FirstOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return First.InvokeAsync(source, predicate, cancellationToken, true); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class First + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/FirstOrDefault.cs b/src/UniTask.NetCore/Linq/FirstOrDefault.cs deleted file mode 100644 index 8766cab..0000000 --- a/src/UniTask.NetCore/Linq/FirstOrDefault.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class FirstOrDefault - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/Last.cs b/src/UniTask.NetCore/Linq/Last.cs index 940b967..430aedb 100644 --- a/src/UniTask.NetCore/Linq/Last.cs +++ b/src/UniTask.NetCore/Linq/Last.cs @@ -1,775 +1,240 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Last + public static partial class UniTaskAsyncEnumerable { + public static UniTask LastAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Last.InvokeAsync(source, cancellationToken, false); + } + + public static UniTask LastAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Last.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask LastAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Last.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask LastAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Last.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask LastOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Last.InvokeAsync(source, cancellationToken, true); + } + + public static UniTask LastOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Last.InvokeAsync(source, predicate, cancellationToken, true); + } + + public static UniTask LastOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Last.InvokeAsync(source, predicate, cancellationToken, true); + } + + public static UniTask LastOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Last.InvokeAsync(source, predicate, cancellationToken, true); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class Last + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/LastOrDefault.cs b/src/UniTask.NetCore/Linq/LastOrDefault.cs deleted file mode 100644 index b18f736..0000000 --- a/src/UniTask.NetCore/Linq/LastOrDefault.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class LastOrDefault - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/Single.cs b/src/UniTask.NetCore/Linq/Single.cs index 8fd06ae..512eb88 100644 --- a/src/UniTask.NetCore/Linq/Single.cs +++ b/src/UniTask.NetCore/Linq/Single.cs @@ -1,776 +1,230 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - // avoid conflicts with System.Single - internal sealed class SingleOperator + public static partial class UniTaskAsyncEnumerable { + public static UniTask SingleAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return SingleOperator.InvokeAsync(source, cancellationToken, false); + } + + public static UniTask SingleAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return SingleOperator.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask SingleAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return SingleOperator.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask SingleAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return SingleOperator.InvokeAsync(source, predicate, cancellationToken, false); + } + + public static UniTask SingleOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return SingleOperator.InvokeAsync(source, cancellationToken, true); + } + + public static UniTask SingleOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return SingleOperator.InvokeAsync(source, predicate, cancellationToken, true); + } + + public static UniTask SingleOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return SingleOperator.InvokeAsync(source, predicate, cancellationToken, true); + } + + public static UniTask SingleOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return SingleOperator.InvokeAsync(source, predicate, cancellationToken, true); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class SingleOperator + { + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/SingleOrDefault.cs b/src/UniTask.NetCore/Linq/SingleOrDefault.cs deleted file mode 100644 index ffec4ca..0000000 --- a/src/UniTask.NetCore/Linq/SingleOrDefault.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class SingleOrDefault - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs index 067738d..ed452c5 100644 --- a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs +++ b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs @@ -223,6 +223,8 @@ namespace Cysharp.Threading.Tasks.Linq CancellationToken cancellationToken; + bool useCachedCurrent; + T current; bool subscribeCompleted; readonly Queue queuedResult; Exception error; @@ -250,7 +252,14 @@ namespace Cysharp.Threading.Tasks.Linq ExceptionDispatchInfo.Capture(error).Throw(); } - return queuedResult.Dequeue(); + if (useCachedCurrent) + { + return current; + } + + current = queuedResult.Dequeue(); + useCachedCurrent = true; + return current; } } @@ -258,6 +267,8 @@ namespace Cysharp.Threading.Tasks.Linq { lock (queuedResult) { + useCachedCurrent = false; + if (cancellationToken.IsCancellationRequested) { return UniTask.FromCanceled(cancellationToken); diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 0f3fd29..a432008 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -172,45 +172,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask FirstAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - public static UniTask FirstAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask FirstAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask FirstAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask FirstOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask FirstOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask FirstOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask FirstOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer) @@ -403,46 +365,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask LastAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LastOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - + public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) { throw new NotImplementedException(); @@ -611,46 +534,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask SingleAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleOrDefaultAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleOrDefaultAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleOrDefaultAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SingleOrDefaultAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Skip(this IUniTaskAsyncEnumerable source, Int32 count) { throw new NotImplementedException(); diff --git a/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs b/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs index 1c7a4e5..834968a 100644 --- a/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs +++ b/src/UniTask.NetCore/NetCore/UniTask.AsValueTask.cs @@ -1,4 +1,6 @@ -using System; +#pragma warning disable 0649 + +using System; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Threading.Tasks.Sources; @@ -75,7 +77,6 @@ namespace Cysharp.Threading.Tasks struct UniTaskToValueTask { - public IUniTaskSource source; public T result; public short token; diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index fe5fb5f..18d9fc3 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -34,12 +34,13 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - var x = await new[] { 110, 50, 200 }.ToUniTaskAsyncEnumerable().MinAsync(); - Console.WriteLine(x); - // new object[] { }.Min( + var xs = new[] { 1, 10, 100 }.GetEnumerator(); + while (xs.MoveNext()) + { - // AsyncEnumerable.MinAwaitAsync( + } + Console.WriteLine(xs.MoveNext()); } diff --git a/src/UniTask.NetCoreTests/Linq/FirstLast.cs b/src/UniTask.NetCoreTests/Linq/FirstLast.cs new file mode 100644 index 0000000..185ae35 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/FirstLast.cs @@ -0,0 +1,258 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + +namespace NetCoreTests.Linq +{ + public class FirstLast + { + [Fact] + public async Task FirstTest() + { + { + await Assert.ThrowsAsync(async () => await Enumerable.Empty().ToUniTaskAsyncEnumerable().FirstAsync()); + Assert.Throws(() => Enumerable.Empty().First()); + + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().FirstAsync(); + var y = new[] { 99 }.First(); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().FirstAsync(x => x % 98 == 0)); + Assert.Throws(() => array.First(x => x % 98 == 0)); + + var x = await array.ToUniTaskAsyncEnumerable().FirstAsync(x => x % 2 == 0); + var y = array.First(x => x % 2 == 0); + x.Should().Be(y); + } + + { + var x = await Enumerable.Empty().ToUniTaskAsyncEnumerable().FirstOrDefaultAsync(); + var y = Enumerable.Empty().FirstOrDefault(); + x.Should().Be(y); + } + { + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().FirstOrDefaultAsync(); + var y = new[] { 99 }.FirstOrDefault(); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + var x = await array.ToUniTaskAsyncEnumerable().FirstOrDefaultAsync(x => x % 98 == 0); + var y = array.FirstOrDefault(x => x % 98 == 0); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + var x = await array.ToUniTaskAsyncEnumerable().FirstAsync(x => x % 2 == 0); + var y = array.FirstOrDefault(x => x % 2 == 0); + x.Should().Be(y); + } + } + + [Fact] + public async Task LastTest() + { + { + await Assert.ThrowsAsync(async () => await Enumerable.Empty().ToUniTaskAsyncEnumerable().LastAsync()); + Assert.Throws(() => Enumerable.Empty().Last()); + + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().LastAsync(); + var y = new[] { 99 }.Last(); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().LastAsync(x => x % 98 == 0)); + Assert.Throws(() => array.Last(x => x % 98 == 0)); + + var x = await array.ToUniTaskAsyncEnumerable().LastAsync(x => x % 2 == 0); + var y = array.Last(x => x % 2 == 0); + x.Should().Be(y); + } + + { + var x = await Enumerable.Empty().ToUniTaskAsyncEnumerable().LastOrDefaultAsync(); + var y = Enumerable.Empty().LastOrDefault(); + x.Should().Be(y); + } + { + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().LastOrDefaultAsync(); + var y = new[] { 99 }.LastOrDefault(); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + var x = await array.ToUniTaskAsyncEnumerable().LastOrDefaultAsync(x => x % 98 == 0); + var y = array.LastOrDefault(x => x % 98 == 0); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + var x = await array.ToUniTaskAsyncEnumerable().LastOrDefaultAsync(x => x % 2 == 0); + var y = array.LastOrDefault(x => x % 2 == 0); + x.Should().Be(y); + } + } + + [Fact] + public async Task SingleTest() + { + { + await Assert.ThrowsAsync(async () => await Enumerable.Empty().ToUniTaskAsyncEnumerable().SingleAsync()); + Assert.Throws(() => Enumerable.Empty().Single()); + + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().SingleAsync(); + var y = new[] { 99 }.Single(); + x.Should().Be(y); + + var array = new[] { 99, 11, 135, 10, 144, 800 }; + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().SingleAsync()); + Assert.Throws(() => array.Single()); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + // not found + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().SingleAsync(x => x % 999 == 0)); + Assert.Throws(() => array.Single(x => x % 999 == 0)); + // found multi + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().SingleAsync(x => x % 2 == 0)); + Assert.Throws(() => array.Single(x => x % 2 == 0)); + + { + var x = await array.ToUniTaskAsyncEnumerable().SingleAsync(x => x % 144 == 0); + var y = array.Single(x => x % 144 == 0); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().SingleAsync(x => x % 800 == 0); + var y = array.Single(x => x % 800 == 0); + x.Should().Be(y); + } + } + + { + { + var x = await Enumerable.Empty().ToUniTaskAsyncEnumerable().SingleOrDefaultAsync(); + var y = Enumerable.Empty().SingleOrDefault(); + x.Should().Be(y); + } + { + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().SingleOrDefaultAsync(); + var y = new[] { 99 }.SingleOrDefault(); + x.Should().Be(y); + + var array = new[] { 99, 11, 135, 10, 144, 800 }; + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().SingleOrDefaultAsync()); + Assert.Throws(() => array.SingleOrDefault()); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + // not found + { + var x = await array.ToUniTaskAsyncEnumerable().SingleOrDefaultAsync(x => x % 999 == 0); + var y = array.SingleOrDefault(x => x % 999 == 0); + x.Should().Be(y); + } + // found multi + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().SingleOrDefaultAsync(x => x % 2 == 0)); + Assert.Throws(() => array.SingleOrDefault(x => x % 2 == 0)); + + // normal + { + var x = await array.ToUniTaskAsyncEnumerable().SingleOrDefaultAsync(x => x % 144 == 0); + var y = array.SingleOrDefault(x => x % 144 == 0); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().SingleOrDefaultAsync(x => x % 800 == 0); + var y = array.SingleOrDefault(x => x % 800 == 0); + x.Should().Be(y); + } + } + } + } + + + [Fact] + public async Task ElementAtTest() + { + { + await Assert.ThrowsAsync(async () => await Enumerable.Empty().ToUniTaskAsyncEnumerable().ElementAtAsync(0)); + Assert.Throws(() => Enumerable.Empty().ElementAt(0)); + + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().ElementAtAsync(0); + var y = new[] { 99 }.ElementAt(0); + x.Should().Be(y); + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + await Assert.ThrowsAsync(async () => await array.ToUniTaskAsyncEnumerable().ElementAtAsync(10)); + Assert.Throws(() => array.ElementAt(10)); + + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtAsync(0); + var y = array.ElementAt(0); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtAsync(3); + var y = array.ElementAt(3); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtAsync(5); + var y = array.ElementAt(5); + x.Should().Be(y); + } + } + + + { + { + var x = await Enumerable.Empty().ToUniTaskAsyncEnumerable().ElementAtOrDefaultAsync(0); + var y = Enumerable.Empty().ElementAtOrDefault(0); + x.Should().Be(y); + } + { + var x = await new[] { 99 }.ToUniTaskAsyncEnumerable().ElementAtOrDefaultAsync(0); + var y = new[] { 99 }.ElementAtOrDefault(0); + x.Should().Be(y); + } + } + { + var array = new[] { 99, 11, 135, 10, 144, 800 }; + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtOrDefaultAsync(10); + var y = array.ElementAtOrDefault(10); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtOrDefaultAsync(0); + var y = array.ElementAtOrDefault(0); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtOrDefaultAsync(3); + var y = array.ElementAtOrDefault(3); + x.Should().Be(y); + } + { + var x = await array.ToUniTaskAsyncEnumerable().ElementAtOrDefaultAsync(5); + var y = array.ElementAtOrDefault(5); + x.Should().Be(y); + } + } + } + } + + +} diff --git a/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs b/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs index 2ceae96..5c7bc93 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Internal/Error.cs @@ -20,16 +20,22 @@ namespace Cysharp.Threading.Tasks.Internal throw new ArgumentNullException(paramName); } - [MethodImpl(MethodImplOptions.NoInlining)] - internal static Exception ArgumentOutOfRange(string paramName) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Exception ArgumentOutOfRange(string paramName) { return new ArgumentOutOfRangeException(paramName); } - [MethodImpl(MethodImplOptions.NoInlining)] - internal static Exception NoElements() + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Exception NoElements() { - throw new InvalidOperationException("Source sequence doesn't contain any elements."); + return new InvalidOperationException("Source sequence doesn't contain any elements."); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Exception MoreThanOneElement() + { + return new InvalidOperationException("Source sequence contains more than one element."); } [MethodImpl(MethodImplOptions.NoInlining)] From e93bcbf564a9aae913d463edb27a89a2fc96fa4d Mon Sep 17 00:00:00 2001 From: neuecc Date: Sat, 9 May 2020 23:33:27 +0900 Subject: [PATCH 08/31] Count, LongCount --- src/UniTask.NetCore/Linq/Count.cs | 6 +- src/UniTask.NetCore/Linq/LongCount.cs | 911 ++++----------------- src/UniTask.NetCore/Linq/_FileMaker.cs | 28 - src/UniTask.NetCoreTests/Linq/Aggregate.cs | 32 + 4 files changed, 175 insertions(+), 802 deletions(-) diff --git a/src/UniTask.NetCore/Linq/Count.cs b/src/UniTask.NetCore/Linq/Count.cs index 659fee7..a6ec863 100644 --- a/src/UniTask.NetCore/Linq/Count.cs +++ b/src/UniTask.NetCore/Linq/Count.cs @@ -18,7 +18,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return Count.InvokeAsync(source, cancellationToken); + return Count.InvokeAsync(source, predicate, cancellationToken); } public static UniTask CountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) @@ -26,7 +26,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return Count.InvokeAsync(source, cancellationToken); + return Count.InvokeAsync(source, predicate, cancellationToken); } public static UniTask CountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) @@ -34,7 +34,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return Count.InvokeAsync(source, cancellationToken); + return Count.InvokeAsync(source, predicate, cancellationToken); } } diff --git a/src/UniTask.NetCore/Linq/LongCount.cs b/src/UniTask.NetCore/Linq/LongCount.cs index 9abb9a2..13b8c0f 100644 --- a/src/UniTask.NetCore/Linq/LongCount.cs +++ b/src/UniTask.NetCore/Linq/LongCount.cs @@ -1,775 +1,144 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class LongCount + public static partial class UniTaskAsyncEnumerable { + public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return LongCount.InvokeAsync(source, cancellationToken); + } + + public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return LongCount.InvokeAsync(source, predicate, cancellationToken); + } + + public static UniTask LongCountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return LongCount.InvokeAsync(source, predicate, cancellationToken); + } + + public static UniTask LongCountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return LongCount.InvokeAsync(source, predicate, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class LongCount + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index a432008..7f5d3ea 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -152,15 +152,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask ElementAtAsync(this IUniTaskAsyncEnumerable source, Int32 index, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask ElementAtOrDefaultAsync(this IUniTaskAsyncEnumerable source, Int32 index, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) { @@ -366,25 +357,6 @@ namespace ___Dummy } - public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LongCountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask LongCountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable OfType(this IUniTaskAsyncEnumerable source) diff --git a/src/UniTask.NetCoreTests/Linq/Aggregate.cs b/src/UniTask.NetCoreTests/Linq/Aggregate.cs index 53fafb5..146bc1a 100644 --- a/src/UniTask.NetCoreTests/Linq/Aggregate.cs +++ b/src/UniTask.NetCoreTests/Linq/Aggregate.cs @@ -345,5 +345,37 @@ namespace NetCoreTests.Linq return Comparer.Default.Compare(Value, other.Value); } } + + + [Theory] + [InlineData(0, 10)] + [InlineData(0, 1)] + [InlineData(10, 0)] + [InlineData(1, 11)] + public async Task Count(int start, int count) + { + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).CountAsync(); + var ys = Enumerable.Range(start, count).Count(); + xs.Should().Be(ys); + } + + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).CountAsync(x => x % 2 == 0); + var ys = Enumerable.Range(start, count).Count(x => x % 2 == 0); + xs.Should().Be(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).LongCountAsync(); + var ys = Enumerable.Range(start, count).LongCount(); + xs.Should().Be(ys); + } + + { + var xs = await UniTaskAsyncEnumerable.Range(start, count).LongCountAsync(x => x % 2 == 0); + var ys = Enumerable.Range(start, count).LongCount(x => x % 2 == 0); + xs.Should().Be(ys); + } + } } } From 31b788a2c9f919a5559303a7c9c6d612d24bbb30 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 00:07:51 +0900 Subject: [PATCH 09/31] All, ANy, Contains, SequeuceEqual --- src/UniTask.NetCore/Linq/All.cs | 875 +++------------------ src/UniTask.NetCore/Linq/Any.cs | 903 ++++------------------ src/UniTask.NetCore/Linq/Contains.cs | 817 ++------------------ src/UniTask.NetCore/Linq/Count.cs | 18 +- src/UniTask.NetCore/Linq/LongCount.cs | 18 +- src/UniTask.NetCore/Linq/SequenceEqual.cs | 854 ++------------------ src/UniTask.NetCore/Linq/_FileMaker.cs | 52 -- src/UniTask.NetCoreTests/Linq/AllAny.cs | 112 +++ 8 files changed, 495 insertions(+), 3154 deletions(-) create mode 100644 src/UniTask.NetCoreTests/Linq/AllAny.cs diff --git a/src/UniTask.NetCore/Linq/All.cs b/src/UniTask.NetCore/Linq/All.cs index bc15cec..b8fb003 100644 --- a/src/UniTask.NetCore/Linq/All.cs +++ b/src/UniTask.NetCore/Linq/All.cs @@ -1,775 +1,108 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class All + public static partial class UniTaskAsyncEnumerable { + public static UniTask AllAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return All.InvokeAsync(source, predicate, cancellationToken); + } + + public static UniTask AllAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return All.InvokeAsync(source, predicate, cancellationToken); + } + + public static UniTask AllAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return All.InvokeAsync(source, predicate, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class All + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Any.cs b/src/UniTask.NetCore/Linq/Any.cs index b614c81..cf3cbfa 100644 --- a/src/UniTask.NetCore/Linq/Any.cs +++ b/src/UniTask.NetCore/Linq/Any.cs @@ -1,775 +1,136 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Any + public static partial class UniTaskAsyncEnumerable { + public static UniTask AnyAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Any.InvokeAsync(source, cancellationToken); + } + + public static UniTask AnyAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Any.InvokeAsync(source, predicate, cancellationToken); + } + + public static UniTask AnyAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Any.InvokeAsync(source, predicate, cancellationToken); + } + + public static UniTask AnyAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return Any.InvokeAsync(source, predicate, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class Any + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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 InvokeAsync(IUniTaskAsyncEnumerable source, Func> 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Contains.cs b/src/UniTask.NetCore/Linq/Contains.cs index b9d1b90..e38601c 100644 --- a/src/UniTask.NetCore/Linq/Contains.cs +++ b/src/UniTask.NetCore/Linq/Contains.cs @@ -1,775 +1,50 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Contains + public static partial class UniTaskAsyncEnumerable { + public static UniTask ContainsAsync(this IUniTaskAsyncEnumerable source, TSource value, CancellationToken cancellationToken = default) + { + return ContainsAsync(source, value, EqualityComparer.Default, cancellationToken); + } + + public static UniTask ContainsAsync(this IUniTaskAsyncEnumerable source, TSource value, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return Contains.InvokeAsync(source, value, comparer, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class Contains + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TSource value, IEqualityComparer 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Count.cs b/src/UniTask.NetCore/Linq/Count.cs index a6ec863..1cdcda3 100644 --- a/src/UniTask.NetCore/Linq/Count.cs +++ b/src/UniTask.NetCore/Linq/Count.cs @@ -10,7 +10,7 @@ namespace Cysharp.Threading.Tasks.Linq { Error.ThrowArgumentNullException(source, nameof(source)); - return Count.InvokeAsync(source, cancellationToken); + return Count.InvokeAsync(source, cancellationToken); } public static UniTask CountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) @@ -18,7 +18,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return Count.InvokeAsync(source, predicate, cancellationToken); + return Count.InvokeAsync(source, predicate, cancellationToken); } public static UniTask CountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) @@ -26,7 +26,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return Count.InvokeAsync(source, predicate, cancellationToken); + return Count.InvokeAsync(source, predicate, cancellationToken); } public static UniTask CountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) @@ -34,13 +34,13 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return Count.InvokeAsync(source, predicate, cancellationToken); + return Count.InvokeAsync(source, predicate, cancellationToken); } } - internal static class Count + internal static class Count { - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) { var count = 0; @@ -63,7 +63,7 @@ namespace Cysharp.Threading.Tasks.Linq return count; } - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) { var count = 0; @@ -89,7 +89,7 @@ namespace Cysharp.Threading.Tasks.Linq return count; } - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) { var count = 0; @@ -115,7 +115,7 @@ namespace Cysharp.Threading.Tasks.Linq return count; } - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) { var count = 0; diff --git a/src/UniTask.NetCore/Linq/LongCount.cs b/src/UniTask.NetCore/Linq/LongCount.cs index 13b8c0f..4460061 100644 --- a/src/UniTask.NetCore/Linq/LongCount.cs +++ b/src/UniTask.NetCore/Linq/LongCount.cs @@ -10,7 +10,7 @@ namespace Cysharp.Threading.Tasks.Linq { Error.ThrowArgumentNullException(source, nameof(source)); - return LongCount.InvokeAsync(source, cancellationToken); + return LongCount.InvokeAsync(source, cancellationToken); } public static UniTask LongCountAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) @@ -18,7 +18,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return LongCount.InvokeAsync(source, predicate, cancellationToken); + return LongCount.InvokeAsync(source, predicate, cancellationToken); } public static UniTask LongCountAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) @@ -26,7 +26,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return LongCount.InvokeAsync(source, predicate, cancellationToken); + return LongCount.InvokeAsync(source, predicate, cancellationToken); } public static UniTask LongCountAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) @@ -34,13 +34,13 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(predicate, nameof(predicate)); - return LongCount.InvokeAsync(source, predicate, cancellationToken); + return LongCount.InvokeAsync(source, predicate, cancellationToken); } } - internal static class LongCount + internal static class LongCount { - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) { long count = 0; @@ -63,7 +63,7 @@ namespace Cysharp.Threading.Tasks.Linq return count; } - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) { long count = 0; @@ -89,7 +89,7 @@ namespace Cysharp.Threading.Tasks.Linq return count; } - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) { long count = 0; @@ -115,7 +115,7 @@ namespace Cysharp.Threading.Tasks.Linq return count; } - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) { long count = 0; diff --git a/src/UniTask.NetCore/Linq/SequenceEqual.cs b/src/UniTask.NetCore/Linq/SequenceEqual.cs index a297a45..ccef8b6 100644 --- a/src/UniTask.NetCore/Linq/SequenceEqual.cs +++ b/src/UniTask.NetCore/Linq/SequenceEqual.cs @@ -1,775 +1,87 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class SequenceEqual + public static partial class UniTaskAsyncEnumerable { + public static UniTask SequenceEqualAsync(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, CancellationToken cancellationToken = default) + { + return SequenceEqualAsync(first, second, EqualityComparer.Default, cancellationToken); + } + + public static UniTask SequenceEqualAsync(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return SequenceEqual.InvokeAsync(first, second, comparer, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class SequenceEqual + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer 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(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 7f5d3ea..902b263 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -66,41 +66,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask AllAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AllAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AllAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AnyAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AnyAsync(this IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AnyAwaitAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AnyAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Append(this IUniTaskAsyncEnumerable source, TSource element) { throw new NotImplementedException(); @@ -122,15 +87,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask ContainsAsync(this IUniTaskAsyncEnumerable source, TSource value, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - public static UniTask ContainsAsync(this IUniTaskAsyncEnumerable source, TSource value, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source) { @@ -496,15 +453,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static UniTask SequenceEqualAsync(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask SequenceEqualAsync(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable Skip(this IUniTaskAsyncEnumerable source, Int32 count) { diff --git a/src/UniTask.NetCoreTests/Linq/AllAny.cs b/src/UniTask.NetCoreTests/Linq/AllAny.cs new file mode 100644 index 0000000..541c3db --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/AllAny.cs @@ -0,0 +1,112 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class AllAny + { + [Theory] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(1, 2)] + [InlineData(1, 3)] + [InlineData(0, 10)] + [InlineData(0, 11)] + public async Task AllTest(int start, int count) + { + var range = Enumerable.Range(start, count); + var x = await range.ToUniTaskAsyncEnumerable().AllAsync(x => x % 2 == 0); + var y = range.All(x => x % 2 == 0); + + x.Should().Be(y); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(1, 2)] + [InlineData(1, 3)] + [InlineData(0, 10)] + [InlineData(0, 11)] + public async Task AnyTest(int start, int count) + { + var range = Enumerable.Range(start, count); + { + var x = await range.ToUniTaskAsyncEnumerable().AnyAsync(); + var y = range.Any(); + + x.Should().Be(y); + } + { + var x = await range.ToUniTaskAsyncEnumerable().AnyAsync(x => x % 2 == 0); + var y = range.Any(x => x % 2 == 0); + + x.Should().Be(y); + } + } + + [Theory] + [InlineData(0, 0)] + [InlineData(1, 1)] + [InlineData(1, 2)] + [InlineData(1, 3)] + [InlineData(0, 10)] + [InlineData(0, 11)] + public async Task ContainsTest(int start, int count) + { + var range = Enumerable.Range(start, count); + foreach (var c in Enumerable.Range(0, 15)) + { + var x = await range.ToUniTaskAsyncEnumerable().ContainsAsync(c); + var y = range.Contains(c); + x.Should().Be(y); + } + } + + [Fact] + public async Task SequenceEqual() + { + // empty and empty + (await new int[0].ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[0].ToUniTaskAsyncEnumerable())).Should().BeTrue(); + (new int[0].SequenceEqual(new int[0])).Should().BeTrue(); + + // empty and exists + (await new int[0].ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1 }.ToUniTaskAsyncEnumerable())).Should().BeFalse(); + (new int[0].SequenceEqual(new int[] { 1 })).Should().BeFalse(); + + // exists and empty + (await new int[] { 1 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[0].ToUniTaskAsyncEnumerable())).Should().BeFalse(); + (new int[] { 1 }.SequenceEqual(new int[] { })).Should().BeFalse(); + + // samelength same value + (await new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable())).Should().BeTrue(); + (new int[] { 1, 2, 3 }.SequenceEqual(new int[] { 1, 2, 3 })).Should().BeTrue(); + + // samelength different value(first) + (await new int[] { 5, 2, 3 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable())).Should().BeFalse(); + + // samelength different value(middle) + (await new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1, 5, 3 }.ToUniTaskAsyncEnumerable())).Should().BeFalse(); + + // samelength different value(last) + (await new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1, 2, 5 }.ToUniTaskAsyncEnumerable())).Should().BeFalse(); + + // left is long + (await new int[] { 1, 2, 3, 4 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable())).Should().BeFalse(); + (new int[] { 1, 2, 3, 4 }.SequenceEqual(new int[] { 1, 2, 3 })).Should().BeFalse(); + + // right is long + (await new int[] { 1, 2, 3 }.ToUniTaskAsyncEnumerable().SequenceEqualAsync(new int[] { 1, 2, 3, 4 }.ToUniTaskAsyncEnumerable())).Should().BeFalse(); + (new int[] { 1, 2, 3 }.SequenceEqual(new int[] { 1, 2, 3, 4 })).Should().BeFalse(); + } + } +} From f37cd703a944e4e9e80991f71708b172e10a4df7 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 00:33:46 +0900 Subject: [PATCH 10/31] Aggregate and ForEach --- src/UniTask.NetCore/Linq/Aggregate.cs | 318 +++++++++ src/UniTask.NetCore/Linq/ForEach.cs | 26 +- src/UniTask.NetCore/Linq/_Aggregate.cs | 775 --------------------- src/UniTask.NetCore/Linq/_FileMaker.cs | 45 +- src/UniTask.NetCoreSandbox/Program.cs | 9 +- src/UniTask.NetCoreTests/Linq/Aggregate.cs | 115 +++ 6 files changed, 451 insertions(+), 837 deletions(-) create mode 100644 src/UniTask.NetCore/Linq/Aggregate.cs delete mode 100644 src/UniTask.NetCore/Linq/_Aggregate.cs diff --git a/src/UniTask.NetCore/Linq/Aggregate.cs b/src/UniTask.NetCore/Linq/Aggregate.cs new file mode 100644 index 0000000..723a010 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Aggregate.cs @@ -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 AggregateAsync(this IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, accumulator, cancellationToken); + } + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken); + } + + public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); + + return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); + + return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + + return Aggregate.InvokeAsync(source, seed, accumulator, cancellationToken); + } + + public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(accumulator, nameof(accumulator)); + Error.ThrowArgumentNullException(accumulator, nameof(resultSelector)); + + return Aggregate.InvokeAsync(source, seed, accumulator, resultSelector, cancellationToken); + } + } + + internal static class Aggregate + { + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TSource value; + if (await e.MoveNextAsync()) + { + value = e.Current; + } + else + { + throw Error.NoElements(); + } + + while (await e.MoveNextAsync()) + { + value = accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = accumulator(value, e.Current); + } + return resultSelector(value); + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + // with async + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TSource value; + if (await e.MoveNextAsync()) + { + value = e.Current; + } + else + { + throw Error.NoElements(); + } + + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current); + } + return await resultSelector(value); + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + + // with cancellation + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TSource value; + if (await e.MoveNextAsync()) + { + value = e.Current; + } + else + { + throw Error.NoElements(); + } + + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current, cancellationToken); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current, cancellationToken); + } + return value; + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken) + { + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + TAccumulate value = seed; + while (await e.MoveNextAsync()) + { + value = await accumulator(value, e.Current, cancellationToken); + } + return await resultSelector(value, cancellationToken); + + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ForEach.cs b/src/UniTask.NetCore/Linq/ForEach.cs index 956c319..600426c 100644 --- a/src/UniTask.NetCore/Linq/ForEach.cs +++ b/src/UniTask.NetCore/Linq/ForEach.cs @@ -11,7 +11,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); } public static UniTask ForEachAsync(this IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken = default) @@ -19,7 +19,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -27,7 +27,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -35,7 +35,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -43,7 +43,7 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); } public static UniTask ForEachAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken = default) @@ -51,13 +51,13 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(action, nameof(action)); - return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ForEach.InvokeAwaitWithCancellationAsync(source, action, cancellationToken); } } - internal static class ForEach + internal static class ForEach { - public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -76,7 +76,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) + public static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, Action action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -96,7 +96,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -115,7 +115,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -135,7 +135,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try @@ -154,7 +154,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) + public static async UniTask InvokeAwaitWithCancellationAsync(IUniTaskAsyncEnumerable source, Func action, CancellationToken cancellationToken) { var e = source.GetAsyncEnumerator(cancellationToken); try diff --git a/src/UniTask.NetCore/Linq/_Aggregate.cs b/src/UniTask.NetCore/Linq/_Aggregate.cs deleted file mode 100644 index 388148b..0000000 --- a/src/UniTask.NetCore/Linq/_Aggregate.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class _Aggregate - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 902b263..6754ed8 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -21,50 +21,7 @@ namespace ___Dummy { // Buffer,Distinct, DistinctUntilChanged, Do, MaxBy, MinBy, Never,Return, Throw - public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, Func accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func accumulator, Func resultSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask AggregateAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, TAccumulate seed, Func> accumulator, Func> resultSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } + public static IUniTaskAsyncEnumerable Append(this IUniTaskAsyncEnumerable source, TSource element) { diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 18d9fc3..6ca3f92 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -34,13 +34,12 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - var xs = new[] { 1, 10, 100 }.GetEnumerator(); - while (xs.MoveNext()) - { + new int[] { }.Aggregate((x, y) => x + y); - } - Console.WriteLine(xs.MoveNext()); + + + await Task.Yield(); } diff --git a/src/UniTask.NetCoreTests/Linq/Aggregate.cs b/src/UniTask.NetCoreTests/Linq/Aggregate.cs index 146bc1a..61ac6f7 100644 --- a/src/UniTask.NetCoreTests/Linq/Aggregate.cs +++ b/src/UniTask.NetCoreTests/Linq/Aggregate.cs @@ -377,5 +377,120 @@ namespace NetCoreTests.Linq xs.Should().Be(ys); } } + + + [Fact] + public async Task AggregateTest1() + { + // 0 + await Assert.ThrowsAsync(async () => await new int[] { }.ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y)); + Assert.Throws(() => new int[] { }.Aggregate((x, y) => x + y)); + + // 1 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y); + var b = Enumerable.Range(1, 1).Aggregate((x, y) => x + y); + a.Should().Be(b); + } + + // 2 + { + var a = await Enumerable.Range(1, 2).ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y); + var b = Enumerable.Range(1, 2).Aggregate((x, y) => x + y); + a.Should().Be(b); + } + + // 10 + { + var a = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().AggregateAsync((x, y) => x + y); + var b = Enumerable.Range(1, 10).Aggregate((x, y) => x + y); + a.Should().Be(b); + } + } + + [Fact] + public async Task AggregateTest2() + { + // 0 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + + // 1 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + + // 2 + { + var a = await Enumerable.Range(1, 2).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 2).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + + // 10 + { + var a = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y); + var b = Enumerable.Range(1, 10).Aggregate(1000, (x, y) => x + y); + a.Should().Be(b); + } + } + + [Fact] + public async Task AggregateTest3() + { + // 0 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + + // 1 + { + var a = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 1).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + + // 2 + { + var a = await Enumerable.Range(1, 2).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 2).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + + // 10 + { + var a = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().AggregateAsync(1000, (x, y) => x + y, x => (x * 99).ToString()); + var b = Enumerable.Range(1, 10).Aggregate(1000, (x, y) => x + y, x => (x * 99).ToString()); + a.Should().Be(b); + } + } + + [Fact] + public async Task ForEach() + { + var list = new List(); + await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().ForEachAsync(x => + { + list.Add(x); + }); + + list.Should().BeEquivalentTo(Enumerable.Range(1, 10)); + + var list2 = new List<(int, int)>(); + await Enumerable.Range(5, 10).ToUniTaskAsyncEnumerable().ForEachAsync((index, x) => + { + list2.Add((index, x)); + }); + + var list3 = Enumerable.Range(5, 10).Select((index, x) => (index, x)).ToArray(); + list2.Should().BeEquivalentTo(list3); + } } } From 716decd199bbf6d1e7bb04f4a63688bcab9c8422 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 02:39:13 +0900 Subject: [PATCH 11/31] ToDict, ToLookup, ToList, TOHashSet, ToObservable --- src/UniTask.NetCore/IAsyncEnumerable.cs | 1 - src/UniTask.NetCore/Linq/AsEnumerable.cs | 775 ---------- .../Linq/AsUniTaskAsyncEnumerable.cs | 10 + src/UniTask.NetCore/Linq/Empty.cs | 1 - src/UniTask.NetCore/Linq/Never.cs | 1 - src/UniTask.NetCore/Linq/Range.cs | 1 - src/UniTask.NetCore/Linq/Repeat.cs | 1 - src/UniTask.NetCore/Linq/Return.cs | 1 - src/UniTask.NetCore/Linq/Select.cs | 6 - src/UniTask.NetCore/Linq/ToArray.cs | 11 +- src/UniTask.NetCore/Linq/ToDictionary.cs | 1045 ++++--------- src/UniTask.NetCore/Linq/ToEnumerable.cs | 775 ---------- src/UniTask.NetCore/Linq/ToHashSet.cs | 809 +--------- src/UniTask.NetCore/Linq/ToList.cs | 809 +--------- src/UniTask.NetCore/Linq/ToLookup.cs | 1311 +++++++---------- src/UniTask.NetCore/Linq/ToObservable.cs | 864 ++--------- .../Linq/ToUniTaskAsyncEnumerable.cs | 4 - src/UniTask.NetCore/Linq/_FileMaker.cs | 163 +- src/UniTask.NetCoreSandbox/Program.cs | 19 +- src/UniTask.NetCoreTests/Linq/Convert.cs | 117 ++ 20 files changed, 1133 insertions(+), 5591 deletions(-) delete mode 100644 src/UniTask.NetCore/Linq/AsEnumerable.cs create mode 100644 src/UniTask.NetCore/Linq/AsUniTaskAsyncEnumerable.cs delete mode 100644 src/UniTask.NetCore/Linq/ToEnumerable.cs diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask.NetCore/IAsyncEnumerable.cs index dfc88e1..34d0218 100644 --- a/src/UniTask.NetCore/IAsyncEnumerable.cs +++ b/src/UniTask.NetCore/IAsyncEnumerable.cs @@ -41,7 +41,6 @@ namespace Cysharp.Threading.Tasks public Enumerator GetAsyncEnumerator() { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(enumerable.GetAsyncEnumerator(cancellationToken)); } diff --git a/src/UniTask.NetCore/Linq/AsEnumerable.cs b/src/UniTask.NetCore/Linq/AsEnumerable.cs deleted file mode 100644 index 4877fa5..0000000 --- a/src/UniTask.NetCore/Linq/AsEnumerable.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class AsEnumerable - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/AsUniTaskAsyncEnumerable.cs b/src/UniTask.NetCore/Linq/AsUniTaskAsyncEnumerable.cs new file mode 100644 index 0000000..c00452e --- /dev/null +++ b/src/UniTask.NetCore/Linq/AsUniTaskAsyncEnumerable.cs @@ -0,0 +1,10 @@ +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable AsUniTaskAsyncEnumerable(this IUniTaskAsyncEnumerable source) + { + return source; + } + } +} diff --git a/src/UniTask.NetCore/Linq/Empty.cs b/src/UniTask.NetCore/Linq/Empty.cs index 8d2f288..2b4adea 100644 --- a/src/UniTask.NetCore/Linq/Empty.cs +++ b/src/UniTask.NetCore/Linq/Empty.cs @@ -20,7 +20,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return Enumerator.Instance; } diff --git a/src/UniTask.NetCore/Linq/Never.cs b/src/UniTask.NetCore/Linq/Never.cs index 88a1e00..a735812 100644 --- a/src/UniTask.NetCore/Linq/Never.cs +++ b/src/UniTask.NetCore/Linq/Never.cs @@ -20,7 +20,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(cancellationToken); } diff --git a/src/UniTask.NetCore/Linq/Range.cs b/src/UniTask.NetCore/Linq/Range.cs index 35a4713..09c1f17 100644 --- a/src/UniTask.NetCore/Linq/Range.cs +++ b/src/UniTask.NetCore/Linq/Range.cs @@ -31,7 +31,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(start, end, cancellationToken); } diff --git a/src/UniTask.NetCore/Linq/Repeat.cs b/src/UniTask.NetCore/Linq/Repeat.cs index 405a96f..e74ddc2 100644 --- a/src/UniTask.NetCore/Linq/Repeat.cs +++ b/src/UniTask.NetCore/Linq/Repeat.cs @@ -26,7 +26,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(element, count, cancellationToken); } diff --git a/src/UniTask.NetCore/Linq/Return.cs b/src/UniTask.NetCore/Linq/Return.cs index e7308f7..b5364d4 100644 --- a/src/UniTask.NetCore/Linq/Return.cs +++ b/src/UniTask.NetCore/Linq/Return.cs @@ -22,7 +22,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(value, cancellationToken); } diff --git a/src/UniTask.NetCore/Linq/Select.cs b/src/UniTask.NetCore/Linq/Select.cs index eff3144..ca1479f 100644 --- a/src/UniTask.NetCore/Linq/Select.cs +++ b/src/UniTask.NetCore/Linq/Select.cs @@ -68,7 +68,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, selector, cancellationToken); } @@ -112,7 +111,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, selector, cancellationToken); } @@ -157,7 +155,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, selector, cancellationToken); } @@ -197,7 +194,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, selector, cancellationToken); } @@ -238,7 +234,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, selector, cancellationToken); } @@ -278,7 +273,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, selector, cancellationToken); } diff --git a/src/UniTask.NetCore/Linq/ToArray.cs b/src/UniTask.NetCore/Linq/ToArray.cs index 0410232..25c56ec 100644 --- a/src/UniTask.NetCore/Linq/ToArray.cs +++ b/src/UniTask.NetCore/Linq/ToArray.cs @@ -9,21 +9,24 @@ namespace Cysharp.Threading.Tasks.Linq { public static UniTask ToArrayAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) { - return Cysharp.Threading.Tasks.Linq.ToArray.InvokeAsync(source, cancellationToken); + Error.ThrowArgumentNullException(source, nameof(source)); + + return Cysharp.Threading.Tasks.Linq.ToArray.InvokeAsync(source, cancellationToken); } } - internal static class ToArray + internal static class ToArray { - internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + internal static async UniTask InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) { var pool = ArrayPool.Shared; var array = pool.Rent(16); TSource[] result = default; - var e = source.GetAsyncEnumerator(cancellationToken); + IUniTaskAsyncEnumerator e = default; try { + e = source.GetAsyncEnumerator(cancellationToken); var i = 0; while (await e.MoveNextAsync()) { diff --git a/src/UniTask.NetCore/Linq/ToDictionary.cs b/src/UniTask.NetCore/Linq/ToDictionary.cs index c24c914..56d65e2 100644 --- a/src/UniTask.NetCore/Linq/ToDictionary.cs +++ b/src/UniTask.NetCore/Linq/ToDictionary.cs @@ -1,775 +1,278 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class ToDictionary + public static partial class UniTaskAsyncEnumerable { + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return ToDictionary.InvokeAsync(source, keySelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToDictionary.InvokeAsync(source, keySelector, comparer, cancellationToken); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + + return ToDictionary.InvokeAsync(source, keySelector, elementSelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToDictionary.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return ToDictionary.InvokeAsync(source, keySelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToDictionary.InvokeAsync(source, keySelector, comparer, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + + return ToDictionary.InvokeAsync(source, keySelector, elementSelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToDictionary.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return ToDictionary.InvokeAsync(source, keySelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToDictionary.InvokeAsync(source, keySelector, comparer, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + + return ToDictionary.InvokeAsync(source, keySelector, elementSelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToDictionary.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class ToDictionary + { + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary(comparer); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + var key = keySelector(v); + dict.Add(key, v); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return dict; + } + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary(comparer); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + var key = keySelector(v); + var value = elementSelector(v); + dict.Add(key, value); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return dict; + } + + // with await + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary(comparer); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + var key = await keySelector(v); + dict.Add(key, v); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return dict; + } + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary(comparer); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + var key = await keySelector(v); + var value = await elementSelector(v); + dict.Add(key, value); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return dict; + } + + // with cancellation + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary(comparer); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + var key = await keySelector(v, cancellationToken); + dict.Add(key, v); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return dict; + } + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary(comparer); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + var v = e.Current; + var key = await keySelector(v, cancellationToken); + var value = await elementSelector(v, cancellationToken); + dict.Add(key, value); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return dict; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToEnumerable.cs b/src/UniTask.NetCore/Linq/ToEnumerable.cs deleted file mode 100644 index 64f1070..0000000 --- a/src/UniTask.NetCore/Linq/ToEnumerable.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class ToEnumerable - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/ToHashSet.cs b/src/UniTask.NetCore/Linq/ToHashSet.cs index 5787c40..d858db1 100644 --- a/src/UniTask.NetCore/Linq/ToHashSet.cs +++ b/src/UniTask.NetCore/Linq/ToHashSet.cs @@ -1,775 +1,42 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class ToHashSet + public static partial class UniTaskAsyncEnumerable { + public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class ToHashSet + { + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + var set = new HashSet(); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + set.Add(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return set; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToList.cs b/src/UniTask.NetCore/Linq/ToList.cs index 0a6dabb..07182c9 100644 --- a/src/UniTask.NetCore/Linq/ToList.cs +++ b/src/UniTask.NetCore/Linq/ToList.cs @@ -1,775 +1,42 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class ToList + public static partial class UniTaskAsyncEnumerable { + public static UniTask> ToListAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Cysharp.Threading.Tasks.Linq.ToList.InvokeAsync(source, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class ToList + { + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + var list = new List(); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + while (await e.MoveNextAsync()) + { + list.Add(e.Current); + } + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + + return list; + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToLookup.cs b/src/UniTask.NetCore/Linq/ToLookup.cs index e205e65..d0ccbaa 100644 --- a/src/UniTask.NetCore/Linq/ToLookup.cs +++ b/src/UniTask.NetCore/Linq/ToLookup.cs @@ -1,775 +1,544 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class ToLookup + public static partial class UniTaskAsyncEnumerable { + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return ToLookup.InvokeAsync(source, keySelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToLookup.InvokeAsync(source, keySelector, comparer, cancellationToken); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + + return ToLookup.InvokeAsync(source, keySelector, elementSelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToLookup.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return ToLookup.InvokeAsync(source, keySelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToLookup.InvokeAsync(source, keySelector, comparer, cancellationToken); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + + return ToLookup.InvokeAsync(source, keySelector, elementSelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToLookup.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return ToLookup.InvokeAsync(source, keySelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToLookup.InvokeAsync(source, keySelector, comparer, cancellationToken); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + + return ToLookup.InvokeAsync(source, keySelector, elementSelector, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return ToLookup.InvokeAsync(source, keySelector, elementSelector, comparer, cancellationToken); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal static class ToLookup + { + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + var e = source.GetAsyncEnumerator(cancellationToken); + try + { + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + return Lookup.CreateEmpty(); + } + else + { + return Lookup.Create(new ArraySegment(array, 0, i), keySelector, comparer); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + IUniTaskAsyncEnumerator e = default; + try + { + e = source.GetAsyncEnumerator(cancellationToken); + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + return Lookup.CreateEmpty(); + } + else + { + return Lookup.Create(new ArraySegment(array, 0, i), keySelector, elementSelector, comparer); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + + // with await + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + IUniTaskAsyncEnumerator e = default; + try + { + e = source.GetAsyncEnumerator(cancellationToken); + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + return Lookup.CreateEmpty(); + } + else + { + return await Lookup.CreateAsync(new ArraySegment(array, 0, i), keySelector, comparer); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + IUniTaskAsyncEnumerator e = default; + try + { + e = source.GetAsyncEnumerator(cancellationToken); + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + return Lookup.CreateEmpty(); + } + else + { + return await Lookup.CreateAsync(new ArraySegment(array, 0, i), keySelector, elementSelector, comparer); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + // with cancellation + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + IUniTaskAsyncEnumerator e = default; + try + { + e = source.GetAsyncEnumerator(cancellationToken); + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + return Lookup.CreateEmpty(); + } + else + { + return await Lookup.CreateAsync(new ArraySegment(array, 0, i), keySelector, comparer, cancellationToken); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var pool = ArrayPool.Shared; + var array = pool.Rent(16); + + IUniTaskAsyncEnumerator e = default; + try + { + e = source.GetAsyncEnumerator(cancellationToken); + var i = 0; + while (await e.MoveNextAsync()) + { + ArrayPoolUtil.EnsureCapacity(ref array, i, pool); + array[i++] = e.Current; + } + + if (i == 0) + { + return Lookup.CreateEmpty(); + } + else + { + return await Lookup.CreateAsync(new ArraySegment(array, 0, i), keySelector, elementSelector, comparer, cancellationToken); + } + } + finally + { + pool.Return(array, clearArray: !RuntimeHelpersAbstraction.IsWellKnownNoReferenceContainsType()); + + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + // Lookup + + class Lookup : ILookup + { + static readonly Lookup empty = new Lookup(new Dictionary>()); + + // original lookup keeps order but this impl does not(dictionary not guarantee) + readonly Dictionary> dict; + + Lookup(Dictionary> dict) + { + this.dict = dict; + } + + public static Lookup CreateEmpty() + { + return empty; + } + + public static Lookup Create(ArraySegment source, Func keySelector, IEqualityComparer comparer) + { + var dict = new Dictionary>(comparer); + + var arr = source.Array; + var c = source.Count; + for (int i = source.Offset; i < c; i++) + { + var key = keySelector(arr[i]); + + if (!dict.TryGetValue(key, out var list)) + { + list = new Grouping(key); + dict[key] = list; + } + + list.Add(arr[i]); + } + + return new Lookup(dict); + } + + public static Lookup Create(ArraySegment source, Func keySelector, Func elementSelector, IEqualityComparer comparer) + { + var dict = new Dictionary>(comparer); + + var arr = source.Array; + var c = source.Count; + for (int i = source.Offset; i < c; i++) + { + var key = keySelector(arr[i]); + var elem = elementSelector(arr[i]); + + if (!dict.TryGetValue(key, out var list)) + { + list = new Grouping(key); + dict[key] = list; + } + + list.Add(elem); + } + + return new Lookup(dict); + } + + public static async UniTask> CreateAsync(ArraySegment source, Func> keySelector, IEqualityComparer comparer) + { + var dict = new Dictionary>(comparer); + + var arr = source.Array; + var c = source.Count; + for (int i = source.Offset; i < c; i++) + { + var key = await keySelector(arr[i]); + + if (!dict.TryGetValue(key, out var list)) + { + list = new Grouping(key); + dict[key] = list; + } + + list.Add(arr[i]); + } + + return new Lookup(dict); + } + + public static async UniTask> CreateAsync(ArraySegment source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + var dict = new Dictionary>(comparer); + + var arr = source.Array; + var c = source.Count; + for (int i = source.Offset; i < c; i++) + { + var key = await keySelector(arr[i]); + var elem = await elementSelector(arr[i]); + + if (!dict.TryGetValue(key, out var list)) + { + list = new Grouping(key); + dict[key] = list; + } + + list.Add(elem); + } + + return new Lookup(dict); + } + + public static async UniTask> CreateAsync(ArraySegment source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary>(comparer); + + var arr = source.Array; + var c = source.Count; + for (int i = source.Offset; i < c; i++) + { + var key = await keySelector(arr[i], cancellationToken); + + if (!dict.TryGetValue(key, out var list)) + { + list = new Grouping(key); + dict[key] = list; + } + + list.Add(arr[i]); + } + + return new Lookup(dict); + } + + public static async UniTask> CreateAsync(ArraySegment source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + var dict = new Dictionary>(comparer); + + var arr = source.Array; + var c = source.Count; + for (int i = source.Offset; i < c; i++) + { + var key = await keySelector(arr[i], cancellationToken); + var elem = await elementSelector(arr[i], cancellationToken); + + if (!dict.TryGetValue(key, out var list)) + { + list = new Grouping(key); + dict[key] = list; + } + + list.Add(elem); + } + + return new Lookup(dict); + } + + public IEnumerable this[TKey key] => dict[key]; + + public int Count => dict.Count; + + public bool Contains(TKey key) + { + return dict.ContainsKey(key); + } + + public IEnumerator> GetEnumerator() + { + return dict.Values.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return dict.Values.GetEnumerator(); + } + } + + class Grouping : IGrouping + { + readonly List elements; + + public TKey Key { get; private set; } + + public Grouping(TKey key) + { + this.Key = key; + this.elements = new List(); + } + + public void Add(TElement value) + { + elements.Add(value); + } + public IEnumerator GetEnumerator() + { + return elements.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return elements.GetEnumerator(); + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToObservable.cs b/src/UniTask.NetCore/Linq/ToObservable.cs index 1f15910..4f48388 100644 --- a/src/UniTask.NetCore/Linq/ToObservable.cs +++ b/src/UniTask.NetCore/Linq/ToObservable.cs @@ -1,775 +1,97 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class ToObservable + public static partial class UniTaskAsyncEnumerable { + public static IObservable ToObservable(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new ToObservable(source); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class ToObservable : IObservable + { + readonly IUniTaskAsyncEnumerable source; + + public ToObservable(IUniTaskAsyncEnumerable source) + { + this.source = source; + } + + public IDisposable Subscribe(IObserver observer) + { + var ctd = new CancellationTokenDisposable(); + + RunAsync(source, observer, ctd.Token).Forget(); + + return ctd; + } + + static async UniTaskVoid RunAsync(IUniTaskAsyncEnumerable src, IObserver observer, CancellationToken cancellationToken) + { + // cancellationToken.IsCancellationRequested is called when Rx's Disposed. + // when disposed, finish silently. + + var e = src.GetAsyncEnumerator(cancellationToken); + try + { + bool hasNext; + + do + { + try + { + hasNext = await e.MoveNextAsync(); + } + catch (Exception ex) + { + if (cancellationToken.IsCancellationRequested) + { + return; + } + + observer.OnError(ex); + return; + } + + if (hasNext) + { + observer.OnNext(e.Current); + } + else + { + observer.OnCompleted(); + return; + } + } while (!cancellationToken.IsCancellationRequested); + } + finally + { + if (e != null) + { + await e.DisposeAsync(); + } + } + } + + internal sealed class CancellationTokenDisposable : IDisposable + { + readonly CancellationTokenSource cts = new CancellationTokenSource(); + + public CancellationToken Token => cts.Token; + + public void Dispose() + { + if (!cts.IsCancellationRequested) + { + cts.Cancel(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs index ed452c5..435eb9c 100644 --- a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs +++ b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs @@ -48,7 +48,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, cancellationToken); } @@ -103,7 +102,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, cancellationToken); } @@ -157,7 +155,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, cancellationToken); } @@ -211,7 +208,6 @@ namespace Cysharp.Threading.Tasks.Linq public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - cancellationToken.ThrowIfCancellationRequested(); return new Enumerator(source, cancellationToken); } diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 6754ed8..a337916 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -28,11 +28,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable AsAsyncEnumerable(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Cast(this IUniTaskAsyncEnumerable source) { @@ -551,165 +546,11 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable ToAsyncEnumerable(this IEnumerable source) - { - throw new NotImplementedException(); - } + - public static IUniTaskAsyncEnumerable ToAsyncEnumerable(this IObservable source) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable ToAsyncEnumerable(this Task task) - { - throw new NotImplementedException(); - } + - public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToDictionaryAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static IEnumerable ToEnumerable(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - - public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToListAsync(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAsync(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static UniTask> ToLookupAwaitWithCancellationAsync(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken = default) - { - throw new NotImplementedException(); - } - - public static IObservable ToObservable(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) { diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 6ca3f92..6344532 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -31,15 +31,24 @@ namespace NetCoreSandbox } } - - static async Task Main(string[] args) + static async IAsyncEnumerable FooAsync([EnumeratorCancellation]CancellationToken cancellationToken = default) { - new int[] { }.Aggregate((x, y) => x + y); + yield return 1; + await Task.Delay(10, cancellationToken); + } + static void Main(string[] args) + { + // Create Canceled token. + var cts = new CancellationTokenSource(); + cts.Cancel(); + // OK, don't throw. + var e1 = FooAsync(cts.Token).GetAsyncEnumerator(cts.Token); + Console.WriteLine("OK:FooAsyunc().GetAsyncEnumerator()"); - - await Task.Yield(); + // Ix.Async LINQ Operator throws OperationCanceledException + var e2 = FooAsync(cts.Token).Select(x => x).GetAsyncEnumerator(cts.Token); } diff --git a/src/UniTask.NetCoreTests/Linq/Convert.cs b/src/UniTask.NetCoreTests/Linq/Convert.cs index b4fb59a..0e3d4b9 100644 --- a/src/UniTask.NetCoreTests/Linq/Convert.cs +++ b/src/UniTask.NetCoreTests/Linq/Convert.cs @@ -28,6 +28,21 @@ namespace NetCoreTests.Linq } } + + [Fact] + public async Task ToObservable() + { + { + var xs = await UniTaskAsyncEnumerable.Range(1, 10).ToObservable().ToArray(); + xs.Should().BeEquivalentTo(Enumerable.Range(1, 10)); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, 0).ToObservable().ToArray(); + xs.Should().BeEquivalentTo(Enumerable.Range(1, 0)); + } + } + + [Fact] public async Task ToAsyncEnumerableTask() { @@ -73,6 +88,108 @@ namespace NetCoreTests.Linq } } + [Fact] + public async Task ToDictionary() + { + { + var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x); + var ys = Enumerable.Range(1, 100).ToDictionary(x => x); + + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + { + var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x); + var ys = Enumerable.Range(1, 0).ToDictionary(x => x); + + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + { + var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x, x => x * 2); + var ys = Enumerable.Range(1, 100).ToDictionary(x => x, x => x * 2); + + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + { + var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToDictionaryAsync(x => x, x => x * 2); + var ys = Enumerable.Range(1, 0).ToDictionary(x => x, x => x * 2); + + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + } + + [Fact] + public async Task ToLookup() + { + var arr = new[] { 1, 4, 10, 10, 4, 5, 10, 9 }; + { + var xs = await arr.ToUniTaskAsyncEnumerable().ToLookupAsync(x => x); + var ys = arr.ToLookup(x => x); + + xs.Count.Should().Be(ys.Count); + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + foreach (var key in xs.Select(x => x.Key)) + { + xs[key].Should().BeEquivalentTo(ys[key]); + } + } + { + var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToLookupAsync(x => x); + var ys = Enumerable.Range(1, 0).ToLookup(x => x); + + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + { + var xs = await arr.ToUniTaskAsyncEnumerable().ToLookupAsync(x => x, x => x * 2); + var ys = arr.ToLookup(x => x, x => x * 2); + + xs.Count.Should().Be(ys.Count); + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + foreach (var key in xs.Select(x => x.Key)) + { + xs[key].Should().BeEquivalentTo(ys[key]); + } + } + { + var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().ToLookupAsync(x => x, x => x * 2); + var ys = Enumerable.Range(1, 0).ToLookup(x => x, x => x * 2); + + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + } + + [Fact] + public async Task ToList() + { + { + var xs = await Enumerable.Range(1, 100).ToUniTaskAsyncEnumerable().ToListAsync(); + var ys = Enumerable.Range(1, 100).ToList(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await Enumerable.Empty().ToUniTaskAsyncEnumerable().ToListAsync(); + var ys = Enumerable.Empty().ToList(); + + xs.Should().BeEquivalentTo(ys); + } + } + + [Fact] + public async Task ToHashSet() + { + { + var xs = await new[] { 1, 20, 4, 5, 20, 4, 6 }.ToUniTaskAsyncEnumerable().ToHashSetAsync(); + var ys = new[] { 1, 20, 4, 5, 20, 4, 6 }.ToHashSet(); + + xs.OrderBy(x => x).Should().BeEquivalentTo(ys.OrderBy(x => x)); + } + { + var xs = await Enumerable.Empty().ToUniTaskAsyncEnumerable().ToHashSetAsync(); + var ys = Enumerable.Empty().ToHashSet(); + + xs.Should().BeEquivalentTo(ys); + } + } } From af6dbd8868e2db70b0a1203d8bb8866fda0791e5 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 03:50:29 +0900 Subject: [PATCH 12/31] append prepend concat --- src/UniTask.NetCore/Linq/Append.cs | 775 --------------- src/UniTask.NetCore/Linq/AppendPrepend.cs | 913 +++++++++++++++++ .../Linq/AsyncEnumeratorBase.cs | 4 +- src/UniTask.NetCore/Linq/Concat.cs | 918 +++--------------- src/UniTask.NetCore/Linq/Prepend.cs | 775 --------------- src/UniTask.NetCore/Linq/_FileMaker.cs | 14 +- src/UniTask.NetCoreTests/Linq/Concat.cs | 65 ++ 7 files changed, 1129 insertions(+), 2335 deletions(-) delete mode 100644 src/UniTask.NetCore/Linq/Append.cs create mode 100644 src/UniTask.NetCore/Linq/AppendPrepend.cs delete mode 100644 src/UniTask.NetCore/Linq/Prepend.cs create mode 100644 src/UniTask.NetCoreTests/Linq/Concat.cs diff --git a/src/UniTask.NetCore/Linq/Append.cs b/src/UniTask.NetCore/Linq/Append.cs deleted file mode 100644 index 4d22846..0000000 --- a/src/UniTask.NetCore/Linq/Append.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class Append - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/AppendPrepend.cs b/src/UniTask.NetCore/Linq/AppendPrepend.cs new file mode 100644 index 0000000..8b3a135 --- /dev/null +++ b/src/UniTask.NetCore/Linq/AppendPrepend.cs @@ -0,0 +1,913 @@ +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Append(this IUniTaskAsyncEnumerable source, TSource element) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new AppendPrepend(source, element, true); + } + + public static IUniTaskAsyncEnumerable Prepend(this IUniTaskAsyncEnumerable source, TSource element) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new AppendPrepend(source, element, true); + } + } + + internal sealed class AppendPrepend : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly TSource element; + readonly bool append; // or prepend + + public AppendPrepend(IUniTaskAsyncEnumerable source, TSource element, bool append) + { + this.source = source; + this.element = element; + this.append = append; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, element, append, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + enum State : byte + { + None, + RequirePrepend, + RequireAppend, + Completed + } + + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly TSource element; + CancellationToken cancellationToken; + + State state; + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, TSource element, bool append, CancellationToken cancellationToken) + { + this.source = source; + this.element = element; + this.state = append ? State.RequireAppend : State.RequirePrepend; + this.cancellationToken = cancellationToken; + } + + public TSource Current { get; private set; } + + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (enumerator == null) + { + if (state == State.RequireAppend) + { + Current = element; + state = State.None; + return CompletedTasks.True; + } + + enumerator = source.GetAsyncEnumerator(cancellationToken); + } + + if (state == State.Completed) + { + return CompletedTasks.False; + } + + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + + if (awaiter.IsCompleted) + { + MoveNextCoreDelegate(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + + return new UniTask(this, completionSource.Version); + } + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.awaiter.GetResult()) + { + self.Current = self.enumerator.Current; + } + else + { + if (self.state == State.RequireAppend) + { + self.state = State.Completed; + self.Current = self.element; + } + else + { + self.state = State.Completed; + self.completionSource.TrySetResult(false); + return; + } + } + + self.completionSource.TrySetResult(true); + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index 2818715..3befbef 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -153,6 +153,8 @@ namespace Cysharp.Threading.Tasks.Linq public abstract class AsyncEnumeratorAwaitSelectorBase : MoveNextSource, IUniTaskAsyncEnumerator { static readonly Action moveNextCallbackDelegate = MoveNextCallBack; + static readonly Action setCurrentCallbackDelegate = SetCurrentCallBack; + readonly IUniTaskAsyncEnumerable source; protected CancellationToken cancellationToken; @@ -274,7 +276,7 @@ namespace Cysharp.Threading.Tasks.Linq } else { - resultAwaiter.SourceOnCompleted(SetCurrentCallBack, this); // TODO:cache + resultAwaiter.SourceOnCompleted(setCurrentCallbackDelegate, this); result = default; return false; } diff --git a/src/UniTask.NetCore/Linq/Concat.cs b/src/UniTask.NetCore/Linq/Concat.cs index 327ac6f..6e3dfa4 100644 --- a/src/UniTask.NetCore/Linq/Concat.cs +++ b/src/UniTask.NetCore/Linq/Concat.cs @@ -1,775 +1,151 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Concat + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Concat(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return new Concat(first, second); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Concat : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + + public Concat(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + this.first = first; + this.second = second; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + enum IteratingState + { + IteratingFirst, + IteratingSecond, + Complete + } + + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + CancellationToken cancellationToken; + + IteratingState iteratingState; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, CancellationToken cancellationToken) + { + this.first = first; + this.second = second; + this.cancellationToken = cancellationToken; + this.iteratingState = IteratingState.IteratingFirst; + } + + public TSource Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (iteratingState == IteratingState.Complete) return CompletedTasks.False; + + completionSource.Reset(); + StartIterate(); + return new UniTask(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); + } + } + + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + + if (awaiter.IsCompleted) + { + MoveNextCoreDelegate(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.awaiter.GetResult()) + { + self.Current = self.enumerator.Current; + self.completionSource.TrySetResult(true); + } + else + { + if (self.iteratingState == IteratingState.IteratingFirst) + { + self.RunSecondAfterDisposeAsync().Forget(); + return; + } + + self.iteratingState = IteratingState.Complete; + self.completionSource.TrySetResult(false); + } + } + + async UniTaskVoid RunSecondAfterDisposeAsync() + { + try + { + await enumerator.DisposeAsync(); + enumerator = null; + awaiter = default; + iteratingState = IteratingState.IteratingSecond; + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + + StartIterate(); + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Prepend.cs b/src/UniTask.NetCore/Linq/Prepend.cs deleted file mode 100644 index b5d7d8c..0000000 --- a/src/UniTask.NetCore/Linq/Prepend.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class Prepend - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index a337916..c8f6d3d 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -23,21 +23,12 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Append(this IUniTaskAsyncEnumerable source, TSource element) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Cast(this IUniTaskAsyncEnumerable source) { throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable Concat(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } @@ -333,10 +324,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable Prepend(this IUniTaskAsyncEnumerable source, TSource element) - { - throw new NotImplementedException(); - } + public static IUniTaskAsyncEnumerable Reverse(this IUniTaskAsyncEnumerable source) { diff --git a/src/UniTask.NetCoreTests/Linq/Concat.cs b/src/UniTask.NetCoreTests/Linq/Concat.cs new file mode 100644 index 0000000..e0e390a --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Concat.cs @@ -0,0 +1,65 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Concat + { + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(0, 2)] + [InlineData(0, 10)] + public async Task Append(int start, int count) + { + var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Append(99).ToArrayAsync(); + var ys = Enumerable.Range(start, count).Append(99).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(0, 2)] + [InlineData(0, 10)] + public async Task Prepend(int start, int count) + { + var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Prepend(99).ToArrayAsync(); + var ys = Enumerable.Range(start, count).Prepend(99).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + public static IEnumerable array1 = new object[][] + { + new object[] { (0, 0), (0, 0) }, // empty + empty + new object[] { (0, 1), (0, 0) }, // 1 + empty + new object[] { (0, 0), (0, 1) }, // empty + 1 + new object[] { (0, 5), (0, 0) }, // 5 + empty + new object[] { (0, 0), (0, 5) }, // empty + 5 + new object[] { (0, 5), (0, 5) }, // 5 + 5 + }; + + [Theory] + [MemberData(nameof(array1))] + public async Task ConcatTest((int, int) left, (int, int) right) + { + var l = Enumerable.Range(left.Item1, left.Item2); + var r = Enumerable.Range(right.Item1, right.Item2); + + var xs = await l.ToUniTaskAsyncEnumerable().Concat(r.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = l.Concat(r).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } +} From 93dd82e3d4fa0d90af0fa2057653da28ef6ee447 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 22:44:40 +0900 Subject: [PATCH 13/31] exception testing --- src/UniTask.NetCore/Linq/AppendPrepend.cs | 795 +--------------- .../Linq/AsyncEnumeratorBase.cs | 15 + src/UniTask.NetCore/Linq/Cast.cs | 820 +--------------- src/UniTask.NetCore/Linq/Concat.cs | 35 +- src/UniTask.NetCore/Linq/Create.cs | 775 --------------- src/UniTask.NetCore/Linq/DefaultIfEmpty.cs | 898 +++--------------- src/UniTask.NetCore/Linq/OfType.cs | 828 ++-------------- src/UniTask.NetCore/Linq/Throw.cs | 54 ++ .../Linq/ToUniTaskAsyncEnumerable.cs | 18 +- src/UniTask.NetCore/Linq/Where.cs | 245 ++++- src/UniTask.NetCore/Linq/Zip.cs | 30 +- src/UniTask.NetCore/Linq/_FileMaker.cs | 51 +- src/UniTask.NetCoreSandbox/Program.cs | 26 +- src/UniTask.NetCoreTests/Linq/Concat.cs | 51 + src/UniTask.NetCoreTests/Linq/Filtering.cs | 118 +++ src/UniTask.NetCoreTests/Linq/_Exception.cs | 126 +++ .../Plugins/UniTask/UniTaskScheduler.cs | 4 +- 17 files changed, 926 insertions(+), 3963 deletions(-) delete mode 100644 src/UniTask.NetCore/Linq/Create.cs create mode 100644 src/UniTask.NetCore/Linq/Throw.cs create mode 100644 src/UniTask.NetCoreTests/Linq/Filtering.cs create mode 100644 src/UniTask.NetCoreTests/Linq/_Exception.cs diff --git a/src/UniTask.NetCore/Linq/AppendPrepend.cs b/src/UniTask.NetCore/Linq/AppendPrepend.cs index 8b3a135..960e113 100644 --- a/src/UniTask.NetCore/Linq/AppendPrepend.cs +++ b/src/UniTask.NetCore/Linq/AppendPrepend.cs @@ -110,26 +110,28 @@ namespace Cysharp.Threading.Tasks.Linq { var self = (Enumerator)state; - if (self.awaiter.GetResult()) + if (self.TryGetResult(self.awaiter, out var result)) { - self.Current = self.enumerator.Current; - } - else - { - if (self.state == State.RequireAppend) + if (result) { - self.state = State.Completed; - self.Current = self.element; + self.Current = self.enumerator.Current; + self.completionSource.TrySetResult(true); } else { - self.state = State.Completed; - self.completionSource.TrySetResult(false); - return; + 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); + } } } - - self.completionSource.TrySetResult(true); } public UniTask DisposeAsync() @@ -144,770 +146,3 @@ namespace Cysharp.Threading.Tasks.Linq } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index 3befbef..6813a7d 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -31,6 +31,21 @@ namespace Cysharp.Threading.Tasks.Linq { completionSource.GetResult(token); } + + protected bool TryGetResult(UniTask.Awaiter awaiter, out T result) + { + try + { + result = awaiter.GetResult(); + return true; + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + result = default; + return false; + } + } } diff --git a/src/UniTask.NetCore/Linq/Cast.cs b/src/UniTask.NetCore/Linq/Cast.cs index 413d127..9a27f72 100644 --- a/src/UniTask.NetCore/Linq/Cast.cs +++ b/src/UniTask.NetCore/Linq/Cast.cs @@ -1,775 +1,53 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Cast + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Cast(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new Cast(source); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Cast : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + + public Cast(IUniTaskAsyncEnumerable source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + public Enumerator(IUniTaskAsyncEnumerable 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; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Concat.cs b/src/UniTask.NetCore/Linq/Concat.cs index 6e3dfa4..45aab70 100644 --- a/src/UniTask.NetCore/Linq/Concat.cs +++ b/src/UniTask.NetCore/Linq/Concat.cs @@ -86,7 +86,15 @@ namespace Cysharp.Threading.Tasks.Linq } } - awaiter = enumerator.MoveNextAsync().GetAwaiter(); + try + { + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } if (awaiter.IsCompleted) { @@ -102,21 +110,24 @@ namespace Cysharp.Threading.Tasks.Linq { var self = (Enumerator)state; - if (self.awaiter.GetResult()) + if (self.TryGetResult(self.awaiter, out var result)) { - self.Current = self.enumerator.Current; - self.completionSource.TrySetResult(true); - } - else - { - if (self.iteratingState == IteratingState.IteratingFirst) + if (result) { - self.RunSecondAfterDisposeAsync().Forget(); - return; + 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); + self.iteratingState = IteratingState.Complete; + self.completionSource.TrySetResult(false); + } } } diff --git a/src/UniTask.NetCore/Linq/Create.cs b/src/UniTask.NetCore/Linq/Create.cs deleted file mode 100644 index d853334..0000000 --- a/src/UniTask.NetCore/Linq/Create.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class Create - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs b/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs index 49ca694..756fd5a 100644 --- a/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs +++ b/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs @@ -1,775 +1,135 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class DefaultIfEmpty + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new DefaultIfEmpty(source, default); + } + + public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source, TSource defaultValue) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new DefaultIfEmpty(source, defaultValue); + } } + internal sealed class DefaultIfEmpty : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly TSource defaultValue; + + public DefaultIfEmpty(IUniTaskAsyncEnumerable source, TSource defaultValue) + { + this.source = source; + this.defaultValue = defaultValue; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, defaultValue, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + enum IteratingState : byte + { + Empty, + Iterating, + Completed + } + + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly TSource defaultValue; + CancellationToken cancellationToken; + + IteratingState iteratingState; + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, TSource defaultValue, CancellationToken cancellationToken) + { + this.source = source; + this.defaultValue = defaultValue; + this.cancellationToken = cancellationToken; + + this.iteratingState = IteratingState.Empty; + } + + public TSource Current { get; private set; } + + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (iteratingState == IteratingState.Empty) + { + return CompletedTasks.False; + } + + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + + if (awaiter.IsCompleted) + { + MoveNextCore(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + + return new UniTask(this, completionSource.Version); + } + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + self.iteratingState = IteratingState.Iterating; + self.Current = self.enumerator.Current; + self.completionSource.TrySetResult(true); + } + else + { + if (self.iteratingState == IteratingState.Empty) + { + self.iteratingState = IteratingState.Completed; + + self.Current = self.defaultValue; + self.completionSource.TrySetResult(true); + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/OfType.cs b/src/UniTask.NetCore/Linq/OfType.cs index b49404c..213cc98 100644 --- a/src/UniTask.NetCore/Linq/OfType.cs +++ b/src/UniTask.NetCore/Linq/OfType.cs @@ -1,775 +1,61 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class OfType + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable OfType(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new OfType(source); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class OfType : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + + public OfType(IUniTaskAsyncEnumerable source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + public Enumerator(IUniTaskAsyncEnumerable 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; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Throw.cs b/src/UniTask.NetCore/Linq/Throw.cs new file mode 100644 index 0000000..a939559 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Throw.cs @@ -0,0 +1,54 @@ +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq +{ + public static partial class UniTaskAsyncEnumerable + { + public static IUniTaskAsyncEnumerable Throw(Exception exception) + { + return new Throw(exception); + } + } + + internal class Throw : IUniTaskAsyncEnumerable + { + readonly Exception exception; + + public Throw(Exception exception) + { + this.exception = exception; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(exception, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly Exception exception; + CancellationToken cancellationToken; + + public Enumerator(Exception exception, CancellationToken cancellationToken) + { + this.exception = exception; + this.cancellationToken = cancellationToken; + } + + public TValue Current => default; + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + return UniTask.FromException(exception); + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs index 435eb9c..500ce13 100644 --- a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs +++ b/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs @@ -243,19 +243,21 @@ namespace Cysharp.Threading.Tasks.Linq { get { - if (error != null) - { - ExceptionDispatchInfo.Capture(error).Throw(); - } - if (useCachedCurrent) { return current; } - current = queuedResult.Dequeue(); - useCachedCurrent = true; - return current; + if (queuedResult.Count != 0) + { + current = queuedResult.Dequeue(); + useCachedCurrent = true; + return current; + } + else + { + return default; // undefined. + } } } diff --git a/src/UniTask.NetCore/Linq/Where.cs b/src/UniTask.NetCore/Linq/Where.cs index 6d2a07d..05a1ed7 100644 --- a/src/UniTask.NetCore/Linq/Where.cs +++ b/src/UniTask.NetCore/Linq/Where.cs @@ -1,18 +1,57 @@ -using System; +using Cysharp.Threading.Tasks.Internal; +using System; using System.Threading; namespace Cysharp.Threading.Tasks.Linq { public static partial class UniTaskAsyncEnumerable { - public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) + public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) { - return new Cysharp.Threading.Tasks.Linq.Where(source, predicate); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new Where(source, predicate); } - public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) { - return new Cysharp.Threading.Tasks.Linq.WhereAwait(source, predicate); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new WhereInt(source, predicate); + } + + public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new WhereAwait(source, predicate); + } + + public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new WhereAwaitInt(source, predicate); + } + + public static IUniTaskAsyncEnumerable WhereAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new WhereAwaitCancellation(source, predicate); + } + + public static IUniTaskAsyncEnumerable WhereAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new WhereAwaitIntCancellation(source, predicate); } } @@ -66,6 +105,57 @@ namespace Cysharp.Threading.Tasks.Linq } } + internal sealed class WhereInt : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func predicate; + + public WhereInt(IUniTaskAsyncEnumerable source, Func predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly Func predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (predicate(SourceCurrent, checked(index++))) + { + Current = SourceCurrent; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } + internal sealed class WhereAwait : IUniTaskAsyncEnumerable { readonly IUniTaskAsyncEnumerable source; @@ -113,4 +203,149 @@ namespace Cysharp.Threading.Tasks.Linq } } + internal sealed class WhereAwaitInt : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public WhereAwaitInt(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent, checked(index++)); + } + + protected override bool TrySetCurrentCore(bool awaitResult) + { + if (awaitResult) + { + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } + + + + internal sealed class WhereAwaitCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public WhereAwaitCancellation(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent, cancellationToken); + } + + protected override bool TrySetCurrentCore(bool awaitResult) + { + if (awaitResult) + { + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } + + internal sealed class WhereAwaitIntCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public WhereAwaitIntCancellation(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent, checked(index++), cancellationToken); + } + + protected override bool TrySetCurrentCore(bool awaitResult) + { + if (awaitResult) + { + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } + } \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Zip.cs b/src/UniTask.NetCore/Linq/Zip.cs index 31dd547..e3fdefb 100644 --- a/src/UniTask.NetCore/Linq/Zip.cs +++ b/src/UniTask.NetCore/Linq/Zip.cs @@ -90,22 +90,34 @@ namespace Cysharp.Threading.Tasks.Linq { var self = (Enumerator)state; - if (self.firstAwaiter.GetResult()) + if (self.TryGetResult(self.firstAwaiter, out var result)) { - self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); - if (self.secondAwaiter.IsCompleted) + if (result) { - SecondMoveNextCore(self); + try + { + self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + + if (self.secondAwaiter.IsCompleted) + { + SecondMoveNextCore(self); + } + else + { + self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + } } else { - self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + self.completionSource.TrySetResult(false); } } - else - { - self.completionSource.TrySetResult(false); - } } static void SecondMoveNextCore(object state) diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index c8f6d3d..41494b1 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -24,24 +24,8 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Cast(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - - - public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable DefaultIfEmpty(this IUniTaskAsyncEnumerable source, TSource defaultValue) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) { throw new NotImplementedException(); @@ -259,11 +243,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable OfType(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - public static IOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector) { throw new NotImplementedException(); @@ -550,35 +529,7 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Where(this IUniTaskAsyncEnumerable source, Func predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable WhereAwait(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable WhereAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable WhereAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } + public static IUniTaskAsyncEnumerable> Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) { diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 6344532..ae8d8c7 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -37,24 +37,28 @@ namespace NetCoreSandbox await Task.Delay(10, cancellationToken); } - static void Main(string[] args) + static async Task Main(string[] args) { - // Create Canceled token. - var cts = new CancellationTokenSource(); - cts.Cancel(); - - // OK, don't throw. - var e1 = FooAsync(cts.Token).GetAsyncEnumerator(cts.Token); - Console.WriteLine("OK:FooAsyunc().GetAsyncEnumerator()"); - - // Ix.Async LINQ Operator throws OperationCanceledException - var e2 = FooAsync(cts.Token).Select(x => x).GetAsyncEnumerator(cts.Token); + Console.WriteLine("YEAH"); + try + { + var xs = await UniTaskAsyncEnumerable.Range(1, 10).Concat(UniTaskAsyncEnumerable.Throw(new InvalidOperationException("something"))) + .SumAsync(); + } + catch (Exception ex) + { + Console.WriteLine("EX"); + Console.WriteLine(ex); + } } void Foo() { + + + // AsyncEnumerable.t var sb = new StringBuilder(); diff --git a/src/UniTask.NetCoreTests/Linq/Concat.cs b/src/UniTask.NetCoreTests/Linq/Concat.cs index e0e390a..2d6cdfa 100644 --- a/src/UniTask.NetCoreTests/Linq/Concat.cs +++ b/src/UniTask.NetCoreTests/Linq/Concat.cs @@ -27,6 +27,19 @@ namespace NetCoreTests.Linq xs.Should().BeEquivalentTo(ys); } + [Fact] + public async Task AppendThrow() + { + var xs = UniTaskTestException.ThrowImmediate().Append(99).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + + var ys = UniTaskTestException.ThrowAfter().Append(99).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await ys); + + var zs = UniTaskTestException.ThrowInMoveNext().Append(99).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await zs); + } + [Theory] [InlineData(0, 0)] [InlineData(0, 1)] @@ -40,6 +53,19 @@ namespace NetCoreTests.Linq xs.Should().BeEquivalentTo(ys); } + [Fact] + public async Task PrependThrow() + { + var xs = UniTaskTestException.ThrowImmediate().Prepend(99).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + + var ys = UniTaskTestException.ThrowAfter().Prepend(99).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await ys); + + var zs = UniTaskTestException.ThrowInMoveNext().Prepend(99).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await zs); + } + public static IEnumerable array1 = new object[][] { new object[] { (0, 0), (0, 0) }, // empty + empty @@ -61,5 +87,30 @@ namespace NetCoreTests.Linq var ys = l.Concat(r).ToArray(); xs.Should().BeEquivalentTo(ys); } + + [Fact] + public async Task ConcatThrow() + { + { + var xs = UniTaskTestException.ThrowImmediate().Concat(UniTaskAsyncEnumerable.Range(1, 10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + + var ys = UniTaskTestException.ThrowAfter().Concat(UniTaskAsyncEnumerable.Range(1, 10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await ys); + + var zs = UniTaskTestException.ThrowInMoveNext().Concat(UniTaskAsyncEnumerable.Range(1, 10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await zs); + } + { + var xs = UniTaskAsyncEnumerable.Range(1, 10).Concat(UniTaskTestException.ThrowImmediate()).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + + var ys = UniTaskAsyncEnumerable.Range(1, 10).Concat(UniTaskTestException.ThrowAfter()).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await ys); + + var zs = UniTaskAsyncEnumerable.Range(1, 10).Concat(UniTaskTestException.ThrowInMoveNext()).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await zs); + } + } } } diff --git a/src/UniTask.NetCoreTests/Linq/Filtering.cs b/src/UniTask.NetCoreTests/Linq/Filtering.cs new file mode 100644 index 0000000..c9fdd97 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Filtering.cs @@ -0,0 +1,118 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Filtering + { + [Fact] + public async Task Where() + { + var range = Enumerable.Range(1, 10); + var src = range.ToUniTaskAsyncEnumerable(); + + { + var a = await src.Where(x => x % 2 == 0).ToArrayAsync(); + var expected = range.Where(x => x % 2 == 0).ToArray(); + a.Should().BeEquivalentTo(expected); + } + { + var a = await src.Where((x, i) => (x + i) % 2 == 0).ToArrayAsync(); + var expected = range.Where((x, i) => (x + i) % 2 == 0).ToArray(); + a.Should().BeEquivalentTo(expected); + } + { + var a = await src.WhereAwait(x => UniTask.Run(() => x % 2 == 0)).ToArrayAsync(); + var b = await src.WhereAwait(x => UniTask.FromResult(x % 2 == 0)).ToArrayAsync(); + var expected = range.Where(x => x % 2 == 0).ToArray(); + a.Should().BeEquivalentTo(expected); + b.Should().BeEquivalentTo(expected); + } + { + var a = await src.WhereAwait((x, i) => UniTask.Run(() => (x + i) % 2 == 0)).ToArrayAsync(); + var b = await src.WhereAwait((x, i) => UniTask.FromResult((x + i) % 2 == 0)).ToArrayAsync(); + var expected = range.Where((x, i) => (x + i) % 2 == 0).ToArray(); + a.Should().BeEquivalentTo(expected); + b.Should().BeEquivalentTo(expected); + } + } + + + [Fact] + public async Task WhereException() + { + foreach (var item in UniTaskTestException.Throws()) + { + { + var xs = item.Where(x => x % 2 == 0).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.Where((x, i) => x % 2 == 0).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.WhereAwait(x => UniTask.FromResult(x % 2 == 0)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.WhereAwait((x, i) => UniTask.FromResult(x % 2 == 0)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } + + [Fact] + public async Task OfType() + { + var data = new object[] { 0, null, 10, 30, null, "foo", 99 }; + + var a = await data.ToUniTaskAsyncEnumerable().OfType().ToArrayAsync(); + var b = data.OfType().ToArray(); + + a.Should().BeEquivalentTo(b); + } + + + [Fact] + public async Task OfTypeException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Select(x => (object)x).OfType().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Cast() + { + var data = new object[] { 0, 10, 30, 99 }; + + var a = await data.ToUniTaskAsyncEnumerable().Cast().ToArrayAsync(); + var b = data.Cast().ToArray(); + + a.Should().BeEquivalentTo(b); + } + + + [Fact] + public async Task CastException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Select(x => (object)x).Cast().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } +} diff --git a/src/UniTask.NetCoreTests/Linq/_Exception.cs b/src/UniTask.NetCoreTests/Linq/_Exception.cs new file mode 100644 index 0000000..1e977cc --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/_Exception.cs @@ -0,0 +1,126 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using System; +using System.Collections.Generic; +using System.Runtime.ExceptionServices; +using System.Threading; + +namespace NetCoreTests.Linq +{ + public class UniTaskTestException : Exception + { + public static IUniTaskAsyncEnumerable ThrowImmediate() + { + return UniTaskAsyncEnumerable.Throw(new UniTaskTestException()); + } + public static IUniTaskAsyncEnumerable ThrowAfter() + { + return new ThrowAfter(new UniTaskTestException()); + } + public static IUniTaskAsyncEnumerable ThrowInMoveNext() + { + return new ThrowIn(new UniTaskTestException()); + } + + + public static IEnumerable> Throws() + { + yield return ThrowImmediate(); + yield return ThrowAfter(); + yield return ThrowInMoveNext(); + yield return UniTaskAsyncEnumerable.Range(1, 3).Concat(ThrowImmediate()); + yield return UniTaskAsyncEnumerable.Range(1, 3).Concat(ThrowAfter()); + yield return UniTaskAsyncEnumerable.Range(1, 3).Concat(ThrowInMoveNext()); + } + } + + internal class ThrowIn : IUniTaskAsyncEnumerable + { + readonly Exception exception; + + public ThrowIn(Exception exception) + { + this.exception = exception; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(exception, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly Exception exception; + CancellationToken cancellationToken; + + public Enumerator(Exception exception, CancellationToken cancellationToken) + { + this.exception = exception; + this.cancellationToken = cancellationToken; + } + + public TValue Current => default; + + public UniTask MoveNextAsync() + { + ExceptionDispatchInfo.Capture(exception).Throw(); + return new UniTask(false); + } + + public UniTask DisposeAsync() + { + return default; + } + } + } + + internal class ThrowAfter : IUniTaskAsyncEnumerable + { + readonly Exception exception; + + public ThrowAfter(Exception exception) + { + this.exception = exception; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(exception, cancellationToken); + } + + class Enumerator : IUniTaskAsyncEnumerator + { + readonly Exception exception; + CancellationToken cancellationToken; + + public Enumerator(Exception exception, CancellationToken cancellationToken) + { + this.exception = exception; + this.cancellationToken = cancellationToken; + } + + public TValue Current => default; + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + var tcs = new UniTaskCompletionSource(); + + var awaiter = UniTask.Yield().GetAwaiter(); + awaiter.UnsafeOnCompleted(() => + { + Thread.Sleep(1); + tcs.TrySetException(exception); + }); + + return tcs.Task; + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} diff --git a/src/UniTask/Assets/Plugins/UniTask/UniTaskScheduler.cs b/src/UniTask/Assets/Plugins/UniTask/UniTaskScheduler.cs index d725470..2f91f2a 100644 --- a/src/UniTask/Assets/Plugins/UniTask/UniTaskScheduler.cs +++ b/src/UniTask/Assets/Plugins/UniTask/UniTaskScheduler.cs @@ -70,7 +70,7 @@ namespace Cysharp.Threading.Tasks string msg = null; if (UnobservedExceptionWriteLogType != UnityEngine.LogType.Exception) { - msg = "UnobservedTaskException:" + ex.ToString(); + msg = "UnobservedTaskException: " + ex.ToString(); } switch (UnobservedExceptionWriteLogType) { @@ -93,7 +93,7 @@ namespace Cysharp.Threading.Tasks break; } #else - Console.WriteLine(ex.ToString()); + Console.WriteLine("UnobservedTaskException: " + ex.ToString()); #endif } } From 3f082f1923d9ecd2b28ce3250032b6584c1ca2f3 Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 22:52:12 +0900 Subject: [PATCH 14/31] defaultifempty --- src/UniTask.NetCore/Linq/DefaultIfEmpty.cs | 7 +++++- src/UniTask.NetCoreTests/Linq/Concat.cs | 28 +++++++++++++++++++++ src/UniTask.NetCoreTests/Linq/_Exception.cs | 8 +++--- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs b/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs index 756fd5a..e8d3662 100644 --- a/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs +++ b/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs @@ -73,11 +73,16 @@ namespace Cysharp.Threading.Tasks.Linq cancellationToken.ThrowIfCancellationRequested(); completionSource.Reset(); - if (iteratingState == IteratingState.Empty) + if (iteratingState == IteratingState.Completed) { return CompletedTasks.False; } + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + } + awaiter = enumerator.MoveNextAsync().GetAwaiter(); if (awaiter.IsCompleted) diff --git a/src/UniTask.NetCoreTests/Linq/Concat.cs b/src/UniTask.NetCoreTests/Linq/Concat.cs index 2d6cdfa..5b1a3d2 100644 --- a/src/UniTask.NetCoreTests/Linq/Concat.cs +++ b/src/UniTask.NetCoreTests/Linq/Concat.cs @@ -112,5 +112,33 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await zs); } } + + [Fact] + public async Task DefaultIfEmpty() + { + { + var xs = await Enumerable.Range(1, 0).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync(); + var ys = Enumerable.Range(1, 0).DefaultIfEmpty(99).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await Enumerable.Range(1, 1).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync(); + var ys = Enumerable.Range(1, 1).DefaultIfEmpty(99).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await Enumerable.Range(1, 10).ToUniTaskAsyncEnumerable().DefaultIfEmpty(99).ToArrayAsync(); + var ys = Enumerable.Range(1, 10).DefaultIfEmpty(99).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + // Throw + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.DefaultIfEmpty().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } } } diff --git a/src/UniTask.NetCoreTests/Linq/_Exception.cs b/src/UniTask.NetCoreTests/Linq/_Exception.cs index 1e977cc..e28c513 100644 --- a/src/UniTask.NetCoreTests/Linq/_Exception.cs +++ b/src/UniTask.NetCoreTests/Linq/_Exception.cs @@ -23,14 +23,14 @@ namespace NetCoreTests.Linq } - public static IEnumerable> Throws() + public static IEnumerable> Throws(int count = 3) { yield return ThrowImmediate(); yield return ThrowAfter(); yield return ThrowInMoveNext(); - yield return UniTaskAsyncEnumerable.Range(1, 3).Concat(ThrowImmediate()); - yield return UniTaskAsyncEnumerable.Range(1, 3).Concat(ThrowAfter()); - yield return UniTaskAsyncEnumerable.Range(1, 3).Concat(ThrowInMoveNext()); + yield return UniTaskAsyncEnumerable.Range(1, count).Concat(ThrowImmediate()); + yield return UniTaskAsyncEnumerable.Range(1, count).Concat(ThrowAfter()); + yield return UniTaskAsyncEnumerable.Range(1, count).Concat(ThrowInMoveNext()); } } From 5db5beab29df058a965aaa265deb7f36b0f3e46a Mon Sep 17 00:00:00 2001 From: neuecc Date: Sun, 10 May 2020 23:26:25 +0900 Subject: [PATCH 15/31] Reverse --- src/UniTask.NetCore/Linq/Reverse.cs | 843 ++------------------ src/UniTask.NetCoreSandbox/Program.cs | 13 +- src/UniTask.NetCoreTests/Linq/Projection.cs | 40 + 3 files changed, 114 insertions(+), 782 deletions(-) create mode 100644 src/UniTask.NetCoreTests/Linq/Projection.cs diff --git a/src/UniTask.NetCore/Linq/Reverse.cs b/src/UniTask.NetCore/Linq/Reverse.cs index c59f44b..4a553ca 100644 --- a/src/UniTask.NetCore/Linq/Reverse.cs +++ b/src/UniTask.NetCore/Linq/Reverse.cs @@ -1,775 +1,76 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Reverse + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Reverse(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + return new Reverse(source); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Reverse : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + + public Reverse(IUniTaskAsyncEnumerable source) + { + this.source = source; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + readonly IUniTaskAsyncEnumerable source; + CancellationToken cancellationToken; + + TSource[] array; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + { + this.source = source; + this.cancellationToken = cancellationToken; + } + + public TSource Current { get; private set; } + + // after consumed array, don't use await so allow async(not require UniTaskCompletionSourceCore). + public async UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (array == null) + { + array = await source.ToArrayAsync(cancellationToken); + index = array.Length - 1; + } + + if (index != -1) + { + Current = array[index]; + --index; + return true; + } + else + { + return false; + } + } + + public UniTask DisposeAsync() + { + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index ae8d8c7..843564a 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -39,17 +39,8 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - Console.WriteLine("YEAH"); - try - { - var xs = await UniTaskAsyncEnumerable.Range(1, 10).Concat(UniTaskAsyncEnumerable.Throw(new InvalidOperationException("something"))) - .SumAsync(); - } - catch (Exception ex) - { - Console.WriteLine("EX"); - Console.WriteLine(ex); - } + var foo = Enumerable.Range(1, 10).ToArray().AsEnumerable().GetEnumerator() as IEnumerator; + Console.WriteLine(foo.GetType().FullName); } diff --git a/src/UniTask.NetCoreTests/Linq/Projection.cs b/src/UniTask.NetCoreTests/Linq/Projection.cs new file mode 100644 index 0000000..49f3017 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Projection.cs @@ -0,0 +1,40 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Projection + { + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(0, 2)] + [InlineData(0, 10)] + public async Task Reverse(int start, int count) + { + var xs = await Enumerable.Range(start, count).ToUniTaskAsyncEnumerable().Reverse().ToArrayAsync(); + var ys = Enumerable.Range(start, count).Reverse().ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task ReverseException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Reverse().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } +} From 16c527fa89dca04133158cf2a4ea8615169482c0 Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 00:27:57 +0900 Subject: [PATCH 16/31] try selectmany --- .../Linq/AsyncEnumeratorBase.cs | 15 +- src/UniTask.NetCore/Linq/SelectMany.cs | 1042 +++++------------ src/UniTask.NetCore/Linq/_FileMaker.cs | 5 - 3 files changed, 287 insertions(+), 775 deletions(-) diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index 6813a7d..d9ccd84 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -46,8 +46,21 @@ namespace Cysharp.Threading.Tasks.Linq return false; } } - } + protected bool TryGetResult(UniTask.Awaiter awaiter) + { + try + { + awaiter.GetResult(); + return true; + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return false; + } + } + } public abstract class AsyncEnumeratorBase : MoveNextSource, IUniTaskAsyncEnumerator { diff --git a/src/UniTask.NetCore/Linq/SelectMany.cs b/src/UniTask.NetCore/Linq/SelectMany.cs index 6f5ceee..da8924a 100644 --- a/src/UniTask.NetCore/Linq/SelectMany.cs +++ b/src/UniTask.NetCore/Linq/SelectMany.cs @@ -1,775 +1,279 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class SelectMany + public static partial class UniTaskAsyncEnumerable { + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new SelectMany(source, selector); + } + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) + { + throw new NotImplementedException(); + } } + internal sealed class SelectMany : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> selector; + public SelectMany(IUniTaskAsyncEnumerable source, Func> selector) + { + this.source = source; + this.selector = selector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, selector, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action sourceMoveNextCoreDelegate = SourceMoveNextCore; + static readonly Action selectedSourceMoveNextCoreDelegate = SeletedSourceMoveNextCore; + static readonly Action selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore; + + readonly IUniTaskAsyncEnumerable source; + readonly Func> selector; + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator sourceEnumerator; + IUniTaskAsyncEnumerator selectedEnumerator; + UniTask.Awaiter sourceAwaiter; + UniTask.Awaiter selectedAwaiter; + UniTask.Awaiter selectedDisposeAsyncAwaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + { + this.source = source; + this.selector = selector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask 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(this, completionSource.Version); + } + + void MoveNextSource() + { + try + { + sourceAwaiter = sourceEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + if (sourceAwaiter.IsCompleted) + { + SourceMoveNextCore(this); + } + else + { + sourceAwaiter.SourceOnCompleted(sourceMoveNextCoreDelegate, this); + } + } + + void MoveNextSelected() + { + try + { + selectedAwaiter = selectedEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + if (selectedAwaiter.IsCompleted) + { + SeletedSourceMoveNextCore(this); + } + else + { + selectedAwaiter.SourceOnCompleted(selectedSourceMoveNextCoreDelegate, this); + } + } + + static void SourceMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedAwaiter, out var result)) + { + if (result) + { + try + { + var current = self.sourceEnumerator.Current; + self.selectedEnumerator = self.selector(current).GetAsyncEnumerator(self.cancellationToken); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + + self.MoveNextSelected(); // iterated selected source. + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void SeletedSourceMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedAwaiter, out var result)) + { + if (result) + { + try + { + self.Current = self.selectedEnumerator.Current; + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + + self.completionSource.TrySetResult(true); + } + else + { + // dispose selected source and try iterate source. + try + { + self.selectedDisposeAsyncAwaiter = self.selectedEnumerator.DisposeAsync().GetAwaiter(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + if (self.selectedDisposeAsyncAwaiter.IsCompleted) + { + SelectedEnumeratorDisposeAsyncCore(self); + } + else + { + self.selectedDisposeAsyncAwaiter.SourceOnCompleted(selectedEnumeratorDisposeAsyncCoreDelegate, self); + } + } + } + } + + static void SelectedEnumeratorDisposeAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedDisposeAsyncAwaiter)) + { + self.selectedEnumerator = null; + self.selectedAwaiter = default; + + self.MoveNextSource(); // iterate next source + } + } + + public async UniTask DisposeAsync() + { + if (selectedEnumerator != null) + { + await selectedEnumerator.DisposeAsync(); + } + if (sourceEnumerator != null) + { + await sourceEnumerator.DisposeAsync(); + } + } + } + } } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 41494b1..14d51ad 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -305,11 +305,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Reverse(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) From 4d13523df76e664afe29eeda86f54d5a929b86bf Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 02:01:49 +0900 Subject: [PATCH 17/31] SelectMany --- src/UniTask.NetCore/Linq/SelectMany.cs | 659 +++++++++++++++++++- src/UniTask.NetCore/Linq/_FileMaker.cs | 59 -- src/UniTask.NetCoreTests/Linq/Projection.cs | 119 ++++ 3 files changed, 752 insertions(+), 85 deletions(-) diff --git a/src/UniTask.NetCore/Linq/SelectMany.cs b/src/UniTask.NetCore/Linq/SelectMany.cs index da8924a..d286441 100644 --- a/src/UniTask.NetCore/Linq/SelectMany.cs +++ b/src/UniTask.NetCore/Linq/SelectMany.cs @@ -12,79 +12,124 @@ namespace Cysharp.Threading.Tasks.Linq Error.ThrowArgumentNullException(source, nameof(source)); Error.ThrowArgumentNullException(selector, nameof(selector)); - return new SelectMany(source, selector); + return new SelectMany(source, selector, (x, y) => y); } public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new SelectMany(source, selector, (x, y) => y); } public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector)); + + return new SelectMany(source, collectionSelector, resultSelector); } public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector)); + + return new SelectMany(source, collectionSelector, resultSelector); } public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new SelectManyAwait(source, selector, (x, y) => UniTask.FromResult(y)); } public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new SelectManyAwait(source, selector, (x, y) => UniTask.FromResult(y)); } public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector)); + + return new SelectManyAwait(source, collectionSelector, resultSelector); } public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector)); + + return new SelectManyAwait(source, collectionSelector, resultSelector); } public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new SelectManyAwaitWithCancellation(source, selector, (x, y, c) => UniTask.FromResult(y)); } public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new SelectManyAwaitWithCancellation(source, selector, (x, y, c) => UniTask.FromResult(y)); } public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector)); + + return new SelectManyAwaitWithCancellation(source, collectionSelector, resultSelector); } public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(collectionSelector, nameof(collectionSelector)); + + return new SelectManyAwaitWithCancellation(source, collectionSelector, resultSelector); } } - internal sealed class SelectMany : IUniTaskAsyncEnumerable + internal sealed class SelectMany : IUniTaskAsyncEnumerable { readonly IUniTaskAsyncEnumerable source; - readonly Func> selector; + readonly Func> selector1; + readonly Func> selector2; + readonly Func resultSelector; - public SelectMany(IUniTaskAsyncEnumerable source, Func> selector) + public SelectMany(IUniTaskAsyncEnumerable source, Func> selector, Func resultSelector) { this.source = source; - this.selector = selector; + this.selector1 = selector; + this.selector2 = null; + this.resultSelector = resultSelector; + } + + public SelectMany(IUniTaskAsyncEnumerable source, Func> selector, Func resultSelector) + { + this.source = source; + this.selector1 = null; + this.selector2 = selector; + this.resultSelector = resultSelector; } public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { - return new Enumerator(source, selector, cancellationToken); + return new Enumerator(source, selector1, selector2, resultSelector, cancellationToken); } sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator @@ -94,19 +139,26 @@ namespace Cysharp.Threading.Tasks.Linq static readonly Action selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore; readonly IUniTaskAsyncEnumerable source; - readonly Func> selector; + + readonly Func> selector1; + readonly Func> selector2; + readonly Func resultSelector; CancellationToken cancellationToken; + TSource sourceCurrent; + int sourceIndex; IUniTaskAsyncEnumerator sourceEnumerator; - IUniTaskAsyncEnumerator selectedEnumerator; + IUniTaskAsyncEnumerator selectedEnumerator; UniTask.Awaiter sourceAwaiter; UniTask.Awaiter selectedAwaiter; UniTask.Awaiter selectedDisposeAsyncAwaiter; - public Enumerator(IUniTaskAsyncEnumerable source, Func> selector, CancellationToken cancellationToken) + public Enumerator(IUniTaskAsyncEnumerable source, Func> selector1, Func> selector2, Func resultSelector, CancellationToken cancellationToken) { this.source = source; - this.selector = selector; + this.selector1 = selector1; + this.selector2 = selector2; + this.resultSelector = resultSelector; this.cancellationToken = cancellationToken; } @@ -182,14 +234,21 @@ namespace Cysharp.Threading.Tasks.Linq { var self = (Enumerator)state; - if (self.TryGetResult(self.selectedAwaiter, out var result)) + if (self.TryGetResult(self.sourceAwaiter, out var result)) { if (result) { try { - var current = self.sourceEnumerator.Current; - self.selectedEnumerator = self.selector(current).GetAsyncEnumerator(self.cancellationToken); + 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) { @@ -216,7 +275,7 @@ namespace Cysharp.Threading.Tasks.Linq { try { - self.Current = self.selectedEnumerator.Current; + self.Current = self.resultSelector(self.sourceCurrent, self.selectedEnumerator.Current); } catch (Exception ex) { @@ -276,4 +335,552 @@ namespace Cysharp.Threading.Tasks.Linq } } } -} + + internal sealed class SelectManyAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func>> selector1; + readonly Func>> selector2; + readonly Func> resultSelector; + + public SelectManyAwait(IUniTaskAsyncEnumerable source, Func>> selector, Func> resultSelector) + { + this.source = source; + this.selector1 = selector; + this.selector2 = null; + this.resultSelector = resultSelector; + } + + public SelectManyAwait(IUniTaskAsyncEnumerable source, Func>> selector, Func> resultSelector) + { + this.source = source; + this.selector1 = null; + this.selector2 = selector; + this.resultSelector = resultSelector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, selector1, selector2, resultSelector, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action sourceMoveNextCoreDelegate = SourceMoveNextCore; + static readonly Action selectedSourceMoveNextCoreDelegate = SeletedSourceMoveNextCore; + static readonly Action selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore; + static readonly Action selectorAwaitCoreDelegate = SelectorAwaitCore; + static readonly Action resultSelectorAwaitCoreDelegate = ResultSelectorAwaitCore; + + readonly IUniTaskAsyncEnumerable source; + + readonly Func>> selector1; + readonly Func>> selector2; + readonly Func> resultSelector; + CancellationToken cancellationToken; + + TSource sourceCurrent; + int sourceIndex; + IUniTaskAsyncEnumerator sourceEnumerator; + IUniTaskAsyncEnumerator selectedEnumerator; + UniTask.Awaiter sourceAwaiter; + UniTask.Awaiter selectedAwaiter; + UniTask.Awaiter selectedDisposeAsyncAwaiter; + + // await additional + UniTask>.Awaiter collectionSelectorAwaiter; + UniTask.Awaiter resultSelectorAwaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, Func>> selector1, Func>> selector2, Func> resultSelector, CancellationToken cancellationToken) + { + this.source = source; + this.selector1 = selector1; + this.selector2 = selector2; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask 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(this, completionSource.Version); + } + + void MoveNextSource() + { + try + { + sourceAwaiter = sourceEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + if (sourceAwaiter.IsCompleted) + { + SourceMoveNextCore(this); + } + else + { + sourceAwaiter.SourceOnCompleted(sourceMoveNextCoreDelegate, this); + } + } + + void MoveNextSelected() + { + try + { + selectedAwaiter = selectedEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + if (selectedAwaiter.IsCompleted) + { + SeletedSourceMoveNextCore(this); + } + else + { + selectedAwaiter.SourceOnCompleted(selectedSourceMoveNextCoreDelegate, this); + } + } + + static void SourceMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.sourceAwaiter, out var result)) + { + if (result) + { + try + { + self.sourceCurrent = self.sourceEnumerator.Current; + + if (self.selector1 != null) + { + self.collectionSelectorAwaiter = self.selector1(self.sourceCurrent).GetAwaiter(); + } + else + { + self.collectionSelectorAwaiter = self.selector2(self.sourceCurrent, checked(self.sourceIndex++)).GetAwaiter(); + } + + if (self.collectionSelectorAwaiter.IsCompleted) + { + SelectorAwaitCore(self); + } + else + { + self.collectionSelectorAwaiter.SourceOnCompleted(selectorAwaitCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void SeletedSourceMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedAwaiter, out var result)) + { + if (result) + { + try + { + self.resultSelectorAwaiter = self.resultSelector(self.sourceCurrent, self.selectedEnumerator.Current).GetAwaiter(); + if (self.resultSelectorAwaiter.IsCompleted) + { + ResultSelectorAwaitCore(self); + } + else + { + self.resultSelectorAwaiter.SourceOnCompleted(resultSelectorAwaitCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + } + else + { + // dispose selected source and try iterate source. + try + { + self.selectedDisposeAsyncAwaiter = self.selectedEnumerator.DisposeAsync().GetAwaiter(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + if (self.selectedDisposeAsyncAwaiter.IsCompleted) + { + SelectedEnumeratorDisposeAsyncCore(self); + } + else + { + self.selectedDisposeAsyncAwaiter.SourceOnCompleted(selectedEnumeratorDisposeAsyncCoreDelegate, self); + } + } + } + } + + static void SelectedEnumeratorDisposeAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedDisposeAsyncAwaiter)) + { + self.selectedEnumerator = null; + self.selectedAwaiter = default; + + self.MoveNextSource(); // iterate next source + } + } + + static void SelectorAwaitCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.collectionSelectorAwaiter, out var result)) + { + self.selectedEnumerator = result.GetAsyncEnumerator(self.cancellationToken); + self.MoveNextSelected(); // iterated selected source. + } + } + + static void ResultSelectorAwaitCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultSelectorAwaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public async UniTask DisposeAsync() + { + if (selectedEnumerator != null) + { + await selectedEnumerator.DisposeAsync(); + } + if (sourceEnumerator != null) + { + await sourceEnumerator.DisposeAsync(); + } + } + } + } + + internal sealed class SelectManyAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func>> selector1; + readonly Func>> selector2; + readonly Func> resultSelector; + + public SelectManyAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func>> selector, Func> resultSelector) + { + this.source = source; + this.selector1 = selector; + this.selector2 = null; + this.resultSelector = resultSelector; + } + + public SelectManyAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func>> selector, Func> resultSelector) + { + this.source = source; + this.selector1 = null; + this.selector2 = selector; + this.resultSelector = resultSelector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, selector1, selector2, resultSelector, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action sourceMoveNextCoreDelegate = SourceMoveNextCore; + static readonly Action selectedSourceMoveNextCoreDelegate = SeletedSourceMoveNextCore; + static readonly Action selectedEnumeratorDisposeAsyncCoreDelegate = SelectedEnumeratorDisposeAsyncCore; + static readonly Action selectorAwaitCoreDelegate = SelectorAwaitCore; + static readonly Action resultSelectorAwaitCoreDelegate = ResultSelectorAwaitCore; + + readonly IUniTaskAsyncEnumerable source; + + readonly Func>> selector1; + readonly Func>> selector2; + readonly Func> resultSelector; + CancellationToken cancellationToken; + + TSource sourceCurrent; + int sourceIndex; + IUniTaskAsyncEnumerator sourceEnumerator; + IUniTaskAsyncEnumerator selectedEnumerator; + UniTask.Awaiter sourceAwaiter; + UniTask.Awaiter selectedAwaiter; + UniTask.Awaiter selectedDisposeAsyncAwaiter; + + // await additional + UniTask>.Awaiter collectionSelectorAwaiter; + UniTask.Awaiter resultSelectorAwaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, Func>> selector1, Func>> selector2, Func> resultSelector, CancellationToken cancellationToken) + { + this.source = source; + this.selector1 = selector1; + this.selector2 = selector2; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask 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(this, completionSource.Version); + } + + void MoveNextSource() + { + try + { + sourceAwaiter = sourceEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + if (sourceAwaiter.IsCompleted) + { + SourceMoveNextCore(this); + } + else + { + sourceAwaiter.SourceOnCompleted(sourceMoveNextCoreDelegate, this); + } + } + + void MoveNextSelected() + { + try + { + selectedAwaiter = selectedEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + if (selectedAwaiter.IsCompleted) + { + SeletedSourceMoveNextCore(this); + } + else + { + selectedAwaiter.SourceOnCompleted(selectedSourceMoveNextCoreDelegate, this); + } + } + + static void SourceMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.sourceAwaiter, out var result)) + { + if (result) + { + try + { + self.sourceCurrent = self.sourceEnumerator.Current; + + if (self.selector1 != null) + { + self.collectionSelectorAwaiter = self.selector1(self.sourceCurrent, self.cancellationToken).GetAwaiter(); + } + else + { + self.collectionSelectorAwaiter = self.selector2(self.sourceCurrent, checked(self.sourceIndex++), self.cancellationToken).GetAwaiter(); + } + + if (self.collectionSelectorAwaiter.IsCompleted) + { + SelectorAwaitCore(self); + } + else + { + self.collectionSelectorAwaiter.SourceOnCompleted(selectorAwaitCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void SeletedSourceMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedAwaiter, out var result)) + { + if (result) + { + try + { + self.resultSelectorAwaiter = self.resultSelector(self.sourceCurrent, self.selectedEnumerator.Current, self.cancellationToken).GetAwaiter(); + if (self.resultSelectorAwaiter.IsCompleted) + { + ResultSelectorAwaitCore(self); + } + else + { + self.resultSelectorAwaiter.SourceOnCompleted(resultSelectorAwaitCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + } + else + { + // dispose selected source and try iterate source. + try + { + self.selectedDisposeAsyncAwaiter = self.selectedEnumerator.DisposeAsync().GetAwaiter(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + if (self.selectedDisposeAsyncAwaiter.IsCompleted) + { + SelectedEnumeratorDisposeAsyncCore(self); + } + else + { + self.selectedDisposeAsyncAwaiter.SourceOnCompleted(selectedEnumeratorDisposeAsyncCoreDelegate, self); + } + } + } + } + + static void SelectedEnumeratorDisposeAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.selectedDisposeAsyncAwaiter)) + { + self.selectedEnumerator = null; + self.selectedAwaiter = default; + + self.MoveNextSource(); // iterate next source + } + } + + static void SelectorAwaitCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.collectionSelectorAwaiter, out var result)) + { + self.selectedEnumerator = result.GetAsyncEnumerator(self.cancellationToken); + self.MoveNextSelected(); // iterated selected source. + } + } + + static void ResultSelectorAwaitCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultSelectorAwaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public async UniTask DisposeAsync() + { + if (selectedEnumerator != null) + { + await selectedEnumerator.DisposeAsync(); + } + if (sourceEnumerator != null) + { + await sourceEnumerator.DisposeAsync(); + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 14d51ad..e04d089 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -307,65 +307,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectMany(this IUniTaskAsyncEnumerable source, Func> collectionSelector, Func resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwait(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SelectManyAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func>> collectionSelector, Func> resultSelector) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable Skip(this IUniTaskAsyncEnumerable source, Int32 count) diff --git a/src/UniTask.NetCoreTests/Linq/Projection.cs b/src/UniTask.NetCoreTests/Linq/Projection.cs index 49f3017..2b411b2 100644 --- a/src/UniTask.NetCoreTests/Linq/Projection.cs +++ b/src/UniTask.NetCoreTests/Linq/Projection.cs @@ -36,5 +36,124 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await xs); } } + + [Theory] + [InlineData(0, 9)] // empty + exists + [InlineData(9, 0)] // exists + empty + [InlineData(9, 9)] // exists + exists + public async Task SelectMany(int leftCount, int rightCount) + { + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => x * y).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + + // await + + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + + // with cancel + + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + + [Fact] + public async Task SelectManyException() + { + // error + exists + // exists + error + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SelectMany(x => UniTaskAsyncEnumerable.Range(0, 1)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Range(0, 1).SelectMany(x => item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + + // await + + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(0, 1))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Range(0, 1).SelectManyAwait(x => UniTask.Run(() => item)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + + // with c + + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(0, 1))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Range(0, 1).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => item)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + } } From c0da316cb441bd404f6e4d1a085ce7954641f67e Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 02:29:23 +0900 Subject: [PATCH 18/31] zip --- src/UniTask.NetCore/Linq/Zip.cs | 321 ++++++++++++++++---- src/UniTask.NetCoreTests/Linq/Projection.cs | 165 ++++++++-- 2 files changed, 409 insertions(+), 77 deletions(-) diff --git a/src/UniTask.NetCore/Linq/Zip.cs b/src/UniTask.NetCore/Linq/Zip.cs index e3fdefb..d646d78 100644 --- a/src/UniTask.NetCore/Linq/Zip.cs +++ b/src/UniTask.NetCore/Linq/Zip.cs @@ -1,4 +1,5 @@ -using System; +using Cysharp.Threading.Tasks.Internal; +using System; using System.Threading; namespace Cysharp.Threading.Tasks.Linq @@ -8,12 +9,37 @@ namespace Cysharp.Threading.Tasks.Linq public static IUniTaskAsyncEnumerable<(TFirst First, TSecond Second)> Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + return Zip(first, second, (x, y) => (x, y)); } public static IUniTaskAsyncEnumerable Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func resultSelector) { - return new Cysharp.Threading.Tasks.Linq.Zip(first, second, resultSelector); + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); + + return new Zip(first, second, resultSelector); + } + + public static IUniTaskAsyncEnumerable ZipAwait(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> selector) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new ZipAwait(first, second, selector); + } + + public static IUniTaskAsyncEnumerable ZipAwaitWithCancellation(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> selector) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(selector, nameof(selector)); + + return new ZipAwaitWithCancellation(first, second, selector); } } @@ -124,30 +150,33 @@ namespace Cysharp.Threading.Tasks.Linq { var self = (Enumerator)state; - if (self.secondAwaiter.GetResult()) + if (self.TryGetResult(self.secondAwaiter, out var result)) { - try + if (result) { - self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current); - } - catch (Exception ex) - { - self.completionSource.TrySetException(ex); - } + try + { + self.Current = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } - if (self.cancellationToken.IsCancellationRequested) - { - self.completionSource.TrySetCanceled(self.cancellationToken); + if (self.cancellationToken.IsCancellationRequested) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + else + { + self.completionSource.TrySetResult(true); + } } else { - self.completionSource.TrySetResult(true); + self.completionSource.TrySetResult(false); } } - else - { - self.completionSource.TrySetResult(false); - } } public async UniTask DisposeAsync() @@ -186,7 +215,7 @@ namespace Cysharp.Threading.Tasks.Linq { static readonly Action firstMoveNextCoreDelegate = FirstMoveNextCore; static readonly Action secondMoveNextCoreDelegate = SecondMoveNextCore; - static readonly Action unwrapResultTaskDelegate = UnwrapResultTask; + static readonly Action resultAwaitCoreDelegate = ResultAwaitCore; readonly IUniTaskAsyncEnumerable first; readonly IUniTaskAsyncEnumerable second; @@ -239,67 +268,84 @@ namespace Cysharp.Threading.Tasks.Linq { var self = (Enumerator)state; - if (self.firstAwaiter.GetResult()) + if (self.TryGetResult(self.firstAwaiter, out var result)) { - self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); - if (self.secondAwaiter.IsCompleted) + if (result) { - SecondMoveNextCore(self); + try + { + self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + + if (self.secondAwaiter.IsCompleted) + { + SecondMoveNextCore(self); + } + else + { + self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + } } else { - self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + self.completionSource.TrySetResult(false); } } - else - { - self.completionSource.TrySetResult(false); - } } static void SecondMoveNextCore(object state) { var self = (Enumerator)state; - if (self.secondAwaiter.GetResult()) + if (self.TryGetResult(self.secondAwaiter, out var result)) { - var task = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current); - self.resultAwaiter = task.GetAwaiter(); - if (self.resultAwaiter.IsCompleted) + if (result) { - UnwrapResultTask(self); + try + { + self.resultAwaiter = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current).GetAwaiter(); + if (self.resultAwaiter.IsCompleted) + { + ResultAwaitCore(self); + } + else + { + self.resultAwaiter.SourceOnCompleted(resultAwaitCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } } else { - self.resultAwaiter.SourceOnCompleted(unwrapResultTaskDelegate, self); + self.completionSource.TrySetResult(false); } } - else - { - self.completionSource.TrySetResult(false); - } } - static void UnwrapResultTask(object state) + static void ResultAwaitCore(object state) { var self = (Enumerator)state; - try + if (self.TryGetResult(self.resultAwaiter, out var result)) { - self.Current = self.resultAwaiter.GetResult(); - } - catch (Exception ex) - { - self.completionSource.TrySetException(ex); - } + self.Current = result; - if (self.cancellationToken.IsCancellationRequested) - { - self.completionSource.TrySetCanceled(self.cancellationToken); - } - else - { - self.completionSource.TrySetResult(true); + if (self.cancellationToken.IsCancellationRequested) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + else + { + self.completionSource.TrySetResult(true); + } } } @@ -317,4 +363,173 @@ namespace Cysharp.Threading.Tasks.Linq } } + internal sealed class ZipAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly Func> resultSelector; + + public ZipAwaitWithCancellation(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> resultSelector) + { + this.first = first; + this.second = second; + this.resultSelector = resultSelector; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, resultSelector, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action firstMoveNextCoreDelegate = FirstMoveNextCore; + static readonly Action secondMoveNextCoreDelegate = SecondMoveNextCore; + static readonly Action resultAwaitCoreDelegate = ResultAwaitCore; + + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly Func> resultSelector; + + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator firstEnumerator; + IUniTaskAsyncEnumerator secondEnumerator; + + UniTask.Awaiter firstAwaiter; + UniTask.Awaiter secondAwaiter; + UniTask.Awaiter resultAwaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> resultSelector, CancellationToken cancellationToken) + { + this.first = first; + this.second = second; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + completionSource.Reset(); + + if (firstEnumerator == null) + { + firstEnumerator = first.GetAsyncEnumerator(cancellationToken); + secondEnumerator = second.GetAsyncEnumerator(cancellationToken); + } + + firstAwaiter = firstEnumerator.MoveNextAsync().GetAwaiter(); + + if (firstAwaiter.IsCompleted) + { + FirstMoveNextCore(this); + } + else + { + firstAwaiter.SourceOnCompleted(firstMoveNextCoreDelegate, this); + } + + return new UniTask(this, completionSource.Version); + } + + static void FirstMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.firstAwaiter, out var result)) + { + if (result) + { + try + { + self.secondAwaiter = self.secondEnumerator.MoveNextAsync().GetAwaiter(); + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + return; + } + + if (self.secondAwaiter.IsCompleted) + { + SecondMoveNextCore(self); + } + else + { + self.secondAwaiter.SourceOnCompleted(secondMoveNextCoreDelegate, self); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void SecondMoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.secondAwaiter, out var result)) + { + if (result) + { + try + { + self.resultAwaiter = self.resultSelector(self.firstEnumerator.Current, self.secondEnumerator.Current, self.cancellationToken).GetAwaiter(); + if (self.resultAwaiter.IsCompleted) + { + ResultAwaitCore(self); + } + else + { + self.resultAwaiter.SourceOnCompleted(resultAwaitCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void ResultAwaitCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultAwaiter, out var result)) + { + self.Current = result; + + if (self.cancellationToken.IsCancellationRequested) + { + self.completionSource.TrySetCanceled(self.cancellationToken); + } + else + { + self.completionSource.TrySetResult(true); + } + } + } + + public async UniTask DisposeAsync() + { + if (firstEnumerator != null) + { + await firstEnumerator.DisposeAsync(); + } + if (secondEnumerator != null) + { + await secondEnumerator.DisposeAsync(); + } + } + } + } } \ No newline at end of file diff --git a/src/UniTask.NetCoreTests/Linq/Projection.cs b/src/UniTask.NetCoreTests/Linq/Projection.cs index 2b411b2..2ec717a 100644 --- a/src/UniTask.NetCoreTests/Linq/Projection.cs +++ b/src/UniTask.NetCoreTests/Linq/Projection.cs @@ -37,6 +37,58 @@ namespace NetCoreTests.Linq } } + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(9)] + public async Task Select(int count) + { + { + var xs = await UniTaskAsyncEnumerable.Range(1, count).Select(x => x * x).ToArrayAsync(); + var ys = Enumerable.Range(1, count).Select(x => x * x).ToArray(); + xs.Should().BeEquivalentTo(ys); + + var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x) => UniTask.Run(() => x * x)).ToArrayAsync(); + zs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, count).Select((x, i) => x * x * i).ToArrayAsync(); + var ys = Enumerable.Range(1, count).Select((x, i) => x * x * i).ToArray(); + xs.Should().BeEquivalentTo(ys); + + var zs = await UniTaskAsyncEnumerable.Range(1, count).SelectAwait((x, i) => UniTask.Run(() => x * x * i)).ToArrayAsync(); + zs.Should().BeEquivalentTo(ys); + } + } + + + [Fact] + public async Task SelectException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Select(x => UniTaskAsyncEnumerable.Range(0, 1)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + + // await + + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SelectAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(0, 1))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + + // cancel + + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SelectAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(0, 1))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Theory] [InlineData(0, 9)] // empty + exists [InlineData(9, 0)] // exists + empty @@ -44,69 +96,69 @@ namespace NetCoreTests.Linq public async Task SelectMany(int leftCount, int rightCount) { { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount)).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => x * y).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany(x => UniTaskAsyncEnumerable.Range(99, rightCount * x), (x, y) => x * y).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectMany((i, x) => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray(); xs.Should().BeEquivalentTo(ys); } // await { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount))).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount))).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait(x => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwait((i, x) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray(); xs.Should().BeEquivalentTo(ys); } // with cancel { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount))).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount)).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x)).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount))).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount)).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x)).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount), (x, y) => x * y).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany(x => Enumerable.Range(99, rightCount * x), (x, y) => x * y).ToArray(); xs.Should().BeEquivalentTo(ys); } { - var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync(); - var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount), (x, y) => x * y).ToArray(); + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).SelectManyAwaitWithCancellation((i, x, _) => UniTask.Run(() => UniTaskAsyncEnumerable.Range(99 * i, rightCount * x)), (x, y, _) => UniTask.Run(() => x * y)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).SelectMany((i, x) => Enumerable.Range(99 * i, rightCount * x), (x, y) => x * y).ToArray(); xs.Should().BeEquivalentTo(ys); } } @@ -155,5 +207,70 @@ namespace NetCoreTests.Linq } + + [Theory] + [InlineData(0, 9)] // empty + exists + [InlineData(9, 0)] // exists + empty + [InlineData(9, 9)] // same + [InlineData(9, 4)] // leftlong + [InlineData(4, 9)] // rightlong + public async Task Zip(int leftCount, int rightCount) + { + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).Zip(UniTaskAsyncEnumerable.Range(99, rightCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwait(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, leftCount).ZipAwaitWithCancellation(UniTaskAsyncEnumerable.Range(99, rightCount), (x, y, _) => UniTask.Run(() => (x, y))).ToArrayAsync(); + var ys = Enumerable.Range(1, leftCount).Zip(Enumerable.Range(99, rightCount)).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + [Fact] + public async Task ZipException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Zip(UniTaskAsyncEnumerable.Range(1, 10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Range(1, 10).Zip(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + + // a + + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.ZipAwait(UniTaskAsyncEnumerable.Range(1, 10), (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Range(1, 10).ZipAwait(item, (x, y) => UniTask.Run(() => (x, y))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + + // c + + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.ZipAwaitWithCancellation(UniTaskAsyncEnumerable.Range(1, 10), (x, y, c) => UniTask.Run(() => (x, y))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Range(1, 10).ZipAwaitWithCancellation(item, (x, y, c) => UniTask.Run(() => (x, y))).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } } } From 1316328766cefff45a71e48694fec32da24c2ee8 Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 12:02:02 +0900 Subject: [PATCH 19/31] Skip, Take, TakeWhile, SkipWhile --- .../Linq/AsyncEnumeratorBase.cs | 22 +- src/UniTask.NetCore/Linq/Do.cs | 255 ++++ src/UniTask.NetCore/Linq/Select.cs | 12 +- src/UniTask.NetCore/Linq/Skip.cs | 836 +----------- src/UniTask.NetCore/Linq/SkipWhile.cs | 1146 ++++++----------- src/UniTask.NetCore/Linq/Take.cs | 836 +----------- src/UniTask.NetCore/Linq/TakeWhile.cs | 1109 +++++----------- src/UniTask.NetCore/Linq/Where.cs | 12 +- src/UniTask.NetCore/Linq/_FileMaker.cs | 91 +- src/UniTask.NetCoreSandbox/Program.cs | 18 +- src/UniTask.NetCoreTests/Linq/Paging.cs | 235 ++++ 11 files changed, 1383 insertions(+), 3189 deletions(-) create mode 100644 src/UniTask.NetCore/Linq/Do.cs create mode 100644 src/UniTask.NetCoreTests/Linq/Paging.cs diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index d9ccd84..d5e5b4f 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -201,7 +201,7 @@ namespace Cysharp.Threading.Tasks.Linq // abstract protected abstract UniTask TransformAsync(TSource sourceCurrent); - protected abstract bool TrySetCurrentCore(TAwait awaitResult); + protected abstract bool TrySetCurrentCore(TAwait awaitResult, out bool terminateIteration); // Util protected TSource SourceCurrent => enumerator.Current; @@ -282,7 +282,13 @@ namespace Cysharp.Threading.Tasks.Linq var task = TransformAsync(enumerator.Current); if (UnwarapTask(task, out var taskResult)) { - return ActionCompleted(TrySetCurrentCore(taskResult), out result); + var currentResult = TrySetCurrentCore(taskResult, out var terminateIteration); + if (terminateIteration) + { + return IterateFinished(out result); + } + + return ActionCompleted(currentResult, out result); } else { @@ -345,10 +351,11 @@ namespace Cysharp.Threading.Tasks.Linq var self = (AsyncEnumeratorAwaitSelectorBase)state; bool doneSetCurrent; + bool terminateIteration; try { var result = self.resultAwaiter.GetResult(); - doneSetCurrent = self.TrySetCurrentCore(result); + doneSetCurrent = self.TrySetCurrentCore(result, out terminateIteration); } catch (Exception ex) { @@ -368,7 +375,14 @@ namespace Cysharp.Threading.Tasks.Linq } else { - self.SourceMoveNext(); + if (terminateIteration) + { + self.completionSource.TrySetResult(false); + } + else + { + self.SourceMoveNext(); + } } } } diff --git a/src/UniTask.NetCore/Linq/Do.cs b/src/UniTask.NetCore/Linq/Do.cs new file mode 100644 index 0000000..a5565fb --- /dev/null +++ b/src/UniTask.NetCore/Linq/Do.cs @@ -0,0 +1,255 @@ +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 Do(this IUniTaskAsyncEnumerable source, Action onNext) + { + Error.ThrowArgumentNullException(source, nameof(source)); + return source.Do(onNext, null, null); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Action onNext, Action onError) + { + Error.ThrowArgumentNullException(source, nameof(source)); + return source.Do(onNext, onError, null); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Action onNext, Action onCompleted) + { + Error.ThrowArgumentNullException(source, nameof(source)); + return source.Do(onNext, null, onCompleted); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Action onNext, Action onError, Action onCompleted) + { + Error.ThrowArgumentNullException(source, nameof(source)); + return new Do(source, onNext, onError, onCompleted); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, IObserver observer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(observer, nameof(observer)); + + return source.Do(observer.OnNext, observer.OnError, observer.OnCompleted); // alloc delegate. + } + + // TODO:Rename -> DoAwait + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onCompleted) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError, Func onCompleted) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onCompleted) + { + throw new NotImplementedException(); + } + + public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError, Func onCompleted) + { + throw new NotImplementedException(); + } + } + + internal sealed class Do : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Action onNext; + readonly Action onError; + readonly Action onCompleted; + + public Do(IUniTaskAsyncEnumerable source, Action onNext, Action onError, Action onCompleted) + { + this.source = source; + this.onNext = onNext; + this.onError = onError; + this.onCompleted = onCompleted; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, onNext, onError, onCompleted, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly Action onNext; + readonly Action onError; + readonly Action onCompleted; + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, Action onNext, Action onError, Action onCompleted, CancellationToken cancellationToken) + { + this.source = source; + this.onNext = onNext; + this.onError = onError; + this.onCompleted = onCompleted; + this.cancellationToken = cancellationToken; + } + + public TSource Current { get; private set; } + + + public UniTask 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(this, completionSource.Version); + } + + if (isCompleted) + { + MoveNextCore(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + + return new UniTask(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(UniTask.Awaiter awaiter, out T result) + { + try + { + result = awaiter.GetResult(); + return true; + } + catch (Exception ex) + { + CallTrySetExceptionAfterNotification(ex); + result = default; + return false; + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResultWithNotification(self.awaiter, out var result)) + { + if (result) + { + var v = self.enumerator.Current; + + if (self.onNext != null) + { + try + { + self.onNext(v); + } + catch (Exception ex) + { + self.CallTrySetExceptionAfterNotification(ex); + } + } + + self.Current = v; + self.completionSource.TrySetResult(true); + } + else + { + if (self.onCompleted != null) + { + try + { + self.onCompleted(); + } + catch (Exception ex) + { + self.CallTrySetExceptionAfterNotification(ex); + return; + } + } + + self.completionSource.TrySetResult(false); + } + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } +} diff --git a/src/UniTask.NetCore/Linq/Select.cs b/src/UniTask.NetCore/Linq/Select.cs index ca1479f..d541fda 100644 --- a/src/UniTask.NetCore/Linq/Select.cs +++ b/src/UniTask.NetCore/Linq/Select.cs @@ -173,9 +173,10 @@ namespace Cysharp.Threading.Tasks.Linq return selector(sourceCurrent); } - protected override bool TrySetCurrentCore(TResult awaitResult) + protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration) { Current = awaitResult; + terminateIteration= false; return true; } } @@ -213,9 +214,10 @@ namespace Cysharp.Threading.Tasks.Linq return selector(sourceCurrent, checked(index++)); } - protected override bool TrySetCurrentCore(TResult awaitResult) + protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration) { Current = awaitResult; + terminateIteration= false; return true; } } @@ -252,9 +254,10 @@ namespace Cysharp.Threading.Tasks.Linq return selector(sourceCurrent, cancellationToken); } - protected override bool TrySetCurrentCore(TResult awaitResult) + protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration) { Current = awaitResult; + terminateIteration= false; return true; } } @@ -292,9 +295,10 @@ namespace Cysharp.Threading.Tasks.Linq return selector(sourceCurrent, checked(index++), cancellationToken); } - protected override bool TrySetCurrentCore(TResult awaitResult) + protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration) { Current = awaitResult; + terminateIteration= false; return true; } } diff --git a/src/UniTask.NetCore/Linq/Skip.cs b/src/UniTask.NetCore/Linq/Skip.cs index 2ba8c9e..8c46119 100644 --- a/src/UniTask.NetCore/Linq/Skip.cs +++ b/src/UniTask.NetCore/Linq/Skip.cs @@ -1,775 +1,69 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Skip + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Skip(this IUniTaskAsyncEnumerable source, Int32 count) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new Skip(source, count); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Skip : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly int count; + + public Skip(IUniTaskAsyncEnumerable source, int count) + { + this.source = source; + this.count = count; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, count, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorBase + { + readonly int count; + + int index; + + public Enumerator(IUniTaskAsyncEnumerable 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; + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/SkipWhile.cs b/src/UniTask.NetCore/Linq/SkipWhile.cs index cedbcef..ec97e42 100644 --- a/src/UniTask.NetCore/Linq/SkipWhile.cs +++ b/src/UniTask.NetCore/Linq/SkipWhile.cs @@ -1,775 +1,379 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class SkipWhile + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable SkipWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new SkipWhile(source, predicate); + } + + public static IUniTaskAsyncEnumerable SkipWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new SkipWhileInt(source, predicate); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new SkipWhileAwait(source, predicate); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new SkipWhileIntAwait(source, predicate); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new SkipWhileAwaitWithCancellation(source, predicate); + } + + public static IUniTaskAsyncEnumerable SkipWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new SkipWhileIntAwaitWithCancellation(source, predicate); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class SkipWhile : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func predicate; + + public SkipWhile(IUniTaskAsyncEnumerable source, Func predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + Func predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (predicate == null || !predicate(SourceCurrent)) + { + predicate = null; + Current = SourceCurrent; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } + + internal sealed class SkipWhileInt : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func predicate; + + public SkipWhileInt(IUniTaskAsyncEnumerable source, Func predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + Func predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (predicate == null || !predicate(SourceCurrent, checked(index++))) + { + predicate = null; + Current = SourceCurrent; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } + + internal sealed class SkipWhileAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public SkipWhileAwait(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + Func> predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + if (predicate == null) + { + return CompletedTasks.False; + } + + return predicate(sourceCurrent); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + if (!awaitResult) + { + predicate = null; + Current = SourceCurrent; + terminateIteration= false; + return true; + } + else + { + terminateIteration= false; + return false; + } + } + } + } + + internal sealed class SkipWhileIntAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public SkipWhileIntAwait(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + Func> predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + if (predicate == null) + { + return CompletedTasks.False; + } + + return predicate(sourceCurrent, checked(index++)); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + terminateIteration= false; + if (!awaitResult) + { + predicate = null; + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } + + internal sealed class SkipWhileAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public SkipWhileAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + Func> predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + if (predicate == null) + { + return CompletedTasks.False; + } + + return predicate(sourceCurrent, cancellationToken); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + terminateIteration= false; + if (!awaitResult) + { + predicate = null; + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } + + internal sealed class SkipWhileIntAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public SkipWhileIntAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + Func> predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + if (predicate == null) + { + return CompletedTasks.False; + } + + return predicate(sourceCurrent, checked(index++), cancellationToken); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + terminateIteration= false; + if (!awaitResult) + { + predicate = null; + Current = SourceCurrent; + return true; + } + else + { + return false; + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Take.cs b/src/UniTask.NetCore/Linq/Take.cs index 901720e..d632b1c 100644 --- a/src/UniTask.NetCore/Linq/Take.cs +++ b/src/UniTask.NetCore/Linq/Take.cs @@ -1,775 +1,69 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Take + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Take(this IUniTaskAsyncEnumerable source, Int32 count) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return new Take(source, count); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Take : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly int count; + + public Take(IUniTaskAsyncEnumerable source, int count) + { + this.source = source; + this.count = count; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, count, cancellationToken); + } + + sealed class Enumerator : AsyncEnumeratorBase + { + readonly int count; + + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, int count, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.count = count; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (checked(index++) < count) + { + Current = SourceCurrent; + result = true; + return true; + } + else + { + result = false; + return true; + } + } + else + { + result = false; + return true; + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/TakeWhile.cs b/src/UniTask.NetCore/Linq/TakeWhile.cs index 4445869..8e98292 100644 --- a/src/UniTask.NetCore/Linq/TakeWhile.cs +++ b/src/UniTask.NetCore/Linq/TakeWhile.cs @@ -1,775 +1,342 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class TakeWhile + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable TakeWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new TakeWhile(source, predicate); + } + + public static IUniTaskAsyncEnumerable TakeWhile(this IUniTaskAsyncEnumerable source, Func predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new TakeWhileInt(source, predicate); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new TakeWhileAwait(source, predicate); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new TakeWhileIntAwait(source, predicate); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new TakeWhileAwaitWithCancellation(source, predicate); + } + + public static IUniTaskAsyncEnumerable TakeWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(predicate, nameof(predicate)); + + return new TakeWhileIntAwaitWithCancellation(source, predicate); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class TakeWhile : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func predicate; + + public TakeWhile(IUniTaskAsyncEnumerable source, Func predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + Func predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (predicate(SourceCurrent)) + { + Current = SourceCurrent; + result = true; + return true; + } + } + + result = false; + return true; + } + } + } + + internal sealed class TakeWhileInt : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func predicate; + + public TakeWhileInt(IUniTaskAsyncEnumerable source, Func predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly Func predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func predicate, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + if (predicate(SourceCurrent, checked(index++))) + { + Current = SourceCurrent; + result = true; + return true; + } + } + + result = false; + return true; + } + } + } + + internal sealed class TakeWhileAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public TakeWhileAwait(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + Func> predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + if (awaitResult) + { + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = true; + return false; + } + } + } + } + + internal sealed class TakeWhileIntAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public TakeWhileIntAwait(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent, checked(index++)); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + if (awaitResult) + { + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = true; + return false; + } + } + } + } + + internal sealed class TakeWhileAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public TakeWhileAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + Func> predicate; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent, cancellationToken); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + if (awaitResult) + { + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = true; + return false; + } + } + } + } + + internal sealed class TakeWhileIntAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> predicate; + + public TakeWhileIntAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> predicate) + { + this.source = source; + this.predicate = predicate; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, predicate, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly Func> predicate; + int index; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> predicate, CancellationToken cancellationToken) + : base(source, cancellationToken) + { + this.predicate = predicate; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return predicate(sourceCurrent, checked(index++), cancellationToken); + } + + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) + { + if (awaitResult) + { + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = true; + return false; + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Where.cs b/src/UniTask.NetCore/Linq/Where.cs index 05a1ed7..6b1cdd6 100644 --- a/src/UniTask.NetCore/Linq/Where.cs +++ b/src/UniTask.NetCore/Linq/Where.cs @@ -188,8 +188,9 @@ namespace Cysharp.Threading.Tasks.Linq return predicate(sourceCurrent); } - protected override bool TrySetCurrentCore(bool awaitResult) + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) { + terminateIteration = false; if (awaitResult) { Current = SourceCurrent; @@ -236,8 +237,9 @@ namespace Cysharp.Threading.Tasks.Linq return predicate(sourceCurrent, checked(index++)); } - protected override bool TrySetCurrentCore(bool awaitResult) + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) { + terminateIteration = false; if (awaitResult) { Current = SourceCurrent; @@ -285,8 +287,9 @@ namespace Cysharp.Threading.Tasks.Linq return predicate(sourceCurrent, cancellationToken); } - protected override bool TrySetCurrentCore(bool awaitResult) + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) { + terminateIteration = false; if (awaitResult) { Current = SourceCurrent; @@ -333,8 +336,9 @@ namespace Cysharp.Threading.Tasks.Linq return predicate(sourceCurrent, checked(index++), cancellationToken); } - protected override bool TrySetCurrentCore(bool awaitResult) + protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration) { + terminateIteration = false; if (awaitResult) { Current = SourceCurrent; diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index e04d089..11e8d7a 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -308,87 +308,18 @@ namespace ___Dummy - - public static IUniTaskAsyncEnumerable Skip(this IUniTaskAsyncEnumerable source, Int32 count) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable SkipLast(this IUniTaskAsyncEnumerable source, Int32 count) { throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable SkipWhile(this IUniTaskAsyncEnumerable source, Func predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SkipWhile(this IUniTaskAsyncEnumerable source, Func predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SkipWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SkipWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SkipWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable SkipWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Take(this IUniTaskAsyncEnumerable source, Int32 count) - { - throw new NotImplementedException(); - } + public static IUniTaskAsyncEnumerable TakeLast(this IUniTaskAsyncEnumerable source, Int32 count) { throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable TakeWhile(this IUniTaskAsyncEnumerable source, Func predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable TakeWhile(this IUniTaskAsyncEnumerable source, Func predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable TakeWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable TakeWhileAwait(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable TakeWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable TakeWhileAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> predicate) - { - throw new NotImplementedException(); - } - public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector) { throw new NotImplementedException(); @@ -467,26 +398,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable> Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Zip(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable ZipAwait(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> selector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable ZipAwaitWithCancellation(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, Func> selector) - { - throw new NotImplementedException(); - } - } diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 843564a..024c8da 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -39,8 +39,20 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - var foo = Enumerable.Range(1, 10).ToArray().AsEnumerable().GetEnumerator() as IEnumerator; - Console.WriteLine(foo.GetType().FullName); + await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10).Do(x => Console.WriteLine("DO:" + x)) + //.TakeWhileAwait(x => UniTask.FromResult(x < 5)) + .Take(5) + + ) + { + + Console.WriteLine(item); + } + + + + + } @@ -48,7 +60,7 @@ namespace NetCoreSandbox void Foo() { - + // AsyncEnumerable.Range(1,10).Do( // AsyncEnumerable.t diff --git a/src/UniTask.NetCoreTests/Linq/Paging.cs b/src/UniTask.NetCoreTests/Linq/Paging.cs new file mode 100644 index 0000000..d0e2b55 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Paging.cs @@ -0,0 +1,235 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Paging + { + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(9, 0)] + [InlineData(9, 1)] + [InlineData(9, 5)] + [InlineData(9, 9)] + [InlineData(9, 15)] + public async Task Skip(int collection, int skipCount) + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).Skip(skipCount).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).Skip(skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task SkipException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Skip(5).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(9, 0)] + [InlineData(9, 1)] + [InlineData(9, 5)] + [InlineData(9, 9)] + [InlineData(9, 15)] + public async Task Take(int collection, int takeCount) + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).Take(takeCount).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).Take(takeCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task TakeException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Take(5).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(9, 0)] + [InlineData(9, 1)] + [InlineData(9, 5)] + [InlineData(9, 9)] + [InlineData(9, 15)] + public async Task SkipWhile(int collection, int skipCount) + { + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwait(x => UniTask.Run(() => x < skipCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwait((x, i) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < skipCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipWhile(x => x < skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipWhile((x, i) => x < (skipCount - i)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + } + + [Fact] + public async Task SkipWhileException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipWhile(x => x < 2).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipWhile((x, i) => x < 2).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipWhileAwait((x) => UniTask.Run(() => x < 2)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipWhileAwait((x, i) => UniTask.Run(() => x < 2)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < 2)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < 2)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(9, 0)] + [InlineData(9, 1)] + [InlineData(9, 5)] + [InlineData(9, 9)] + [InlineData(9, 15)] + public async Task TakeWhile(int collection, int skipCount) + { + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwait(x => UniTask.Run(() => x < skipCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwait((x, i) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < skipCount)).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeWhile(x => x < skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < (skipCount - i))).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeWhile((x, i) => x < (skipCount - i)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + } + + [Fact] + public async Task TakeWhileException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeWhile(x => x < 5).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeWhile((x, i) => x < 5).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeWhileAwait((x) => UniTask.Run(() => x < 5)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeWhileAwait((x, i) => UniTask.Run(() => x < 5)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < 5)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < 5)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } +} From a5f47d4095bcf6a8573dd1444d08643a4418238b Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 12:38:32 +0900 Subject: [PATCH 20/31] SkipLast --- src/UniTask.NetCore/Linq/SkipLast.cs | 920 ++++-------------------- src/UniTask.NetCore/Linq/_FileMaker.cs | 6 - src/UniTask.NetCoreSandbox/Program.cs | 10 +- src/UniTask.NetCoreTests/Linq/Paging.cs | 25 + 4 files changed, 181 insertions(+), 780 deletions(-) diff --git a/src/UniTask.NetCore/Linq/SkipLast.cs b/src/UniTask.NetCore/Linq/SkipLast.cs index 5f79cf2..665e15d 100644 --- a/src/UniTask.NetCore/Linq/SkipLast.cs +++ b/src/UniTask.NetCore/Linq/SkipLast.cs @@ -1,775 +1,153 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class SkipLast + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable SkipLast(this IUniTaskAsyncEnumerable source, Int32 count) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + // non skip. + if (count <= 0) + { + return source; + } + + return new SkipLast(source, count); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class SkipLast : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly int count; + + public SkipLast(IUniTaskAsyncEnumerable source, int count) + { + this.source = source; + this.count = count; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, count, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly int count; + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + Queue queue; + + bool continueNext; + + public Enumerator(IUniTaskAsyncEnumerable source, int count, CancellationToken cancellationToken) + { + this.source = source; + this.count = count; + this.cancellationToken = cancellationToken; + } + + public TSource Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + queue = new Queue(); + } + + completionSource.Reset(); + SourceMoveNext(); + return new UniTask(this, completionSource.Version); + } + + void SourceMoveNext() + { + try + { + + LOOP: + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + if (self.queue.Count == self.count) + { + self.continueNext = false; + + var deq = self.queue.Dequeue(); + self.Current = deq; + self.queue.Enqueue(self.enumerator.Current); + + self.completionSource.TrySetResult(true); + } + else + { + self.queue.Enqueue(self.enumerator.Current); + + if (!self.continueNext) + { + self.SourceMoveNext(); + } + } + } + else + { + self.continueNext = false; + self.completionSource.TrySetResult(false); + } + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 11e8d7a..7fca4f5 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -307,12 +307,6 @@ namespace ___Dummy - - public static IUniTaskAsyncEnumerable SkipLast(this IUniTaskAsyncEnumerable source, Int32 count) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable TakeLast(this IUniTaskAsyncEnumerable source, Int32 count) diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 024c8da..dc26574 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -39,9 +39,11 @@ namespace NetCoreSandbox static async Task Main(string[] args) { - await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10).Do(x => Console.WriteLine("DO:" + x)) - //.TakeWhileAwait(x => UniTask.FromResult(x < 5)) - .Take(5) + await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10) + .SelectAwait(x => UniTask.Run(() => x)) + .SkipLast(6) + + ) { @@ -53,6 +55,8 @@ namespace NetCoreSandbox + + } diff --git a/src/UniTask.NetCoreTests/Linq/Paging.cs b/src/UniTask.NetCoreTests/Linq/Paging.cs index d0e2b55..aef0600 100644 --- a/src/UniTask.NetCoreTests/Linq/Paging.cs +++ b/src/UniTask.NetCoreTests/Linq/Paging.cs @@ -39,6 +39,31 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await xs); } } + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(9, 0)] + [InlineData(9, 1)] + [InlineData(9, 5)] + [InlineData(9, 9)] + [InlineData(9, 15)] + public async Task SkipLast(int collection, int skipCount) + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).SkipLast(skipCount).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).SkipLast(skipCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task SkipLastException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.SkipLast(5).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } [Theory] [InlineData(0, 0)] From 8ef7a660813ea92d4ffdf553030f5cdc8b02a47a Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 14:01:23 +0900 Subject: [PATCH 21/31] TakeLast --- src/UniTask.NetCore/Linq/SkipLast.cs | 4 + src/UniTask.NetCore/Linq/TakeLast.cs | 940 +++++------------------- src/UniTask.NetCoreSandbox/Program.cs | 2 +- src/UniTask.NetCoreTests/Linq/Paging.cs | 25 + 4 files changed, 199 insertions(+), 772 deletions(-) diff --git a/src/UniTask.NetCore/Linq/SkipLast.cs b/src/UniTask.NetCore/Linq/SkipLast.cs index 665e15d..345ec3e 100644 --- a/src/UniTask.NetCore/Linq/SkipLast.cs +++ b/src/UniTask.NetCore/Linq/SkipLast.cs @@ -138,6 +138,10 @@ namespace Cysharp.Threading.Tasks.Linq self.completionSource.TrySetResult(false); } } + else + { + self.continueNext = false; + } } public UniTask DisposeAsync() diff --git a/src/UniTask.NetCore/Linq/TakeLast.cs b/src/UniTask.NetCore/Linq/TakeLast.cs index 4b4d955..d770c3b 100644 --- a/src/UniTask.NetCore/Linq/TakeLast.cs +++ b/src/UniTask.NetCore/Linq/TakeLast.cs @@ -1,775 +1,173 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class TakeLast + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable TakeLast(this IUniTaskAsyncEnumerable source, Int32 count) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + // non take. + if (count <= 0) + { + return Empty(); + } + + return new TakeLast(source, count); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class TakeLast : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly int count; + + public TakeLast(IUniTaskAsyncEnumerable source, int count) + { + this.source = source; + this.count = count; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, count, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly int count; + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + Queue queue; + + bool iterateCompleted; + bool continueNext; + + public Enumerator(IUniTaskAsyncEnumerable source, int count, CancellationToken cancellationToken) + { + this.source = source; + this.count = count; + this.cancellationToken = cancellationToken; + } + + public TSource Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + queue = new Queue(); + } + + completionSource.Reset(); + SourceMoveNext(); + return new UniTask(this, completionSource.Version); + } + + void SourceMoveNext() + { + if (iterateCompleted) + { + if (queue.Count > 0) + { + Current = queue.Dequeue(); + completionSource.TrySetResult(true); + } + else + { + completionSource.TrySetResult(false); + } + + return; + } + + try + { + LOOP: + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + if (self.queue.Count < self.count) + { + self.queue.Enqueue(self.enumerator.Current); + + if (!self.continueNext) + { + self.SourceMoveNext(); + } + } + else + { + self.queue.Dequeue(); + self.queue.Enqueue(self.enumerator.Current); + + if (!self.continueNext) + { + self.SourceMoveNext(); + } + } + } + else + { + self.continueNext = false; + self.iterateCompleted = true; + self.SourceMoveNext(); + } + } + else + { + self.continueNext = false; + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index dc26574..52a62d1 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -41,7 +41,7 @@ namespace NetCoreSandbox { await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10) .SelectAwait(x => UniTask.Run(() => x)) - .SkipLast(6) + .TakeLast(6) diff --git a/src/UniTask.NetCoreTests/Linq/Paging.cs b/src/UniTask.NetCoreTests/Linq/Paging.cs index aef0600..cfea04b 100644 --- a/src/UniTask.NetCoreTests/Linq/Paging.cs +++ b/src/UniTask.NetCoreTests/Linq/Paging.cs @@ -64,6 +64,31 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await xs); } } + [Theory] + [InlineData(0, 0)] + [InlineData(0, 1)] + [InlineData(9, 0)] + [InlineData(9, 1)] + [InlineData(9, 5)] + [InlineData(9, 9)] + [InlineData(9, 15)] + public async Task TakeLast(int collection, int takeCount) + { + var xs = await UniTaskAsyncEnumerable.Range(1, collection).TakeLast(takeCount).ToArrayAsync(); + var ys = Enumerable.Range(1, collection).TakeLast(takeCount).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task TakeLastException() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.TakeLast(5).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } [Theory] [InlineData(0, 0)] From b20b37e7a5b39d389b3d1187d42239a211f4407a Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 15:53:27 +0900 Subject: [PATCH 22/31] Distinct, Except, Intersect, Union --- .../Linq/AsyncEnumeratorBase.cs | 10 +- src/UniTask.NetCore/Linq/Distinct.cs | 843 ++--------------- src/UniTask.NetCore/Linq/Except.cs | 883 +++-------------- src/UniTask.NetCore/Linq/Intersect.cs | 884 +++--------------- src/UniTask.NetCore/Linq/Join.cs | 776 +-------------- src/UniTask.NetCore/Linq/ToHashSet.cs | 14 +- src/UniTask.NetCore/Linq/Union.cs | 795 +--------------- src/UniTask.NetCore/Linq/_FileMaker.cs | 47 - src/UniTask.NetCoreSandbox/Program.cs | 2 +- src/UniTask.NetCoreTests/Linq/Sets.cs | 138 +++ src/UniTask/Assets/Plugins/UniTask/UniTask.cs | 5 + 11 files changed, 485 insertions(+), 3912 deletions(-) create mode 100644 src/UniTask.NetCoreTests/Linq/Sets.cs diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index d5e5b4f..b4b4493 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -100,10 +100,18 @@ namespace Cysharp.Threading.Tasks.Linq } completionSource.Reset(); - SourceMoveNext(); + if (!OnFirstIteration()) + { + SourceMoveNext(); + } return new UniTask(this, completionSource.Version); } + protected virtual bool OnFirstIteration() + { + return false; + } + protected void SourceMoveNext() { CONTINUE: diff --git a/src/UniTask.NetCore/Linq/Distinct.cs b/src/UniTask.NetCore/Linq/Distinct.cs index 980cae0..fc4aa48 100644 --- a/src/UniTask.NetCore/Linq/Distinct.cs +++ b/src/UniTask.NetCore/Linq/Distinct.cs @@ -1,775 +1,76 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Distinct + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) + { + Error.ThrowArgumentNullException(source, nameof(source)); + + return Distinct(source, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Distinct(source, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Distinct : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly IEqualityComparer comparer; + + public Distinct(IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + this.source = source; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly HashSet set; + + public Enumerator(IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.set = new HashSet(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; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Except.cs b/src/UniTask.NetCore/Linq/Except.cs index db2aa41..28e565a 100644 --- a/src/UniTask.NetCore/Linq/Except.cs +++ b/src/UniTask.NetCore/Linq/Except.cs @@ -1,775 +1,116 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Except + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return new Except(first, second, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Except(first, second, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Except : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly IEqualityComparer comparer; + + public Except(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + this.first = first; + this.second = second; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + static Action HashSetAsyncCoreDelegate = HashSetAsyncCore; + + readonly IEqualityComparer comparer; + readonly IUniTaskAsyncEnumerable second; + + HashSet set; + UniTask>.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(first, cancellationToken) + { + this.second = second; + this.comparer = comparer; + } + + protected override bool OnFirstIteration() + { + if (set != null) return false; + + awaiter = second.ToHashSetAsync(cancellationToken).GetAwaiter(); + if (awaiter.IsCompleted) + { + set = awaiter.GetResult(); + SourceMoveNext(); + } + else + { + awaiter.SourceOnCompleted(HashSetAsyncCoreDelegate, this); + } + + return true; + } + + static void HashSetAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + self.set = result; + self.SourceMoveNext(); + } + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + if (set.Add(v)) + { + Current = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Intersect.cs b/src/UniTask.NetCore/Linq/Intersect.cs index 4207678..897caa1 100644 --- a/src/UniTask.NetCore/Linq/Intersect.cs +++ b/src/UniTask.NetCore/Linq/Intersect.cs @@ -1,775 +1,117 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Intersect + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return new Intersect(first, second, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Intersect(first, second, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class Intersect : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable first; + readonly IUniTaskAsyncEnumerable second; + readonly IEqualityComparer comparer; + + public Intersect(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + this.first = first; + this.second = second; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(first, second, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + static Action HashSetAsyncCoreDelegate = HashSetAsyncCore; + + readonly IEqualityComparer comparer; + readonly IUniTaskAsyncEnumerable second; + + HashSet set; + UniTask>.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(first, cancellationToken) + { + this.second = second; + this.comparer = comparer; + } + + protected override bool OnFirstIteration() + { + if (set != null) return false; + + awaiter = second.ToHashSetAsync(cancellationToken).GetAwaiter(); + if (awaiter.IsCompleted) + { + set = awaiter.GetResult(); + SourceMoveNext(); + } + else + { + awaiter.SourceOnCompleted(HashSetAsyncCoreDelegate, this); + } + + return true; + } + + static void HashSetAsyncCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + self.set = result; + self.SourceMoveNext(); + } + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + + if (set.Remove(v)) + { + Current = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask.NetCore/Linq/Join.cs index 1b1aa09..5f28270 100644 --- a/src/UniTask.NetCore/Linq/Join.cs +++ b/src/UniTask.NetCore/Linq/Join.cs @@ -1,775 +1 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class Join - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToHashSet.cs b/src/UniTask.NetCore/Linq/ToHashSet.cs index d858db1..ec54841 100644 --- a/src/UniTask.NetCore/Linq/ToHashSet.cs +++ b/src/UniTask.NetCore/Linq/ToHashSet.cs @@ -10,15 +10,23 @@ namespace Cysharp.Threading.Tasks.Linq { Error.ThrowArgumentNullException(source, nameof(source)); - return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, cancellationToken); + return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, EqualityComparer.Default, cancellationToken); + } + + public static UniTask> ToHashSetAsync(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken = default) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return Cysharp.Threading.Tasks.Linq.ToHashSet.InvokeAsync(source, comparer, cancellationToken); } } internal static class ToHashSet { - internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) + internal static async UniTask> InvokeAsync(IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken) { - var set = new HashSet(); + var set = new HashSet(comparer); var e = source.GetAsyncEnumerator(cancellationToken); try diff --git a/src/UniTask.NetCore/Linq/Union.cs b/src/UniTask.NetCore/Linq/Union.cs index 3413223..2ceefab 100644 --- a/src/UniTask.NetCore/Linq/Union.cs +++ b/src/UniTask.NetCore/Linq/Union.cs @@ -1,775 +1,26 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System.Collections.Generic; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class Union + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + + return Union(first, second, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(first, nameof(first)); + Error.ThrowArgumentNullException(second, nameof(second)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + // improv without combinate? + return first.Concat(second).Distinct(comparer); + } } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 7fca4f5..96f13ab 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -26,26 +26,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - - public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Except(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } @@ -200,16 +180,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Intersect(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) { throw new NotImplementedException(); @@ -309,10 +279,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable TakeLast(this IUniTaskAsyncEnumerable source, Int32 count) - { - throw new NotImplementedException(); - } public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector) { @@ -380,19 +346,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Union(this IUniTaskAsyncEnumerable first, IUniTaskAsyncEnumerable second, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - - - } diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index 52a62d1..f9deafb 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -54,7 +54,7 @@ namespace NetCoreSandbox - + //Enumerable.Range(1,10).ToHashSet( } diff --git a/src/UniTask.NetCoreTests/Linq/Sets.cs b/src/UniTask.NetCoreTests/Linq/Sets.cs new file mode 100644 index 0000000..627c578 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Sets.cs @@ -0,0 +1,138 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Sets + { + public static IEnumerable array1 = new object[][] + { + new object[] { new int[] { } }, // empty + new object[] { new int[] { 1, 2, 3 } }, // no dup + new object[] { new int[] { 1, 2, 3, 3, 4, 5, 2 } }, // dup + }; + + public static IEnumerable array2 = new object[][] + { + new object[] { new int[] { } }, // empty + new object[] { new int[] { 1, 2 } }, + new object[] { new int[] { 1, 2, 4, 5, 9 } }, // dup + }; + + [Theory] + [MemberData(nameof(array1))] + public async Task Distinct(int[] array) + { + var xs = await array.ToUniTaskAsyncEnumerable().Distinct().ToArrayAsync(); + var ys = array.Distinct().ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task DistinctThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Distinct().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Except() + { + foreach (var a1 in array1.First().Cast()) + { + foreach (var a2 in array2.First().Cast()) + { + var xs = await a1.ToUniTaskAsyncEnumerable().Except(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = a1.Except(a2).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + } + + [Fact] + public async Task ExceptThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Except(UniTaskAsyncEnumerable.Return(10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Return(10).Except(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Intersect() + { + foreach (var a1 in array1.First().Cast()) + { + foreach (var a2 in array2.First().Cast()) + { + var xs = await a1.ToUniTaskAsyncEnumerable().Intersect(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = a1.Intersect(a2).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + } + + [Fact] + public async Task IntersectThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Intersect(UniTaskAsyncEnumerable.Return(10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Return(10).Intersect(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + + [Fact] + public async Task Union() + { + foreach (var a1 in array1.First().Cast()) + { + foreach (var a2 in array2.First().Cast()) + { + var xs = await a1.ToUniTaskAsyncEnumerable().Union(a2.ToUniTaskAsyncEnumerable()).ToArrayAsync(); + var ys = a1.Union(a2).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + } + + [Fact] + public async Task UnionThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Union(UniTaskAsyncEnumerable.Return(10)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + foreach (var item in UniTaskTestException.Throws()) + { + var xs = UniTaskAsyncEnumerable.Return(10).Union(item).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } +} diff --git a/src/UniTask/Assets/Plugins/UniTask/UniTask.cs b/src/UniTask/Assets/Plugins/UniTask/UniTask.cs index 1958d3e..35bf8b6 100644 --- a/src/UniTask/Assets/Plugins/UniTask/UniTask.cs +++ b/src/UniTask/Assets/Plugins/UniTask/UniTask.cs @@ -15,6 +15,7 @@ namespace Cysharp.Threading.Tasks { internal static readonly Action InvokeActionDelegate = InvokeAction; + [DebuggerHidden] static void InvokeAction(object state) { ((Action)state).Invoke(); @@ -318,6 +319,8 @@ namespace Cysharp.Threading.Tasks /// /// If register manually continuation, you can use it instead of for compiler OnCompleted methods. /// + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SourceOnCompleted(Action continuation, object state) { if (task.source == null) @@ -640,6 +643,8 @@ namespace Cysharp.Threading.Tasks /// /// If register manually continuation, you can use it instead of for compiler OnCompleted methods. /// + [DebuggerHidden] + [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SourceOnCompleted(Action continuation, object state) { var s = task.source; From 12c507574e21a16abd9781e22fc4bcdc2c0d4c91 Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 17:33:41 +0900 Subject: [PATCH 23/31] Join --- src/UniTask.NetCore/Linq/Join.cs | 717 ++++++++++++++++++++++++- src/UniTask.NetCore/Linq/ToLookup.cs | 2 +- src/UniTask.NetCore/Linq/_FileMaker.cs | 29 - src/UniTask.NetCoreTests/Linq/Joins.cs | 116 ++++ 4 files changed, 833 insertions(+), 31 deletions(-) create mode 100644 src/UniTask.NetCoreTests/Linq/Joins.cs diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask.NetCore/Linq/Join.cs index 5f28270..1b42e2d 100644 --- a/src/UniTask.NetCore/Linq/Join.cs +++ b/src/UniTask.NetCore/Linq/Join.cs @@ -1 +1,716 @@ - \ No newline at end of file +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 Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable JoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable JoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable JoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable JoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + } + + internal sealed class Join : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func outerKeySelector; + readonly Func innerKeySelector; + readonly Func resultSelector; + readonly IEqualityComparer comparer; + + public Join(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func outerKeySelector; + readonly Func innerKeySelector; + readonly Func resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + ILookup lookup; + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + TOuter currentOuterValue; + IEnumerator valueEnumerator; + + bool continueNext; + + public Enumerator(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (lookup == null) + { + CreateInnerHashSet().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateInnerHashSet() + { + try + { + lookup = await inner.ToLookupAsync(innerKeySelector, 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 = null; + } + } + + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + + return; + + TRY_SET_RESULT_TRUE: + completionSource.TrySetResult(true); + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + self.currentOuterValue = self.enumerator.Current; + var key = self.outerKeySelector(self.currentOuterValue); + self.valueEnumerator = self.lookup[key].GetEnumerator(); + + if (self.continueNext) + { + return; + } + else + { + self.SourceMoveNext(); + } + } + else + { + self.continueNext = false; + self.completionSource.TrySetResult(false); + } + } + else + { + self.continueNext = false; + } + } + + public UniTask DisposeAsync() + { + if (valueEnumerator != null) + { + valueEnumerator.Dispose(); + } + + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } + + internal sealed class JoinAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func> resultSelector; + readonly IEqualityComparer comparer; + + public JoinAwait(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + static readonly Action OuterSelectCoreDelegate = OuterSelectCore; + static readonly Action ResultSelectCoreDelegate = ResultSelectCore; + + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + ILookup lookup; + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + TOuter currentOuterValue; + IEnumerator valueEnumerator; + + UniTask.Awaiter resultAwaiter; + UniTask.Awaiter outerKeyAwaiter; + + bool continueNext; + + public Enumerator(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (lookup == null) + { + CreateInnerHashSet().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateInnerHashSet() + { + try + { + lookup = await inner.ToLookupAwaitAsync(innerKeySelector, 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 = null; + } + } + + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + self.currentOuterValue = self.enumerator.Current; + + self.outerKeyAwaiter = self.outerKeySelector(self.currentOuterValue).GetAwaiter(); + + if (self.outerKeyAwaiter.IsCompleted) + { + OuterSelectCore(self); + } + else + { + self.continueNext = false; + self.outerKeyAwaiter.SourceOnCompleted(OuterSelectCoreDelegate, self); + } + } + else + { + self.continueNext = false; + self.completionSource.TrySetResult(false); + } + } + else + { + self.continueNext = false; + } + } + + static void OuterSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.outerKeyAwaiter, out var key)) + { + self.valueEnumerator = self.lookup[key].GetEnumerator(); + + if (self.continueNext) + { + return; + } + else + { + self.SourceMoveNext(); + } + } + else + { + self.continueNext = false; + } + } + + static void ResultSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultAwaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public UniTask DisposeAsync() + { + if (valueEnumerator != null) + { + valueEnumerator.Dispose(); + } + + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } + + internal sealed class JoinAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func> resultSelector; + readonly IEqualityComparer comparer; + + public JoinAwaitWithCancellation(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + static readonly Action OuterSelectCoreDelegate = OuterSelectCore; + static readonly Action ResultSelectCoreDelegate = ResultSelectCore; + + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + ILookup lookup; + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + TOuter currentOuterValue; + IEnumerator valueEnumerator; + + UniTask.Awaiter resultAwaiter; + UniTask.Awaiter outerKeyAwaiter; + + bool continueNext; + + public Enumerator(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (lookup == null) + { + CreateInnerHashSet().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateInnerHashSet() + { + try + { + lookup = await inner.ToLookupAwaitWithCancellationAsync(innerKeySelector, 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 = null; + } + } + + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + self.currentOuterValue = self.enumerator.Current; + + self.outerKeyAwaiter = self.outerKeySelector(self.currentOuterValue, self.cancellationToken).GetAwaiter(); + + if (self.outerKeyAwaiter.IsCompleted) + { + OuterSelectCore(self); + } + else + { + self.continueNext = false; + self.outerKeyAwaiter.SourceOnCompleted(OuterSelectCoreDelegate, self); + } + } + else + { + self.continueNext = false; + self.completionSource.TrySetResult(false); + } + } + else + { + self.continueNext = false; + } + } + + static void OuterSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.outerKeyAwaiter, out var key)) + { + self.valueEnumerator = self.lookup[key].GetEnumerator(); + + if (self.continueNext) + { + return; + } + else + { + self.SourceMoveNext(); + } + } + else + { + self.continueNext = false; + } + } + + static void ResultSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultAwaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public UniTask DisposeAsync() + { + if (valueEnumerator != null) + { + valueEnumerator.Dispose(); + } + + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } + +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/ToLookup.cs b/src/UniTask.NetCore/Linq/ToLookup.cs index d0ccbaa..dfd9faa 100644 --- a/src/UniTask.NetCore/Linq/ToLookup.cs +++ b/src/UniTask.NetCore/Linq/ToLookup.cs @@ -494,7 +494,7 @@ namespace Cysharp.Threading.Tasks.Linq return new Lookup(dict); } - public IEnumerable this[TKey key] => dict[key]; + public IEnumerable this[TKey key] => dict.TryGetValue(key, out var g) ? g : Enumerable.Empty(); public int Count => dict.Count; diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 96f13ab..840e767 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -180,35 +180,6 @@ namespace ___Dummy throw new NotImplementedException(); } - public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable Join(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable JoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable JoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable JoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable JoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } diff --git a/src/UniTask.NetCoreTests/Linq/Joins.cs b/src/UniTask.NetCoreTests/Linq/Joins.cs new file mode 100644 index 0000000..bfd1099 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Joins.cs @@ -0,0 +1,116 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class Joins + { + static int rd; + + static UniTask RandomRun(T value) + { + if (Interlocked.Increment(ref rd) % 2 == 0) + { + return UniTask.Run(() => value); + } + else + { + return UniTask.FromResult(value); + } + } + + [Fact] + public async Task Join() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + + var xs = await outer.ToUniTaskAsyncEnumerable().Join(inner.ToUniTaskAsyncEnumerable(), x => x, x => x, (x, y) => (x, y)).ToArrayAsync(); + var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + + [Fact] + public async Task JoinThrow() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + foreach (var item in UniTaskTestException.Throws()) + { + var xs = outer.ToUniTaskAsyncEnumerable().Join(item, x => x, x => x, (x, y) => x + y).ToArrayAsync(); + var ys = item.Join(inner.ToUniTaskAsyncEnumerable(), x => x, x => x, (x, y) => x + y).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + } + + [Fact] + public async Task JoinAwait() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + + var xs = await outer.ToUniTaskAsyncEnumerable().JoinAwait(inner.ToUniTaskAsyncEnumerable(), x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun((x, y))).ToArrayAsync(); + var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + + [Fact] + public async Task JoinAwaitThrow() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + foreach (var item in UniTaskTestException.Throws()) + { + var xs = outer.ToUniTaskAsyncEnumerable().JoinAwait(item, x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun(x + y)).ToArrayAsync(); + var ys = item.Join(inner.ToUniTaskAsyncEnumerable(), x => x, x => x, (x, y) => x + y).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + } + + [Fact] + public async Task JoinAwaitCt() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + + var xs = await outer.ToUniTaskAsyncEnumerable().JoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun((x, y))).ToArrayAsync(); + var ys = outer.Join(inner, x => x, x => x, (x, y) => (x, y)).ToArray(); + + xs.Should().BeEquivalentTo(ys); + } + + + [Fact] + public async Task JoinAwaitCtThrow() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + foreach (var item in UniTaskTestException.Throws()) + { + var xs = outer.ToUniTaskAsyncEnumerable().JoinAwaitWithCancellation(item, (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun(x + y)).ToArrayAsync(); + var ys = item.JoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun(x + y)).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + } + } +} From 418586fbfb1dc29315bfa29f4a75b6082755903c Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 11 May 2020 23:17:33 +0900 Subject: [PATCH 24/31] GroupBy --- src/UniTask.NetCore/IAsyncEnumerable.cs | 5 + src/UniTask.NetCore/Linq/GroupBy.cs | 1594 ++++++++++++----------- src/UniTask.NetCore/Linq/Join.cs | 9 +- src/UniTask.NetCore/Linq/ToLookup.cs | 7 +- src/UniTask.NetCore/Linq/_FileMaker.cs | 119 -- src/UniTask.NetCoreSandbox/Program.cs | 2 + src/UniTask.NetCoreTests/Linq/Joins.cs | 73 ++ 7 files changed, 915 insertions(+), 894 deletions(-) diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask.NetCore/IAsyncEnumerable.cs index 34d0218..917c521 100644 --- a/src/UniTask.NetCore/IAsyncEnumerable.cs +++ b/src/UniTask.NetCore/IAsyncEnumerable.cs @@ -19,6 +19,11 @@ namespace Cysharp.Threading.Tasks UniTask DisposeAsync(); } + //public interface IUniTaskAsyncGrouping : IUniTaskAsyncEnumerable + //{ + // TKey Key { get; } + //} + public static class UniTaskAsyncEnumerableExtensions { public static UniTaskCancelableAsyncEnumerable WithCancellation(this IUniTaskAsyncEnumerable source, CancellationToken cancellationToken) diff --git a/src/UniTask.NetCore/Linq/GroupBy.cs b/src/UniTask.NetCore/Linq/GroupBy.cs index 46629e6..5da393b 100644 --- a/src/UniTask.NetCore/Linq/GroupBy.cs +++ b/src/UniTask.NetCore/Linq/GroupBy.cs @@ -1,775 +1,827 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class GroupBy + public static partial class UniTaskAsyncEnumerable { + // Ix-Async returns IGrouping but it is competely waste, use standard IGrouping. + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector) + { + return new GroupBy(source, keySelector, x => x, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) + { + return new GroupBy(source, keySelector, x => x, comparer); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector) + { + return new GroupBy(source, keySelector, elementSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) + { + return new GroupBy(source, keySelector, elementSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector) + { + return new GroupBy(source, keySelector, x => x, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + return new GroupBy(source, keySelector, x => x, resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector) + { + return new GroupBy(source, keySelector, elementSelector, resultSelector, EqualityComparer.Default); + } + public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + return new GroupBy(source, keySelector, elementSelector, resultSelector, comparer); + } + + // await + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), comparer); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) + { + return new GroupByAwait(source, keySelector, elementSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + return new GroupByAwait(source, keySelector, elementSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector) + { + return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector) + { + return new GroupByAwait(source, keySelector, elementSelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + return new GroupByAwait(source, keySelector, elementSelector, resultSelector, comparer); + } + + // with ct + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), comparer); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) + { + return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector) + { + return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector) + { + return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, resultSelector, comparer); + } } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class GroupBy : IUniTaskAsyncEnumerable> + { + readonly IUniTaskAsyncEnumerable source; + readonly Func keySelector; + readonly Func elementSelector; + readonly IEqualityComparer comparer; + + public GroupBy(IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, elementSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator> + { + readonly IUniTaskAsyncEnumerable source; + readonly Func keySelector; + readonly Func elementSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + IEnumerator> groupEnumerator; + + public Enumerator(IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public IGrouping Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (groupEnumerator == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(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; + completionSource.TrySetResult(true); + } + else + { + completionSource.TrySetResult(false); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + } + + public UniTask DisposeAsync() + { + if (groupEnumerator != null) + { + groupEnumerator.Dispose(); + } + + return default; + } + } + } + + internal sealed class GroupBy : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func keySelector; + readonly Func elementSelector; + readonly Func, TResult> resultSelector; + readonly IEqualityComparer comparer; + + public GroupBy(IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + readonly IUniTaskAsyncEnumerable source; + readonly Func keySelector; + readonly Func elementSelector; + readonly Func, TResult> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + IEnumerator> groupEnumerator; + + public Enumerator(IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (groupEnumerator == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateLookup() + { + try + { + var lookup = await source.ToLookupAsync(keySelector, elementSelector, comparer, cancellationToken); + groupEnumerator = lookup.GetEnumerator(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + SourceMoveNext(); + } + + void SourceMoveNext() + { + try + { + if (groupEnumerator.MoveNext()) + { + var current = groupEnumerator.Current; + Current = resultSelector(current.Key, current); + completionSource.TrySetResult(true); + } + else + { + completionSource.TrySetResult(false); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + } + + public UniTask DisposeAsync() + { + if (groupEnumerator != null) + { + groupEnumerator.Dispose(); + } + + return default; + } + } + } + + internal sealed class GroupByAwait : IUniTaskAsyncEnumerable> + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly IEqualityComparer comparer; + + public GroupByAwait(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, elementSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator> + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + IEnumerator> groupEnumerator; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public IGrouping Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (groupEnumerator == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(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; + completionSource.TrySetResult(true); + } + else + { + completionSource.TrySetResult(false); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + } + + public UniTask DisposeAsync() + { + if (groupEnumerator != null) + { + groupEnumerator.Dispose(); + } + + return default; + } + } + } + + internal sealed class GroupByAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly Func, UniTask> resultSelector; + readonly IEqualityComparer comparer; + + public GroupByAwait(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + readonly static Action ResultSelectCoreDelegate = ResultSelectCore; + + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly Func, UniTask> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + IEnumerator> groupEnumerator; + UniTask.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (groupEnumerator == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateLookup() + { + try + { + var lookup = await source.ToLookupAwaitAsync(keySelector, elementSelector, comparer, cancellationToken); + groupEnumerator = lookup.GetEnumerator(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + SourceMoveNext(); + } + + void SourceMoveNext() + { + try + { + if (groupEnumerator.MoveNext()) + { + var current = groupEnumerator.Current; + + awaiter = resultSelector(current.Key, current).GetAwaiter(); + if (awaiter.IsCompleted) + { + ResultSelectCore(this); + } + else + { + awaiter.SourceOnCompleted(ResultSelectCoreDelegate, this); + } + return; + } + else + { + completionSource.TrySetResult(false); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + } + + static void ResultSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public UniTask DisposeAsync() + { + if (groupEnumerator != null) + { + groupEnumerator.Dispose(); + } + + return default; + } + } + } + + internal sealed class GroupByAwaitWithCancellation : IUniTaskAsyncEnumerable> + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly IEqualityComparer comparer; + + public GroupByAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, elementSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator> + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + IEnumerator> groupEnumerator; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public IGrouping Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (groupEnumerator == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(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; + completionSource.TrySetResult(true); + } + else + { + completionSource.TrySetResult(false); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + } + + public UniTask DisposeAsync() + { + if (groupEnumerator != null) + { + groupEnumerator.Dispose(); + } + + return default; + } + } + } + + internal sealed class GroupByAwaitWithCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly Func, CancellationToken, UniTask> resultSelector; + readonly IEqualityComparer comparer; + + public GroupByAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, elementSelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + readonly static Action ResultSelectCoreDelegate = ResultSelectCore; + + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly Func> elementSelector; + readonly Func, CancellationToken, UniTask> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + IEnumerator> groupEnumerator; + UniTask.Awaiter awaiter; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.source = source; + this.keySelector = keySelector; + this.elementSelector = elementSelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (groupEnumerator == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateLookup() + { + try + { + var lookup = await source.ToLookupAwaitWithCancellationAsync(keySelector, elementSelector, comparer, cancellationToken); + groupEnumerator = lookup.GetEnumerator(); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + SourceMoveNext(); + } + + void SourceMoveNext() + { + try + { + if (groupEnumerator.MoveNext()) + { + var current = groupEnumerator.Current; + + awaiter = resultSelector(current.Key, current, cancellationToken).GetAwaiter(); + if (awaiter.IsCompleted) + { + ResultSelectCore(this); + } + else + { + awaiter.SourceOnCompleted(ResultSelectCoreDelegate, this); + } + return; + } + else + { + completionSource.TrySetResult(false); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + } + + static void ResultSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public UniTask DisposeAsync() + { + if (groupEnumerator != null) + { + groupEnumerator.Dispose(); + } + + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask.NetCore/Linq/Join.cs index 1b42e2d..ceebbc8 100644 --- a/src/UniTask.NetCore/Linq/Join.cs +++ b/src/UniTask.NetCore/Linq/Join.cs @@ -154,7 +154,7 @@ namespace Cysharp.Threading.Tasks.Linq { try { - lookup = await inner.ToLookupAsync(innerKeySelector, cancellationToken); + lookup = await inner.ToLookupAsync(innerKeySelector, comparer, cancellationToken); enumerator = outer.GetAsyncEnumerator(cancellationToken); } catch (Exception ex) @@ -179,6 +179,7 @@ namespace Cysharp.Threading.Tasks.Linq } else { + valueEnumerator.Dispose(); valueEnumerator = null; } } @@ -342,7 +343,7 @@ namespace Cysharp.Threading.Tasks.Linq { try { - lookup = await inner.ToLookupAwaitAsync(innerKeySelector, cancellationToken); + lookup = await inner.ToLookupAwaitAsync(innerKeySelector, comparer, cancellationToken); enumerator = outer.GetAsyncEnumerator(cancellationToken); } catch (Exception ex) @@ -375,6 +376,7 @@ namespace Cysharp.Threading.Tasks.Linq } else { + valueEnumerator.Dispose(); valueEnumerator = null; } } @@ -568,7 +570,7 @@ namespace Cysharp.Threading.Tasks.Linq { try { - lookup = await inner.ToLookupAwaitWithCancellationAsync(innerKeySelector, cancellationToken: cancellationToken); + lookup = await inner.ToLookupAwaitWithCancellationAsync(innerKeySelector, comparer, cancellationToken: cancellationToken); enumerator = outer.GetAsyncEnumerator(cancellationToken); } catch (Exception ex) @@ -601,6 +603,7 @@ namespace Cysharp.Threading.Tasks.Linq } else { + valueEnumerator.Dispose(); valueEnumerator = null; } } diff --git a/src/UniTask.NetCore/Linq/ToLookup.cs b/src/UniTask.NetCore/Linq/ToLookup.cs index dfd9faa..c93944b 100644 --- a/src/UniTask.NetCore/Linq/ToLookup.cs +++ b/src/UniTask.NetCore/Linq/ToLookup.cs @@ -514,7 +514,7 @@ namespace Cysharp.Threading.Tasks.Linq } } - class Grouping : IGrouping + class Grouping : IGrouping // , IUniTaskAsyncGrouping { readonly List elements; @@ -539,6 +539,11 @@ namespace Cysharp.Threading.Tasks.Linq { return elements.GetEnumerator(); } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return this.ToUniTaskAsyncEnumerable().GetAsyncEnumerator(cancellationToken); + } } } } \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index 840e767..df91ad8 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -30,125 +30,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) { diff --git a/src/UniTask.NetCoreSandbox/Program.cs b/src/UniTask.NetCoreSandbox/Program.cs index f9deafb..24807f2 100644 --- a/src/UniTask.NetCoreSandbox/Program.cs +++ b/src/UniTask.NetCoreSandbox/Program.cs @@ -52,6 +52,8 @@ namespace NetCoreSandbox } + // AsyncEnumerable.Range(1, 10).GroupBy(x=>x).Select(x=>x.first + //Enumerable.Range(1,10).ToHashSet( diff --git a/src/UniTask.NetCoreTests/Linq/Joins.cs b/src/UniTask.NetCoreTests/Linq/Joins.cs index bfd1099..bc276e0 100644 --- a/src/UniTask.NetCoreTests/Linq/Joins.cs +++ b/src/UniTask.NetCoreTests/Linq/Joins.cs @@ -112,5 +112,78 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await ys); } } + + + [Fact] + public async Task GroupBy() + { + var arr = new[] { 1, 4, 10, 10, 4, 5, 10, 9 }; + { + var xs = await arr.ToUniTaskAsyncEnumerable().GroupBy(x => x).ToArrayAsync(); + var ys = arr.GroupBy(x => x).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + + { + var xs = await arr.ToUniTaskAsyncEnumerable().GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArrayAsync(); + var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().BeEquivalentTo(ys.OrderBy(x => x.key).SelectMany(x => x.Item2)); + } + + { + var xs = await arr.ToUniTaskAsyncEnumerable().GroupByAwait(x => RandomRun(x)).ToArrayAsync(); + var ys = arr.GroupBy(x => x).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + + { + var xs = await arr.ToUniTaskAsyncEnumerable().GroupByAwait(x => RandomRun(x), (key, xs) => RandomRun((key, xs.ToArray()))).ToArrayAsync(); + var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().BeEquivalentTo(ys.OrderBy(x => x.key).SelectMany(x => x.Item2)); + } + + { + var xs = await arr.ToUniTaskAsyncEnumerable().GroupByAwaitWithCancellation((x, _) => RandomRun(x)).ToArrayAsync(); + var ys = arr.GroupBy(x => x).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.OrderBy(x => x.Key).Should().BeEquivalentTo(ys.OrderBy(x => x.Key)); + } + + { + var xs = await arr.ToUniTaskAsyncEnumerable().GroupByAwaitWithCancellation((x, _) => RandomRun(x), (key, xs, _) => RandomRun((key, xs.ToArray()))).ToArrayAsync(); + var ys = arr.GroupBy(x => x, (key, xs) => (key, xs.ToArray())).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.OrderBy(x => x.key).SelectMany(x => x.Item2).Should().BeEquivalentTo(ys.OrderBy(x => x.key).SelectMany(x => x.Item2)); + } + } + + + + + [Fact] + public async Task GroupByThrow() + { + var arr = new[] { 1, 4, 10, 10, 4, 5, 10, 9 }; + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.GroupBy(x => x).ToArrayAsync(); + var ys = item.GroupByAwait(x => RandomRun(x)).ToArrayAsync(); + var zs = item.GroupByAwaitWithCancellation((x, _) => RandomRun(x)).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + await Assert.ThrowsAsync(async () => await zs); + } + } } } From 7298686d5ab0699d31beb8a525b51d86c11bad5a Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 00:38:06 +0900 Subject: [PATCH 25/31] Join, GroupBy, GroupJoin --- src/UniTask.NetCore/IAsyncEnumerable.cs | 9 +- src/UniTask.NetCore/Linq/GroupBy.cs | 84 + src/UniTask.NetCore/Linq/GroupJoin.cs | 1373 ++++++++--------- src/UniTask.NetCore/Linq/Join.cs | 3 + src/UniTask.NetCore/Linq/OrderBy.cs | 910 ++--------- src/UniTask.NetCore/Linq/OrderByDescending.cs | 775 ---------- src/UniTask.NetCore/Linq/ThenBy.cs | 775 ---------- src/UniTask.NetCore/Linq/ThenByDescending.cs | 775 ---------- src/UniTask.NetCore/Linq/ToLookup.cs | 5 + src/UniTask.NetCore/Linq/_FileMaker.cs | 36 - src/UniTask.NetCoreTests/Linq/Joins.cs | 64 + 11 files changed, 904 insertions(+), 3905 deletions(-) delete mode 100644 src/UniTask.NetCore/Linq/OrderByDescending.cs delete mode 100644 src/UniTask.NetCore/Linq/ThenBy.cs delete mode 100644 src/UniTask.NetCore/Linq/ThenByDescending.cs diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask.NetCore/IAsyncEnumerable.cs index 917c521..757333d 100644 --- a/src/UniTask.NetCore/IAsyncEnumerable.cs +++ b/src/UniTask.NetCore/IAsyncEnumerable.cs @@ -1,4 +1,6 @@ -using System.Runtime.InteropServices; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Threading; namespace Cysharp.Threading.Tasks @@ -19,6 +21,11 @@ namespace Cysharp.Threading.Tasks UniTask DisposeAsync(); } + public interface IUniTaskOrderedAsyncEnumerable : IUniTaskAsyncEnumerable + { + IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func keySelector, IComparer comparer, bool descending); + } + //public interface IUniTaskAsyncGrouping : IUniTaskAsyncEnumerable //{ // TKey Key { get; } diff --git a/src/UniTask.NetCore/Linq/GroupBy.cs b/src/UniTask.NetCore/Linq/GroupBy.cs index 5da393b..d3fb03c 100644 --- a/src/UniTask.NetCore/Linq/GroupBy.cs +++ b/src/UniTask.NetCore/Linq/GroupBy.cs @@ -12,40 +12,68 @@ namespace Cysharp.Threading.Tasks.Linq public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); return new GroupBy(source, keySelector, x => x, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupBy(source, keySelector, x => x, comparer); } public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); return new GroupBy(source, keySelector, elementSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable> GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupBy(source, keySelector, elementSelector, comparer); } public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); return new GroupBy(source, keySelector, x => x, resultSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func, TResult> resultSelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupBy(source, keySelector, x => x, resultSelector, comparer); } public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, 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(source, keySelector, elementSelector, resultSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable GroupBy(this IUniTaskAsyncEnumerable source, Func keySelector, Func elementSelector, Func, TResult> resultSelector, IEqualityComparer 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(source, keySelector, elementSelector, resultSelector, comparer); } @@ -53,41 +81,69 @@ namespace Cysharp.Threading.Tasks.Linq public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), EqualityComparer.Default); } public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), comparer); } public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); return new GroupByAwait(source, keySelector, elementSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable> GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupByAwait(source, keySelector, elementSelector, comparer); } public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), resultSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); return new GroupByAwait(source, keySelector, elementSelector, resultSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupByAwait(source, keySelector, x => UniTask.FromResult(x), resultSelector, comparer); } public static IUniTaskAsyncEnumerable GroupByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, UniTask> resultSelector, IEqualityComparer 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(source, keySelector, elementSelector, resultSelector, comparer); } @@ -95,41 +151,69 @@ namespace Cysharp.Threading.Tasks.Linq public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), EqualityComparer.Default); } public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), comparer); } public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable> GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, comparer); } public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), resultSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(elementSelector, nameof(elementSelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); return new GroupByAwaitWithCancellation(source, keySelector, elementSelector, resultSelector, EqualityComparer.Default); } public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); return new GroupByAwaitWithCancellation(source, keySelector, (x, _) => UniTask.FromResult(x), resultSelector, comparer); } public static IUniTaskAsyncEnumerable GroupByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, Func> elementSelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer 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(source, keySelector, elementSelector, resultSelector, comparer); } } diff --git a/src/UniTask.NetCore/Linq/GroupJoin.cs b/src/UniTask.NetCore/Linq/GroupJoin.cs index ddaeaf7..1978ac2 100644 --- a/src/UniTask.NetCore/Linq/GroupJoin.cs +++ b/src/UniTask.NetCore/Linq/GroupJoin.cs @@ -1,775 +1,606 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks.Internal; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class GroupJoin + public static partial class UniTaskAsyncEnumerable { + public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector, IEqualityComparer 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(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector) + { + Error.ThrowArgumentNullException(outer, nameof(outer)); + Error.ThrowArgumentNullException(inner, nameof(inner)); + Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector)); + Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); + + return new GroupJoinWithCancellationAwait(outer, inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable GroupJoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(outer, nameof(outer)); + Error.ThrowArgumentNullException(inner, nameof(inner)); + Error.ThrowArgumentNullException(outerKeySelector, nameof(outerKeySelector)); + Error.ThrowArgumentNullException(innerKeySelector, nameof(innerKeySelector)); + Error.ThrowArgumentNullException(resultSelector, nameof(resultSelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new GroupJoinWithCancellationAwait(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer); + } + } - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + internal sealed class GroupJoin : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func outerKeySelector; + readonly Func innerKeySelector; + readonly Func, TResult> resultSelector; + readonly IEqualityComparer comparer; + + public GroupJoin(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func outerKeySelector; + readonly Func innerKeySelector; + readonly Func, TResult> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + ILookup lookup; + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + + + public Enumerator(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (lookup == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateLookup() + { + try + { + lookup = await inner.ToLookupAsync(innerKeySelector, comparer, cancellationToken); + enumerator = outer.GetAsyncEnumerator(cancellationToken); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + SourceMoveNext(); + } + + void SourceMoveNext() + { + try + { + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + MoveNextCore(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + var outer = self.enumerator.Current; + var key = self.outerKeySelector(outer); + var values = self.lookup[key]; + + self.Current = self.resultSelector(outer, values); + self.completionSource.TrySetResult(true); + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } + + internal sealed class GroupJoinAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func, UniTask> resultSelector; + readonly IEqualityComparer comparer; + + public GroupJoinAwait(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + readonly static Action ResultSelectCoreDelegate = ResultSelectCore; + readonly static Action OuterKeySelectCoreDelegate = OuterKeySelectCore; + + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func, UniTask> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + ILookup lookup; + IUniTaskAsyncEnumerator enumerator; + TOuter outerValue; + UniTask.Awaiter awaiter; + UniTask.Awaiter outerKeyAwaiter; + UniTask.Awaiter resultAwaiter; + + + public Enumerator(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (lookup == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateLookup() + { + try + { + lookup = await inner.ToLookupAwaitAsync(innerKeySelector, comparer, cancellationToken); + enumerator = outer.GetAsyncEnumerator(cancellationToken); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + SourceMoveNext(); + } + + void SourceMoveNext() + { + try + { + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + MoveNextCore(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + try + { + + self.outerValue = self.enumerator.Current; + self.outerKeyAwaiter = self.outerKeySelector(self.outerValue).GetAwaiter(); + if (self.outerKeyAwaiter.IsCompleted) + { + OuterKeySelectCore(self); + } + else + { + self.outerKeyAwaiter.SourceOnCompleted(OuterKeySelectCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void OuterKeySelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.outerKeyAwaiter, out var result)) + { + try + { + var values = self.lookup[result]; + self.resultAwaiter = self.resultSelector(self.outerValue, values).GetAwaiter(); + if (self.resultAwaiter.IsCompleted) + { + ResultSelectCore(self); + } + else + { + self.resultAwaiter.SourceOnCompleted(ResultSelectCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + } + } + + static void ResultSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultAwaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } + + internal sealed class GroupJoinWithCancellationAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func, CancellationToken, UniTask> resultSelector; + readonly IEqualityComparer comparer; + + public GroupJoinWithCancellationAwait(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + readonly static Action ResultSelectCoreDelegate = ResultSelectCore; + readonly static Action OuterKeySelectCoreDelegate = OuterKeySelectCore; + + readonly IUniTaskAsyncEnumerable outer; + readonly IUniTaskAsyncEnumerable inner; + readonly Func> outerKeySelector; + readonly Func> innerKeySelector; + readonly Func, CancellationToken, UniTask> resultSelector; + readonly IEqualityComparer comparer; + CancellationToken cancellationToken; + + ILookup lookup; + IUniTaskAsyncEnumerator enumerator; + TOuter outerValue; + UniTask.Awaiter awaiter; + UniTask.Awaiter outerKeyAwaiter; + UniTask.Awaiter resultAwaiter; + + + public Enumerator(IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer, CancellationToken cancellationToken) + { + this.outer = outer; + this.inner = inner; + this.outerKeySelector = outerKeySelector; + this.innerKeySelector = innerKeySelector; + this.resultSelector = resultSelector; + this.comparer = comparer; + this.cancellationToken = cancellationToken; + } + + public TResult Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + completionSource.Reset(); + + if (lookup == null) + { + CreateLookup().Forget(); + } + else + { + SourceMoveNext(); + } + return new UniTask(this, completionSource.Version); + } + + async UniTaskVoid CreateLookup() + { + try + { + lookup = await inner.ToLookupAwaitWithCancellationAsync(innerKeySelector, comparer, cancellationToken); + enumerator = outer.GetAsyncEnumerator(cancellationToken); + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + SourceMoveNext(); + } + + void SourceMoveNext() + { + try + { + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + MoveNextCore(this); + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + try + { + + self.outerValue = self.enumerator.Current; + self.outerKeyAwaiter = self.outerKeySelector(self.outerValue, self.cancellationToken).GetAwaiter(); + if (self.outerKeyAwaiter.IsCompleted) + { + OuterKeySelectCore(self); + } + else + { + self.outerKeyAwaiter.SourceOnCompleted(OuterKeySelectCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + } + else + { + self.completionSource.TrySetResult(false); + } + } + } + + static void OuterKeySelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.outerKeyAwaiter, out var result)) + { + try + { + var values = self.lookup[result]; + self.resultAwaiter = self.resultSelector(self.outerValue, values, self.cancellationToken).GetAwaiter(); + if (self.resultAwaiter.IsCompleted) + { + ResultSelectCore(self); + } + else + { + self.resultAwaiter.SourceOnCompleted(ResultSelectCoreDelegate, self); + } + } + catch (Exception ex) + { + self.completionSource.TrySetException(ex); + } + } + } + + static void ResultSelectCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.resultAwaiter, out var result)) + { + self.Current = result; + self.completionSource.TrySetResult(true); + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask.NetCore/Linq/Join.cs index ceebbc8..bfdf779 100644 --- a/src/UniTask.NetCore/Linq/Join.cs +++ b/src/UniTask.NetCore/Linq/Join.cs @@ -129,6 +129,7 @@ namespace Cysharp.Threading.Tasks.Linq this.outerKeySelector = outerKeySelector; this.innerKeySelector = innerKeySelector; this.resultSelector = resultSelector; + this.comparer = comparer; this.cancellationToken = cancellationToken; } @@ -318,6 +319,7 @@ namespace Cysharp.Threading.Tasks.Linq this.outerKeySelector = outerKeySelector; this.innerKeySelector = innerKeySelector; this.resultSelector = resultSelector; + this.comparer = comparer; this.cancellationToken = cancellationToken; } @@ -545,6 +547,7 @@ namespace Cysharp.Threading.Tasks.Linq this.outerKeySelector = outerKeySelector; this.innerKeySelector = innerKeySelector; this.resultSelector = resultSelector; + this.comparer = comparer; this.cancellationToken = cancellationToken; } diff --git a/src/UniTask.NetCore/Linq/OrderBy.cs b/src/UniTask.NetCore/Linq/OrderBy.cs index e661ad2..8bca66f 100644 --- a/src/UniTask.NetCore/Linq/OrderBy.cs +++ b/src/UniTask.NetCore/Linq/OrderBy.cs @@ -1,775 +1,141 @@ -namespace Cysharp.Threading.Tasks.Linq +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Internal; +using Cysharp.Threading.Tasks.Linq; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace Cysharp.Threading.Tasks.Linq { - internal sealed class OrderBy + public static partial class UniTaskAsyncEnumerable { + #region OrderBy_OrderByDescending + + public static IUniTaskOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + #endregion + + #region ThenBy_ThenByDescending + + public static IUniTaskOrderedAsyncEnumerable ThenBy(this IUniTaskOrderedAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenBy(this IUniTaskOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByDescending(this IUniTaskOrderedAsyncEnumerable source, Func keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByDescending(this IUniTaskOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) + { + throw new NotImplementedException(); + } + + public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) + { + throw new NotImplementedException(); + } + + #endregion } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +} \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/OrderByDescending.cs b/src/UniTask.NetCore/Linq/OrderByDescending.cs deleted file mode 100644 index 309a0f2..0000000 --- a/src/UniTask.NetCore/Linq/OrderByDescending.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class OrderByDescending - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/ThenBy.cs b/src/UniTask.NetCore/Linq/ThenBy.cs deleted file mode 100644 index 71dfe81..0000000 --- a/src/UniTask.NetCore/Linq/ThenBy.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class ThenBy - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/ThenByDescending.cs b/src/UniTask.NetCore/Linq/ThenByDescending.cs deleted file mode 100644 index aadc421..0000000 --- a/src/UniTask.NetCore/Linq/ThenByDescending.cs +++ /dev/null @@ -1,775 +0,0 @@ -namespace Cysharp.Threading.Tasks.Linq -{ - internal sealed class ThenByDescending - { - } - - -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/UniTask.NetCore/Linq/ToLookup.cs b/src/UniTask.NetCore/Linq/ToLookup.cs index c93944b..9cccec0 100644 --- a/src/UniTask.NetCore/Linq/ToLookup.cs +++ b/src/UniTask.NetCore/Linq/ToLookup.cs @@ -544,6 +544,11 @@ namespace Cysharp.Threading.Tasks.Linq { return this.ToUniTaskAsyncEnumerable().GetAsyncEnumerator(cancellationToken); } + + public override string ToString() + { + return "Key: " + Key + ", Count: " + elements.Count; + } } } } \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index df91ad8..bd80f4d 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -31,35 +31,6 @@ namespace ___Dummy - public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupJoin(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func outerKeySelector, Func innerKeySelector, Func, TResult> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupJoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupJoinAwait(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, UniTask> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupJoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector) - { - throw new NotImplementedException(); - } - - public static IUniTaskAsyncEnumerable GroupJoinAwaitWithCancellation(this IUniTaskAsyncEnumerable outer, IUniTaskAsyncEnumerable inner, Func> outerKeySelector, Func> innerKeySelector, Func, CancellationToken, UniTask> resultSelector, IEqualityComparer comparer) - { - throw new NotImplementedException(); - } @@ -125,13 +96,6 @@ namespace ___Dummy throw new NotImplementedException(); } - - - - - - - public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector) { throw new NotImplementedException(); diff --git a/src/UniTask.NetCoreTests/Linq/Joins.cs b/src/UniTask.NetCoreTests/Linq/Joins.cs index bc276e0..48fd120 100644 --- a/src/UniTask.NetCoreTests/Linq/Joins.cs +++ b/src/UniTask.NetCoreTests/Linq/Joins.cs @@ -185,5 +185,69 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await zs); } } + + + + [Fact] + public async Task GroupJoin() + { + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }; + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }; + + { + var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoin(inner.ToUniTaskAsyncEnumerable(), x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArrayAsync(); + var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoinAwait(inner.ToUniTaskAsyncEnumerable(), x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun((x, string.Join(", ", y)))).ToArrayAsync(); + var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await outer.ToUniTaskAsyncEnumerable().GroupJoinAwaitWithCancellation(inner.ToUniTaskAsyncEnumerable(), (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun((x, string.Join(", ", y)))).ToArrayAsync(); + var ys = outer.GroupJoin(inner, x => x, x => x, (x, y) => (x, string.Join(", ", y))).ToArray(); + + xs.Length.Should().Be(ys.Length); + xs.Should().BeEquivalentTo(ys); + } + } + + + [Fact] + public async Task GroupJoinThrow() + { + + var outer = new[] { 1, 2, 4, 5, 8, 10, 14, 4, 8, 1, 2, 10 }.ToUniTaskAsyncEnumerable(); + var inner = new[] { 1, 2, 1, 2, 1, 14, 2 }.ToUniTaskAsyncEnumerable(); + + foreach (var item in UniTaskTestException.Throws()) + { + { + var xs = item.GroupJoin(outer, x => x, x => x, (x, y) => x).ToArrayAsync(); + var ys = inner.GroupJoin(item, x => x, x => x, (x, y) => x).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + { + var xs = item.GroupJoinAwait(outer, x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun(x)).ToArrayAsync(); + var ys = inner.GroupJoinAwait(item, x => RandomRun(x), x => RandomRun(x), (x, y) => RandomRun(x)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + { + var xs = item.GroupJoinAwaitWithCancellation(outer, (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun(x)).ToArrayAsync(); + var ys = inner.GroupJoinAwaitWithCancellation(item, (x, _) => RandomRun(x), (x, _) => RandomRun(x), (x, y, _) => RandomRun(x)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + } + } + + } } From 85dc70a3ab28eac35df15ef66ffdf7b60f20759b Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 02:21:06 +0900 Subject: [PATCH 26/31] OrderBy --- src/UniTask.NetCore/IAsyncEnumerable.cs | 2 + src/UniTask.NetCore/Linq/OrderBy.cs | 467 ++++++++++++++++++++++-- src/UniTask.NetCore/Linq/_FileMaker.cs | 120 +----- src/UniTask.NetCoreTests/Linq/Sort.cs | 221 +++++++++++ 4 files changed, 665 insertions(+), 145 deletions(-) create mode 100644 src/UniTask.NetCoreTests/Linq/Sort.cs diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask.NetCore/IAsyncEnumerable.cs index 757333d..6807908 100644 --- a/src/UniTask.NetCore/IAsyncEnumerable.cs +++ b/src/UniTask.NetCore/IAsyncEnumerable.cs @@ -24,6 +24,8 @@ namespace Cysharp.Threading.Tasks public interface IUniTaskOrderedAsyncEnumerable : IUniTaskAsyncEnumerable { IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func keySelector, IComparer comparer, bool descending); + IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func> keySelector, IComparer comparer, bool descending); + IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func> keySelector, IComparer comparer, bool descending); } //public interface IUniTaskAsyncGrouping : IUniTaskAsyncEnumerable diff --git a/src/UniTask.NetCore/Linq/OrderBy.cs b/src/UniTask.NetCore/Linq/OrderBy.cs index 8bca66f..740c0e2 100644 --- a/src/UniTask.NetCore/Linq/OrderBy.cs +++ b/src/UniTask.NetCore/Linq/OrderBy.cs @@ -1,10 +1,8 @@ using Cysharp.Threading.Tasks; using Cysharp.Threading.Tasks.Internal; -using Cysharp.Threading.Tasks.Linq; using System; using System.Collections.Generic; using System.Threading; -using System.Threading.Tasks; namespace Cysharp.Threading.Tasks.Linq { @@ -14,62 +12,104 @@ namespace Cysharp.Threading.Tasks.Linq public static IUniTaskOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return new OrderedAsyncEnumerable(source, keySelector, Comparer.Default, false, null); } public static IUniTaskOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new OrderedAsyncEnumerable(source, keySelector, comparer, false, null); } public static IUniTaskOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return new OrderedAsyncEnumerableAwait(source, keySelector, Comparer.Default, false, null); } public static IUniTaskOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new OrderedAsyncEnumerableAwait(source, keySelector, comparer, false, null); } public static IUniTaskOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return new OrderedAsyncEnumerableAwaitWithCancellation(source, keySelector, Comparer.Default, false, null); } public static IUniTaskOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new OrderedAsyncEnumerableAwaitWithCancellation(source, keySelector, comparer, false, null); } public static IUniTaskOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return new OrderedAsyncEnumerable(source, keySelector, Comparer.Default, true, null); } public static IUniTaskOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new OrderedAsyncEnumerable(source, keySelector, comparer, true, null); } public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return new OrderedAsyncEnumerableAwait(source, keySelector, Comparer.Default, true, null); } public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new OrderedAsyncEnumerableAwait(source, keySelector, comparer, true, null); } public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return new OrderedAsyncEnumerableAwaitWithCancellation(source, keySelector, Comparer.Default, true, null); } public static IUniTaskOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new OrderedAsyncEnumerableAwaitWithCancellation(source, keySelector, comparer, true, null); } #endregion @@ -78,64 +118,439 @@ namespace Cysharp.Threading.Tasks.Linq public static IUniTaskOrderedAsyncEnumerable ThenBy(this IUniTaskOrderedAsyncEnumerable source, Func keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return source.CreateOrderedEnumerable(keySelector, Comparer.Default, false); } public static IUniTaskOrderedAsyncEnumerable ThenBy(this IUniTaskOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return source.CreateOrderedEnumerable(keySelector, comparer, false); } public static IUniTaskOrderedAsyncEnumerable ThenByAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return source.CreateOrderedEnumerable(keySelector, Comparer.Default, false); } public static IUniTaskOrderedAsyncEnumerable ThenByAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return source.CreateOrderedEnumerable(keySelector, comparer, false); } public static IUniTaskOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return source.CreateOrderedEnumerable(keySelector, Comparer.Default, false); } public static IUniTaskOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return source.CreateOrderedEnumerable(keySelector, comparer, false); } public static IUniTaskOrderedAsyncEnumerable ThenByDescending(this IUniTaskOrderedAsyncEnumerable source, Func keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return source.CreateOrderedEnumerable(keySelector, Comparer.Default, true); } public static IUniTaskOrderedAsyncEnumerable ThenByDescending(this IUniTaskOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return source.CreateOrderedEnumerable(keySelector, comparer, true); } public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return source.CreateOrderedEnumerable(keySelector, Comparer.Default, true); } public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwait(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return source.CreateOrderedEnumerable(keySelector, comparer, true); } public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector) { - throw new NotImplementedException(); + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + + return source.CreateOrderedEnumerable(keySelector, Comparer.Default, true); } public static IUniTaskOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IUniTaskOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) { - throw new NotImplementedException(); + 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 + { + internal abstract UniTask ComputeKeysAsync(TElement[] elements, int count); + + internal abstract int CompareKeys(int index1, int index2); + + internal async UniTask 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 : AsyncEnumerableSorter + { + readonly Func keySelector; + readonly IComparer comparer; + readonly bool descending; + readonly AsyncEnumerableSorter next; + TKey[] keys; + + internal SyncSelectorAsyncEnumerableSorter(Func keySelector, IComparer comparer, bool descending, AsyncEnumerableSorter 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 : AsyncEnumerableSorter + { + readonly Func> keySelector; + readonly IComparer comparer; + readonly bool descending; + readonly AsyncEnumerableSorter next; + TKey[] keys; + + internal AsyncSelectorEnumerableSorter(Func> keySelector, IComparer comparer, bool descending, AsyncEnumerableSorter 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 : AsyncEnumerableSorter + { + readonly Func> keySelector; + readonly IComparer comparer; + readonly bool descending; + readonly AsyncEnumerableSorter next; + CancellationToken cancellationToken; + TKey[] keys; + + internal AsyncSelectorWithCancellationEnumerableSorter(Func> keySelector, IComparer comparer, bool descending, AsyncEnumerableSorter 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 : IUniTaskOrderedAsyncEnumerable + { + protected readonly IUniTaskAsyncEnumerable source; + + public OrderedAsyncEnumerable(IUniTaskAsyncEnumerable source) + { + this.source = source; + } + + public IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func keySelector, IComparer comparer, bool descending) + { + return new OrderedAsyncEnumerable(source, keySelector, comparer, descending, this); + } + + public IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func> keySelector, IComparer comparer, bool descending) + { + return new OrderedAsyncEnumerableAwait(source, keySelector, comparer, descending, this); + } + + public IUniTaskOrderedAsyncEnumerable CreateOrderedEnumerable(Func> keySelector, IComparer comparer, bool descending) + { + return new OrderedAsyncEnumerableAwaitWithCancellation(source, keySelector, comparer, descending, this); + } + + internal abstract AsyncEnumerableSorter GetAsyncEnumerableSorter(AsyncEnumerableSorter next, CancellationToken cancellationToken); + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(this, cancellationToken); + } + + class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator + { + protected readonly OrderedAsyncEnumerable parent; + CancellationToken cancellationToken; + TElement[] buffer; + int[] map; + int index; + + public Enumerator(OrderedAsyncEnumerable parent, CancellationToken cancellationToken) + { + this.parent = parent; + this.cancellationToken = cancellationToken; + } + + public TElement Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (map == null) + { + completionSource.Reset(); + CreateSortSource().Forget(); + return new UniTask(this, completionSource.Version); + } + + if (index < buffer.Length) + { + Current = buffer[map[index++]]; + return CompletedTasks.True; + } + else + { + return CompletedTasks.False; + } + } + + async UniTaskVoid CreateSortSource() + { + try + { + buffer = await parent.source.ToArrayAsync(); + if (buffer.Length == 0) + { + completionSource.TrySetResult(false); + return; + } + + var sorter = parent.GetAsyncEnumerableSorter(null, cancellationToken); + map = await sorter.SortAsync(buffer, buffer.Length); + sorter = null; + + // set first value + Current = buffer[map[index++]]; + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + return; + } + + completionSource.TrySetResult(true); + } + + public UniTask DisposeAsync() + { + return default; + } + } + } + + internal class OrderedAsyncEnumerable : OrderedAsyncEnumerable + { + readonly Func keySelector; + readonly IComparer comparer; + readonly bool descending; + readonly OrderedAsyncEnumerable parent; + + public OrderedAsyncEnumerable(IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer, bool descending, OrderedAsyncEnumerable parent) + : base(source) + { + this.keySelector = keySelector; + this.comparer = comparer; + this.descending = descending; + this.parent = parent; + } + + internal override AsyncEnumerableSorter GetAsyncEnumerableSorter(AsyncEnumerableSorter next, CancellationToken cancellationToken) + { + AsyncEnumerableSorter sorter = new SyncSelectorAsyncEnumerableSorter(keySelector, comparer, descending, next); + if (parent != null) sorter = parent.GetAsyncEnumerableSorter(sorter, cancellationToken); + return sorter; + } + } + + internal class OrderedAsyncEnumerableAwait : OrderedAsyncEnumerable + { + readonly Func> keySelector; + readonly IComparer comparer; + readonly bool descending; + readonly OrderedAsyncEnumerable parent; + + public OrderedAsyncEnumerableAwait(IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer, bool descending, OrderedAsyncEnumerable parent) + : base(source) + { + this.keySelector = keySelector; + this.comparer = comparer; + this.descending = descending; + this.parent = parent; + } + + internal override AsyncEnumerableSorter GetAsyncEnumerableSorter(AsyncEnumerableSorter next, CancellationToken cancellationToken) + { + AsyncEnumerableSorter sorter = new AsyncSelectorEnumerableSorter(keySelector, comparer, descending, next); + if (parent != null) sorter = parent.GetAsyncEnumerableSorter(sorter, cancellationToken); + return sorter; + } + } + + internal class OrderedAsyncEnumerableAwaitWithCancellation : OrderedAsyncEnumerable + { + readonly Func> keySelector; + readonly IComparer comparer; + readonly bool descending; + readonly OrderedAsyncEnumerable parent; + + public OrderedAsyncEnumerableAwaitWithCancellation(IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer, bool descending, OrderedAsyncEnumerable parent) + : base(source) + { + this.keySelector = keySelector; + this.comparer = comparer; + this.descending = descending; + this.parent = parent; + } + + internal override AsyncEnumerableSorter GetAsyncEnumerableSorter(AsyncEnumerableSorter next, CancellationToken cancellationToken) + { + AsyncEnumerableSorter sorter = new AsyncSelectorWithCancellationEnumerableSorter(keySelector, comparer, descending, next, cancellationToken); + if (parent != null) sorter = parent.GetAsyncEnumerableSorter(sorter, cancellationToken); + return sorter; + } + } } \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs index bd80f4d..4f1b224 100644 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ b/src/UniTask.NetCore/Linq/_FileMaker.cs @@ -36,125 +36,7 @@ namespace ___Dummy - public static IOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderBy(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByDescending(this IUniTaskAsyncEnumerable source, Func keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByDescendingAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable OrderByDescendingAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenBy(this IOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByAwait(this IOrderedAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByAwait(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByDescending(this IOrderedAsyncEnumerable source, Func keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByDescending(this IOrderedAsyncEnumerable source, Func keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByDescendingAwait(this IOrderedAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByDescendingAwait(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector) - { - throw new NotImplementedException(); - } - - public static IOrderedAsyncEnumerable ThenByDescendingAwaitWithCancellation(this IOrderedAsyncEnumerable source, Func> keySelector, IComparer comparer) - { - throw new NotImplementedException(); - } + diff --git a/src/UniTask.NetCoreTests/Linq/Sort.cs b/src/UniTask.NetCoreTests/Linq/Sort.cs new file mode 100644 index 0000000..673e697 --- /dev/null +++ b/src/UniTask.NetCoreTests/Linq/Sort.cs @@ -0,0 +1,221 @@ +using Cysharp.Threading.Tasks; +using Cysharp.Threading.Tasks.Linq; +using FluentAssertions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reactive.Concurrency; +using System.Reactive.Linq; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + + +namespace NetCoreTests.Linq +{ + public class SortCheck + { + public int Age { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + + public override string ToString() + { + return (Age, FirstName, LastName).ToString(); + } + } + + public class Sort + { + static int rd; + + static UniTask RandomRun(T value) + { + if (Interlocked.Increment(ref rd) % 2 == 0) + { + return UniTask.Run(() => value); + } + else + { + return UniTask.FromResult(value); + } + } + static UniTask RandomRun(T value, CancellationToken ct) + { + if (Interlocked.Increment(ref rd) % 2 == 0) + { + return UniTask.Run(() => value); + } + else + { + return UniTask.FromResult(value); + } + } + + [Fact] + public async Task OrderBy() + { + var array = new[] { 1, 99, 32, 4, 536, 7, 8 }; + { + var xs = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x).ToArrayAsync(); + var ys = array.OrderBy(x => x).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x).ToArrayAsync(); + var ys = array.OrderByDescending(x => x).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().OrderByAwait(RandomRun).ToArrayAsync(); + var ys = array.OrderBy(x => x).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(RandomRun).ToArrayAsync(); + var ys = array.OrderByDescending(x => x).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation(RandomRun).ToArrayAsync(); + var ys = array.OrderBy(x => x).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + { + var xs = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation(RandomRun).ToArrayAsync(); + var ys = array.OrderByDescending(x => x).ToArray(); + xs.Should().BeEquivalentTo(ys); + } + } + + [Fact] + public async Task ThenBy() + { + var array = new[] + { + new SortCheck { Age = 99, FirstName = "ABC", LastName = "DEF" }, + new SortCheck { Age = 49, FirstName = "ABC", LastName = "DEF" }, + new SortCheck { Age = 49, FirstName = "ABC", LastName = "ZKH" }, + new SortCheck { Age = 12, FirstName = "ABC", LastName = "DEF" }, + new SortCheck { Age = 49, FirstName = "ABC", LastName = "MEF" }, + new SortCheck { Age = 12, FirstName = "QQQ", LastName = "DEF" }, + new SortCheck { Age = 19, FirstName = "ZKN", LastName = "DEF" }, + new SortCheck { Age = 39, FirstName = "APO", LastName = "REF" }, + new SortCheck { Age = 59, FirstName = "ABC", LastName = "DEF" }, + new SortCheck { Age = 99, FirstName = "DBC", LastName = "DEF" }, + new SortCheck { Age = 99, FirstName = "DBC", LastName = "MEF" }, + }; + { + var a = array.OrderBy(x => x.Age).ThenBy(x => x.FirstName).ThenBy(x => x.LastName).ToArray(); + var b = array.OrderBy(x => x.Age).ThenBy(x => x.FirstName).ThenByDescending(x => x.LastName).ToArray(); + var c = array.OrderBy(x => x.Age).ThenByDescending(x => x.FirstName).ThenBy(x => x.LastName).ToArray(); + var d = array.OrderBy(x => x.Age).ThenByDescending(x => x.FirstName).ThenByDescending(x => x.LastName).ToArray(); + var e = array.OrderByDescending(x => x.Age).ThenBy(x => x.FirstName).ThenBy(x => x.LastName).ToArray(); + var f = array.OrderByDescending(x => x.Age).ThenBy(x => x.FirstName).ThenByDescending(x => x.LastName).ToArray(); + var g = array.OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenBy(x => x.LastName).ToArray(); + var h = array.OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenByDescending(x => x.LastName).ToArray(); + + { + var a2 = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x.Age).ThenBy(x => x.FirstName).ThenBy(x => x.LastName).ToArrayAsync(); + var b2 = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x.Age).ThenBy(x => x.FirstName).ThenByDescending(x => x.LastName).ToArrayAsync(); + var c2 = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x.Age).ThenByDescending(x => x.FirstName).ThenBy(x => x.LastName).ToArrayAsync(); + var d2 = await array.ToUniTaskAsyncEnumerable().OrderBy(x => x.Age).ThenByDescending(x => x.FirstName).ThenByDescending(x => x.LastName).ToArrayAsync(); + var e2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenBy(x => x.FirstName).ThenBy(x => x.LastName).ToArrayAsync(); + var f2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenBy(x => x.FirstName).ThenByDescending(x => x.LastName).ToArrayAsync(); + var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenBy(x => x.LastName).ToArrayAsync(); + var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescending(x => x.Age).ThenByDescending(x => x.FirstName).ThenByDescending(x => x.LastName).ToArrayAsync(); + + a.Should().BeEquivalentTo(a2); + b.Should().BeEquivalentTo(b2); + c.Should().BeEquivalentTo(c2); + d.Should().BeEquivalentTo(d2); + e.Should().BeEquivalentTo(e2); + f.Should().BeEquivalentTo(f2); + g.Should().BeEquivalentTo(g2); + h.Should().BeEquivalentTo(h2); + } + { + var a2 = await array.ToUniTaskAsyncEnumerable().OrderByAwait(x => RandomRun(x.Age)).ThenByAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var b2 = await array.ToUniTaskAsyncEnumerable().OrderByAwait(x => RandomRun(x.Age)).ThenByAwait(x => RandomRun(x.FirstName)).ThenByDescendingAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var c2 = await array.ToUniTaskAsyncEnumerable().OrderByAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var d2 = await array.ToUniTaskAsyncEnumerable().OrderByAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByDescendingAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var e2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var f2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByAwait(x => RandomRun(x.FirstName)).ThenByDescendingAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwait(x => RandomRun(x.Age)).ThenByDescendingAwait(x => RandomRun(x.FirstName)).ThenByDescendingAwait(x => RandomRun(x.LastName)).ToArrayAsync(); + + a.Should().BeEquivalentTo(a2); + b.Should().BeEquivalentTo(b2); + c.Should().BeEquivalentTo(c2); + d.Should().BeEquivalentTo(d2); + e.Should().BeEquivalentTo(e2); + f.Should().BeEquivalentTo(f2); + g.Should().BeEquivalentTo(g2); + h.Should().BeEquivalentTo(h2); + } + { + var a2 = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var b2 = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var c2 = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var d2 = await array.ToUniTaskAsyncEnumerable().OrderByAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var e2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var f2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var g2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + var h2 = await array.ToUniTaskAsyncEnumerable().OrderByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.Age)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.FirstName)).ThenByDescendingAwaitWithCancellation((x, ct) => RandomRun(x.LastName)).ToArrayAsync(); + + a.Should().BeEquivalentTo(a2); + b.Should().BeEquivalentTo(b2); + c.Should().BeEquivalentTo(c2); + d.Should().BeEquivalentTo(d2); + e.Should().BeEquivalentTo(e2); + f.Should().BeEquivalentTo(f2); + g.Should().BeEquivalentTo(g2); + h.Should().BeEquivalentTo(h2); + } + } + } + + + [Fact] + public async Task Throws() + { + foreach (var item in UniTaskTestException.Throws()) + { + { + var a = item.OrderBy(x => x).ToArrayAsync(); + var b = item.OrderByDescending(x => x).ToArrayAsync(); + var c = item.OrderBy(x => x).ThenBy(x => x).ToArrayAsync(); + var d = item.OrderBy(x => x).ThenByDescending(x => x).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await a); + await Assert.ThrowsAsync(async () => await b); + await Assert.ThrowsAsync(async () => await c); + await Assert.ThrowsAsync(async () => await d); + } + { + var a = item.OrderByAwait(RandomRun).ToArrayAsync(); + var b = item.OrderByDescendingAwait(RandomRun).ToArrayAsync(); + var c = item.OrderByAwait(RandomRun).ThenByAwait(RandomRun).ToArrayAsync(); + var d = item.OrderByAwait(RandomRun).ThenByDescendingAwait(RandomRun).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await a); + await Assert.ThrowsAsync(async () => await b); + await Assert.ThrowsAsync(async () => await c); + await Assert.ThrowsAsync(async () => await d); + } + { + var a = item.OrderByAwaitWithCancellation(RandomRun).ToArrayAsync(); + var b = item.OrderByDescendingAwaitWithCancellation(RandomRun).ToArrayAsync(); + var c = item.OrderByAwaitWithCancellation(RandomRun).ThenByAwaitWithCancellation(RandomRun).ToArrayAsync(); + var d = item.OrderByAwaitWithCancellation(RandomRun).ThenByDescendingAwaitWithCancellation(RandomRun).ToArrayAsync(); + + await Assert.ThrowsAsync(async () => await a); + await Assert.ThrowsAsync(async () => await b); + await Assert.ThrowsAsync(async () => await c); + await Assert.ThrowsAsync(async () => await d); + } + } + + } + } +} From 57c414a6e09822f450a28a01b3cc7a1a0541872b Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 02:45:12 +0900 Subject: [PATCH 27/31] DistinctSelector --- .../Linq/AsyncEnumeratorBase.cs | 5 +- src/UniTask.NetCore/Linq/Distinct.cs | 205 +++++++++++++++++- src/UniTask.NetCore/Linq/_FileMaker.cs | 51 ----- src/UniTask.NetCoreTests/Linq/Sets.cs | 27 ++- 4 files changed, 228 insertions(+), 60 deletions(-) delete mode 100644 src/UniTask.NetCore/Linq/_FileMaker.cs diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs index b4b4493..3f3ba2f 100644 --- a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs +++ b/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs @@ -212,7 +212,7 @@ namespace Cysharp.Threading.Tasks.Linq protected abstract bool TrySetCurrentCore(TAwait awaitResult, out bool terminateIteration); // Util - protected TSource SourceCurrent => enumerator.Current; + protected TSource SourceCurrent { get; private set; } protected (bool waitCallback, bool requireNextIteration) ActionCompleted(bool trySetCurrentResult, out bool moveNextResult) { @@ -287,7 +287,8 @@ namespace Cysharp.Threading.Tasks.Linq { if (sourceHasCurrent) { - var task = TransformAsync(enumerator.Current); + SourceCurrent = enumerator.Current; + var task = TransformAsync(SourceCurrent); if (UnwarapTask(task, out var taskResult)) { var currentResult = TrySetCurrentCore(taskResult, out var terminateIteration); diff --git a/src/UniTask.NetCore/Linq/Distinct.cs b/src/UniTask.NetCore/Linq/Distinct.cs index fc4aa48..2868fcd 100644 --- a/src/UniTask.NetCore/Linq/Distinct.cs +++ b/src/UniTask.NetCore/Linq/Distinct.cs @@ -9,8 +9,6 @@ namespace Cysharp.Threading.Tasks.Linq { public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source) { - Error.ThrowArgumentNullException(source, nameof(source)); - return Distinct(source, EqualityComparer.Default); } @@ -21,6 +19,48 @@ namespace Cysharp.Threading.Tasks.Linq return new Distinct(source, comparer); } + + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, Func keySelector) + { + return Distinct(source, keySelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable Distinct(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new Distinct(source, keySelector, comparer); + } + + public static IUniTaskAsyncEnumerable DistinctAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + return DistinctAwait(source, keySelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable DistinctAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new DistinctAwait(source, keySelector, comparer); + } + + public static IUniTaskAsyncEnumerable DistinctAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + return DistinctAwaitWithCancellation(source, keySelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable DistinctAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new DistinctAwaitCancellation(source, keySelector, comparer); + } } internal sealed class Distinct : IUniTaskAsyncEnumerable @@ -73,4 +113,165 @@ namespace Cysharp.Threading.Tasks.Linq } } } + + internal sealed class Distinct : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func keySelector; + readonly IEqualityComparer comparer; + + public Distinct(IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly HashSet set; + readonly Func keySelector; + + public Enumerator(IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.set = new HashSet(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 : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly IEqualityComparer comparer; + + public DistinctAwait(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly HashSet set; + readonly Func> keySelector; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.set = new HashSet(comparer); + this.keySelector = keySelector; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return keySelector(sourceCurrent); + } + + protected override bool TrySetCurrentCore(TKey awaitResult, out bool terminateIteration) + { + if (set.Add(awaitResult)) + { + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = false; + return false; + } + } + } + } + + internal sealed class DistinctAwaitCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly IEqualityComparer comparer; + + public DistinctAwaitCancellation(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly HashSet set; + readonly Func> keySelector; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.set = new HashSet(comparer); + this.keySelector = keySelector; + } + + protected override UniTask 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; + } + } + } + } } \ No newline at end of file diff --git a/src/UniTask.NetCore/Linq/_FileMaker.cs b/src/UniTask.NetCore/Linq/_FileMaker.cs deleted file mode 100644 index 4f1b224..0000000 --- a/src/UniTask.NetCore/Linq/_FileMaker.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Cysharp.Threading.Tasks; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace ___Dummy -{ - - public interface IAsyncGrouping - { - } - - - public interface IOrderedAsyncEnumerable - { - - } - public static partial class _FileMaker - { - // Buffer,Distinct, DistinctUntilChanged, Do, MaxBy, MinBy, Never,Return, Throw - - - - - - - - - - - - - - - - - - - - - - - - - } - - -} - diff --git a/src/UniTask.NetCoreTests/Linq/Sets.cs b/src/UniTask.NetCoreTests/Linq/Sets.cs index 627c578..e730f61 100644 --- a/src/UniTask.NetCoreTests/Linq/Sets.cs +++ b/src/UniTask.NetCoreTests/Linq/Sets.cs @@ -32,10 +32,13 @@ namespace NetCoreTests.Linq [MemberData(nameof(array1))] public async Task Distinct(int[] array) { - var xs = await array.ToUniTaskAsyncEnumerable().Distinct().ToArrayAsync(); var ys = array.Distinct().ToArray(); - - xs.Should().BeEquivalentTo(ys); + { + (await array.ToUniTaskAsyncEnumerable().Distinct().ToArrayAsync()).Should().BeEquivalentTo(ys); + (await array.ToUniTaskAsyncEnumerable().Distinct(x => x).ToArrayAsync()).Should().BeEquivalentTo(ys); + (await array.ToUniTaskAsyncEnumerable().DistinctAwait(x => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys); + (await array.ToUniTaskAsyncEnumerable().DistinctAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys); + } } [Fact] @@ -43,8 +46,22 @@ namespace NetCoreTests.Linq { foreach (var item in UniTaskTestException.Throws()) { - var xs = item.Distinct().ToArrayAsync(); - await Assert.ThrowsAsync(async () => await xs); + { + var xs = item.Distinct().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.Distinct(x => x).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.DistinctAwait(x => UniTask.Run(() => x)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.DistinctAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } } } From 72efadd0a25ca7dcfdd49f7c6ff9689ef36e1562 Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 03:01:05 +0900 Subject: [PATCH 28/31] DistinctUntilChanged --- .../Linq/DistinctUntilChanged.cs | 297 ++++++++++++++++++ src/UniTask.NetCoreTests/Linq/Sets.cs | 38 +++ .../UniTask.NetCoreTests.csproj | 4 +- 3 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 src/UniTask.NetCore/Linq/DistinctUntilChanged.cs diff --git a/src/UniTask.NetCore/Linq/DistinctUntilChanged.cs b/src/UniTask.NetCore/Linq/DistinctUntilChanged.cs new file mode 100644 index 0000000..4f25336 --- /dev/null +++ b/src/UniTask.NetCore/Linq/DistinctUntilChanged.cs @@ -0,0 +1,297 @@ +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 DistinctUntilChanged(this IUniTaskAsyncEnumerable source) + { + return DistinctUntilChanged(source, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChanged(this IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new DistinctUntilChanged(source, comparer); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChanged(this IUniTaskAsyncEnumerable source, Func keySelector) + { + return DistinctUntilChanged(source, keySelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChanged(this IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new DistinctUntilChanged(source, keySelector, comparer); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChangedAwait(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + return DistinctUntilChangedAwait(source, keySelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChangedAwait(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new DistinctUntilChangedAwait(source, keySelector, comparer); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChangedAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector) + { + return DistinctUntilChangedAwaitWithCancellation(source, keySelector, EqualityComparer.Default); + } + + public static IUniTaskAsyncEnumerable DistinctUntilChangedAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + Error.ThrowArgumentNullException(source, nameof(source)); + Error.ThrowArgumentNullException(keySelector, nameof(keySelector)); + Error.ThrowArgumentNullException(comparer, nameof(comparer)); + + return new DistinctUntilChangedAwaitCancellation(source, keySelector, comparer); + } + } + + internal sealed class DistinctUntilChanged : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly IEqualityComparer comparer; + + public DistinctUntilChanged(IUniTaskAsyncEnumerable source, IEqualityComparer comparer) + { + this.source = source; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly IEqualityComparer comparer; + TSource prev; + bool first; + + public Enumerator(IUniTaskAsyncEnumerable source, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.comparer = comparer; + this.first = true; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + if (first || !comparer.Equals(prev, v)) + { + first = false; + Current = prev = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } + + internal sealed class DistinctUntilChanged : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func keySelector; + readonly IEqualityComparer comparer; + + public DistinctUntilChanged(IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorBase + { + readonly IEqualityComparer comparer; + readonly Func keySelector; + TKey prev; + bool first; + + public Enumerator(IUniTaskAsyncEnumerable source, Func keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.comparer = comparer; + this.keySelector = keySelector; + this.first = true; + } + + protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result) + { + if (sourceHasCurrent) + { + var v = SourceCurrent; + var key = keySelector(v); + if (first || !comparer.Equals(prev, key)) + { + first = false; + prev = key; + Current = v; + result = true; + return true; + } + else + { + result = default; + return false; + } + } + + result = false; + return true; + } + } + } + + internal sealed class DistinctUntilChangedAwait : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly IEqualityComparer comparer; + + public DistinctUntilChangedAwait(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly IEqualityComparer comparer; + readonly Func> keySelector; + TKey prev; + bool first; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.comparer = comparer; + this.keySelector = keySelector; + this.first = true; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return keySelector(sourceCurrent); + } + + protected override bool TrySetCurrentCore(TKey key, out bool terminateIteration) + { + if (first || !comparer.Equals(prev, key)) + { + first = false; + prev = key; + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = false; + return false; + } + } + } + } + + internal sealed class DistinctUntilChangedAwaitCancellation : IUniTaskAsyncEnumerable + { + readonly IUniTaskAsyncEnumerable source; + readonly Func> keySelector; + readonly IEqualityComparer comparer; + + public DistinctUntilChangedAwaitCancellation(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer) + { + this.source = source; + this.keySelector = keySelector; + this.comparer = comparer; + } + + public IUniTaskAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, keySelector, comparer, cancellationToken); + } + + class Enumerator : AsyncEnumeratorAwaitSelectorBase + { + readonly IEqualityComparer comparer; + readonly Func> keySelector; + TKey prev; + bool first; + + public Enumerator(IUniTaskAsyncEnumerable source, Func> keySelector, IEqualityComparer comparer, CancellationToken cancellationToken) + + : base(source, cancellationToken) + { + this.comparer = comparer; + this.keySelector = keySelector; + this.first = true; + } + + protected override UniTask TransformAsync(TSource sourceCurrent) + { + return keySelector(sourceCurrent, cancellationToken); + } + + protected override bool TrySetCurrentCore(TKey key, out bool terminateIteration) + { + if (first || !comparer.Equals(prev, key)) + { + first = false; + prev = key; + Current = SourceCurrent; + terminateIteration = false; + return true; + } + else + { + terminateIteration = false; + return false; + } + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCoreTests/Linq/Sets.cs b/src/UniTask.NetCoreTests/Linq/Sets.cs index e730f61..6d3c45c 100644 --- a/src/UniTask.NetCoreTests/Linq/Sets.cs +++ b/src/UniTask.NetCoreTests/Linq/Sets.cs @@ -65,6 +65,44 @@ namespace NetCoreTests.Linq } } + [Theory] + [MemberData(nameof(array1))] + public async Task DistinctUntilChanged(int[] array) + { + var ys = await array.ToAsyncEnumerable().DistinctUntilChanged().ToArrayAsync(); + { + (await array.ToUniTaskAsyncEnumerable().DistinctUntilChanged().ToArrayAsync()).Should().BeEquivalentTo(ys); + (await array.ToUniTaskAsyncEnumerable().DistinctUntilChanged(x => x).ToArrayAsync()).Should().BeEquivalentTo(ys); + (await array.ToUniTaskAsyncEnumerable().DistinctUntilChangedAwait(x => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys); + (await array.ToUniTaskAsyncEnumerable().DistinctUntilChangedAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync()).Should().BeEquivalentTo(ys); + } + } + + [Fact] + public async Task DistinctUntilChangedThrow() + { + foreach (var item in UniTaskTestException.Throws()) + { + { + var xs = item.DistinctUntilChanged().ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.DistinctUntilChanged(x => x).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.DistinctUntilChangedAwait(x => UniTask.Run(() => x)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + { + var xs = item.DistinctUntilChangedAwaitWithCancellation((x, _) => UniTask.Run(() => x)).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + } + } + } + + [Fact] public async Task Except() { diff --git a/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj b/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj index 240d795..aa0765b 100644 --- a/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj +++ b/src/UniTask.NetCoreTests/UniTask.NetCoreTests.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 @@ -11,6 +11,8 @@ + + From 61a3744fdd2f96f538a488669f5e83870bb24d2a Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 03:33:11 +0900 Subject: [PATCH 29/31] Buffer --- src/UniTask.NetCore/Linq/Buffer.cs | 340 ++++++++++++++++++++ src/UniTask.NetCoreTests/Linq/Projection.cs | 47 +++ 2 files changed, 387 insertions(+) create mode 100644 src/UniTask.NetCore/Linq/Buffer.cs diff --git a/src/UniTask.NetCore/Linq/Buffer.cs b/src/UniTask.NetCore/Linq/Buffer.cs new file mode 100644 index 0000000..f29af41 --- /dev/null +++ b/src/UniTask.NetCore/Linq/Buffer.cs @@ -0,0 +1,340 @@ +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> Buffer(this IUniTaskAsyncEnumerable source, Int32 count) + { + Error.ThrowArgumentNullException(source, nameof(source)); + if (count <= 0) throw Error.ArgumentOutOfRange(nameof(count)); + + return new Buffer(source, count); + } + + public static IUniTaskAsyncEnumerable> Buffer(this IUniTaskAsyncEnumerable 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(source, count, skip); + } + } + + internal sealed class Buffer : IUniTaskAsyncEnumerable> + { + readonly IUniTaskAsyncEnumerable source; + readonly int count; + + public Buffer(IUniTaskAsyncEnumerable source, int count) + { + this.source = source; + this.count = count; + } + + public IUniTaskAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, count, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator> + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly int count; + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + bool continueNext; + + bool completed; + List buffer; + + public Enumerator(IUniTaskAsyncEnumerable source, int count, CancellationToken cancellationToken) + { + this.source = source; + this.count = count; + this.cancellationToken = cancellationToken; + } + + public IList Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + buffer = new List(count); + } + + completionSource.Reset(); + SourceMoveNext(); + return new UniTask(this, completionSource.Version); + } + + void SourceMoveNext() + { + if (completed) + { + if (buffer != null && buffer.Count > 0) + { + var ret = buffer; + buffer = null; + Current = ret; + completionSource.TrySetResult(true); + return; + } + else + { + completionSource.TrySetResult(false); + return; + } + } + + try + { + + LOOP: + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + self.buffer.Add(self.enumerator.Current); + + if (self.buffer.Count == self.count) + { + self.Current = self.buffer; + self.buffer = new List(self.count); + self.continueNext = false; + self.completionSource.TrySetResult(true); + return; + } + else + { + if (!self.continueNext) + { + self.SourceMoveNext(); + } + } + } + else + { + self.continueNext = false; + self.completed = true; + self.SourceMoveNext(); + } + } + else + { + self.continueNext = false; + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } + + internal sealed class BufferSkip : IUniTaskAsyncEnumerable> + { + readonly IUniTaskAsyncEnumerable source; + readonly int count; + readonly int skip; + + public BufferSkip(IUniTaskAsyncEnumerable source, int count, int skip) + { + this.source = source; + this.count = count; + this.skip = skip; + } + + public IUniTaskAsyncEnumerator> GetAsyncEnumerator(CancellationToken cancellationToken = default) + { + return new Enumerator(source, count, skip, cancellationToken); + } + + sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator> + { + static readonly Action MoveNextCoreDelegate = MoveNextCore; + + readonly IUniTaskAsyncEnumerable source; + readonly int count; + readonly int skip; + CancellationToken cancellationToken; + + IUniTaskAsyncEnumerator enumerator; + UniTask.Awaiter awaiter; + bool continueNext; + + bool completed; + Queue> buffers; + int index = 0; + + public Enumerator(IUniTaskAsyncEnumerable source, int count, int skip, CancellationToken cancellationToken) + { + this.source = source; + this.count = count; + this.skip = skip; + this.cancellationToken = cancellationToken; + } + + public IList Current { get; private set; } + + public UniTask MoveNextAsync() + { + cancellationToken.ThrowIfCancellationRequested(); + + if (enumerator == null) + { + enumerator = source.GetAsyncEnumerator(cancellationToken); + buffers = new Queue>(); + } + + completionSource.Reset(); + SourceMoveNext(); + return new UniTask(this, completionSource.Version); + } + + void SourceMoveNext() + { + if (completed) + { + if (buffers.Count > 0) + { + Current = buffers.Dequeue(); + completionSource.TrySetResult(true); + return; + } + else + { + completionSource.TrySetResult(false); + return; + } + } + + try + { + + LOOP: + awaiter = enumerator.MoveNextAsync().GetAwaiter(); + if (awaiter.IsCompleted) + { + continueNext = true; + MoveNextCore(this); + if (continueNext) + { + continueNext = false; + goto LOOP; // avoid recursive + } + } + else + { + awaiter.SourceOnCompleted(MoveNextCoreDelegate, this); + } + } + catch (Exception ex) + { + completionSource.TrySetException(ex); + } + } + + + static void MoveNextCore(object state) + { + var self = (Enumerator)state; + + if (self.TryGetResult(self.awaiter, out var result)) + { + if (result) + { + if (self.index++ % self.skip == 0) + { + self.buffers.Enqueue(new List(self.count)); + } + + var item = self.enumerator.Current; + foreach (var buffer in self.buffers) + { + buffer.Add(item); + } + + if (self.buffers.Count > 0 && self.buffers.Peek().Count == self.count) + { + self.Current = self.buffers.Dequeue(); + self.continueNext = false; + self.completionSource.TrySetResult(true); + return; + } + else + { + if (!self.continueNext) + { + self.SourceMoveNext(); + } + } + } + else + { + self.continueNext = false; + self.completed = true; + self.SourceMoveNext(); + } + } + else + { + self.continueNext = false; + } + } + + public UniTask DisposeAsync() + { + if (enumerator != null) + { + return enumerator.DisposeAsync(); + } + return default; + } + } + } +} \ No newline at end of file diff --git a/src/UniTask.NetCoreTests/Linq/Projection.cs b/src/UniTask.NetCoreTests/Linq/Projection.cs index 2ec717a..ec652ac 100644 --- a/src/UniTask.NetCoreTests/Linq/Projection.cs +++ b/src/UniTask.NetCoreTests/Linq/Projection.cs @@ -272,5 +272,52 @@ namespace NetCoreTests.Linq await Assert.ThrowsAsync(async () => await xs); } } + + [Theory] + // [InlineData(0, 0)] + [InlineData(0, 3)] + [InlineData(9, 1)] + [InlineData(9, 2)] + [InlineData(9, 3)] + [InlineData(17, 3)] + [InlineData(17, 16)] + [InlineData(17, 17)] + [InlineData(17, 27)] + public async Task Buffer(int rangeCount, int bufferCount) + { + var xs = await UniTaskAsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount).Select(x => string.Join(",", x)).ToArrayAsync(); + var ys = await AsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount).Select(x => string.Join(",", x)).ToArrayAsync(); + + xs.Should().BeEquivalentTo(ys); + } + + [Theory] + // [InlineData(0, 0)] + [InlineData(0, 3, 2)] + [InlineData(9, 1, 1)] + [InlineData(9, 2, 3)] + [InlineData(9, 3, 4)] + [InlineData(17, 3, 3)] + [InlineData(17, 16, 5)] + [InlineData(17, 17, 19)] + public async Task BufferSkip(int rangeCount, int bufferCount, int skipCount) + { + var xs = await UniTaskAsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount, skipCount).Select(x => string.Join(",", x)).ToArrayAsync(); + var ys = await AsyncEnumerable.Range(0, rangeCount).Buffer(bufferCount, skipCount).Select(x => string.Join(",", x)).ToArrayAsync(); + + xs.Should().BeEquivalentTo(ys); + } + + [Fact] + public async Task BufferError() + { + foreach (var item in UniTaskTestException.Throws()) + { + var xs = item.Buffer(3).ToArrayAsync(); + var ys = item.Buffer(3, 2).ToArrayAsync(); + await Assert.ThrowsAsync(async () => await xs); + await Assert.ThrowsAsync(async () => await ys); + } + } } } From cda59ba9c2a5e32eab71fcc9d31c583e346a57f5 Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 03:41:53 +0900 Subject: [PATCH 30/31] Do --- src/UniTask.NetCore/Linq/Do.cs | 67 +++++++++++++++++----------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/UniTask.NetCore/Linq/Do.cs b/src/UniTask.NetCore/Linq/Do.cs index a5565fb..9cb3f41 100644 --- a/src/UniTask.NetCore/Linq/Do.cs +++ b/src/UniTask.NetCore/Linq/Do.cs @@ -41,47 +41,47 @@ namespace Cysharp.Threading.Tasks.Linq return source.Do(observer.OnNext, observer.OnError, observer.OnCompleted); // alloc delegate. } - // TODO:Rename -> DoAwait + // not yet impl. - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwait(this IUniTaskAsyncEnumerable source, Func onNext) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwait(this IUniTaskAsyncEnumerable source, Func onNext, Func onError) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onCompleted) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwait(this IUniTaskAsyncEnumerable source, Func onNext, Func onCompleted) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError, Func onCompleted) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwait(this IUniTaskAsyncEnumerable source, Func onNext, Func onError, Func onCompleted) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func onNext) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func onNext, Func onError) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onCompleted) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func onNext, Func onCompleted) + //{ + // throw new NotImplementedException(); + //} - public static IUniTaskAsyncEnumerable Do(this IUniTaskAsyncEnumerable source, Func onNext, Func onError, Func onCompleted) - { - throw new NotImplementedException(); - } + //public static IUniTaskAsyncEnumerable DoAwaitWithCancellation(this IUniTaskAsyncEnumerable source, Func onNext, Func onError, Func onCompleted) + //{ + // throw new NotImplementedException(); + //} } internal sealed class Do : IUniTaskAsyncEnumerable @@ -252,4 +252,5 @@ namespace Cysharp.Threading.Tasks.Linq } } } + } From c23b9ca48017a32eab24f993a274aac75a5d6f14 Mon Sep 17 00:00:00 2001 From: neuecc Date: Tue, 12 May 2020 03:48:32 +0900 Subject: [PATCH 31/31] move to underunity --- src/UniTask.NetCore/UniTask.NetCore.csproj | 50 ------------------- .../Plugins/UniTask}/IAsyncEnumerable.cs | 0 .../Plugins/UniTask/IAsyncEnumerable.cs.meta | 11 ++++ src/UniTask/Assets/Plugins/UniTask/Linq.meta | 8 +++ .../Assets/Plugins/UniTask}/Linq/Aggregate.cs | 0 .../Plugins/UniTask/Linq/Aggregate.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/All.cs | 0 .../Assets/Plugins/UniTask/Linq/All.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Any.cs | 0 .../Assets/Plugins/UniTask/Linq/Any.cs.meta | 11 ++++ .../Plugins/UniTask}/Linq/AppendPrepend.cs | 0 .../UniTask/Linq/AppendPrepend.cs.meta | 11 ++++ .../UniTask}/Linq/AsUniTaskAsyncEnumerable.cs | 0 .../Linq/AsUniTaskAsyncEnumerable.cs.meta | 11 ++++ .../UniTask}/Linq/AsyncEnumeratorBase.cs | 0 .../UniTask/Linq/AsyncEnumeratorBase.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Average.cs | 0 .../Plugins/UniTask/Linq/Average.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Average.tt | 0 .../Plugins/UniTask/Linq/Average.tt.meta | 7 +++ .../Assets/Plugins/UniTask}/Linq/Buffer.cs | 0 .../Plugins/UniTask/Linq/Buffer.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Cast.cs | 0 .../Assets/Plugins/UniTask/Linq/Cast.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Concat.cs | 0 .../Plugins/UniTask/Linq/Concat.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Contains.cs | 0 .../Plugins/UniTask/Linq/Contains.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Count.cs | 0 .../Assets/Plugins/UniTask/Linq/Count.cs.meta | 11 ++++ .../Plugins/UniTask}/Linq/DefaultIfEmpty.cs | 0 .../UniTask/Linq/DefaultIfEmpty.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Distinct.cs | 0 .../Plugins/UniTask/Linq/Distinct.cs.meta | 11 ++++ .../UniTask}/Linq/DistinctUntilChanged.cs | 0 .../UniTask/Linq/DistinctUntilChanged.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Do.cs | 0 .../Assets/Plugins/UniTask/Linq/Do.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/ElementAt.cs | 0 .../Plugins/UniTask/Linq/ElementAt.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Empty.cs | 0 .../Assets/Plugins/UniTask/Linq/Empty.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Except.cs | 0 .../Plugins/UniTask/Linq/Except.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/First.cs | 0 .../Assets/Plugins/UniTask/Linq/First.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/ForEach.cs | 0 .../Plugins/UniTask/Linq/ForEach.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/GroupBy.cs | 0 .../Plugins/UniTask/Linq/GroupBy.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/GroupJoin.cs | 0 .../Plugins/UniTask/Linq/GroupJoin.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Intersect.cs | 0 .../Plugins/UniTask/Linq/Intersect.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Join.cs | 0 .../Assets/Plugins/UniTask/Linq/Join.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Last.cs | 0 .../Assets/Plugins/UniTask/Linq/Last.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/LongCount.cs | 0 .../Plugins/UniTask/Linq/LongCount.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Max.cs | 0 .../Assets/Plugins/UniTask/Linq/Max.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Min.cs | 0 .../Assets/Plugins/UniTask/Linq/Min.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/MinMax.cs | 0 .../Plugins/UniTask/Linq/MinMax.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/MinMax.tt | 0 .../Plugins/UniTask/Linq/MinMax.tt.meta | 7 +++ .../Assets/Plugins/UniTask}/Linq/Never.cs | 0 .../Assets/Plugins/UniTask/Linq/Never.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/OfType.cs | 0 .../Plugins/UniTask/Linq/OfType.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/OrderBy.cs | 0 .../Plugins/UniTask/Linq/OrderBy.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Range.cs | 0 .../Assets/Plugins/UniTask/Linq/Range.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Repeat.cs | 0 .../Plugins/UniTask/Linq/Repeat.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Return.cs | 0 .../Plugins/UniTask/Linq/Return.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Reverse.cs | 0 .../Plugins/UniTask/Linq/Reverse.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Select.cs | 0 .../Plugins/UniTask/Linq/Select.cs.meta | 11 ++++ .../Plugins/UniTask}/Linq/SelectMany.cs | 0 .../Plugins/UniTask/Linq/SelectMany.cs.meta | 11 ++++ .../Plugins/UniTask}/Linq/SequenceEqual.cs | 0 .../UniTask/Linq/SequenceEqual.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Single.cs | 0 .../Plugins/UniTask/Linq/Single.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Skip.cs | 0 .../Assets/Plugins/UniTask/Linq/Skip.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/SkipLast.cs | 0 .../Plugins/UniTask/Linq/SkipLast.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/SkipWhile.cs | 0 .../Plugins/UniTask/Linq/SkipWhile.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Sum.cs | 0 .../Assets/Plugins/UniTask/Linq/Sum.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Sum.tt | 0 .../Assets/Plugins/UniTask/Linq/Sum.tt.meta | 7 +++ .../Assets/Plugins/UniTask}/Linq/Take.cs | 0 .../Assets/Plugins/UniTask/Linq/Take.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/TakeLast.cs | 0 .../Plugins/UniTask/Linq/TakeLast.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/TakeWhile.cs | 0 .../Plugins/UniTask/Linq/TakeWhile.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Throw.cs | 0 .../Assets/Plugins/UniTask/Linq/Throw.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/ToArray.cs | 0 .../Plugins/UniTask/Linq/ToArray.cs.meta | 11 ++++ .../Plugins/UniTask}/Linq/ToDictionary.cs | 0 .../Plugins/UniTask/Linq/ToDictionary.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/ToHashSet.cs | 0 .../Plugins/UniTask/Linq/ToHashSet.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/ToList.cs | 0 .../Plugins/UniTask/Linq/ToList.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/ToLookup.cs | 0 .../Plugins/UniTask/Linq/ToLookup.cs.meta | 11 ++++ .../Plugins/UniTask}/Linq/ToObservable.cs | 0 .../Plugins/UniTask/Linq/ToObservable.cs.meta | 11 ++++ .../UniTask}/Linq/ToUniTaskAsyncEnumerable.cs | 0 .../Linq/ToUniTaskAsyncEnumerable.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Union.cs | 0 .../Assets/Plugins/UniTask/Linq/Union.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Where.cs | 0 .../Assets/Plugins/UniTask/Linq/Where.cs.meta | 11 ++++ .../Assets/Plugins/UniTask}/Linq/Zip.cs | 0 .../Assets/Plugins/UniTask/Linq/Zip.cs.meta | 11 ++++ src/UniTask/Assets/Scenes/SandboxMain.cs | 18 +++++-- .../ProjectSettings/ProjectVersion.txt | 4 +- 130 files changed, 705 insertions(+), 56 deletions(-) rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/IAsyncEnumerable.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/IAsyncEnumerable.cs.meta create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Aggregate.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Aggregate.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/All.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/All.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Any.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Any.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/AppendPrepend.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/AppendPrepend.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/AsUniTaskAsyncEnumerable.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/AsUniTaskAsyncEnumerable.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/AsyncEnumeratorBase.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/AsyncEnumeratorBase.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Average.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Average.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Average.tt (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Average.tt.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Buffer.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Buffer.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Cast.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Cast.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Concat.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Concat.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Contains.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Contains.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Count.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Count.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/DefaultIfEmpty.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/DefaultIfEmpty.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Distinct.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Distinct.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/DistinctUntilChanged.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/DistinctUntilChanged.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Do.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Do.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ElementAt.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ElementAt.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Empty.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Empty.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Except.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Except.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/First.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/First.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ForEach.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ForEach.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/GroupBy.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/GroupBy.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/GroupJoin.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/GroupJoin.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Intersect.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Intersect.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Join.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Join.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Last.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Last.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/LongCount.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/LongCount.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Max.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Max.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Min.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Min.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/MinMax.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/MinMax.tt (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.tt.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Never.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Never.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/OfType.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/OfType.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/OrderBy.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/OrderBy.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Range.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Range.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Repeat.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Repeat.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Return.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Return.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Reverse.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Reverse.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Select.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Select.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/SelectMany.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/SelectMany.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/SequenceEqual.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/SequenceEqual.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Single.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Single.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Skip.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Skip.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/SkipLast.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/SkipLast.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/SkipWhile.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/SkipWhile.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Sum.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Sum.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Sum.tt (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Sum.tt.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Take.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Take.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/TakeLast.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/TakeLast.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/TakeWhile.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/TakeWhile.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Throw.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Throw.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToArray.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToArray.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToDictionary.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToDictionary.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToHashSet.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToHashSet.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToList.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToList.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToLookup.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToLookup.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToObservable.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToObservable.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/ToUniTaskAsyncEnumerable.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/ToUniTaskAsyncEnumerable.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Union.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Union.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Where.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Where.cs.meta rename src/{UniTask.NetCore => UniTask/Assets/Plugins/UniTask}/Linq/Zip.cs (100%) create mode 100644 src/UniTask/Assets/Plugins/UniTask/Linq/Zip.cs.meta diff --git a/src/UniTask.NetCore/UniTask.NetCore.csproj b/src/UniTask.NetCore/UniTask.NetCore.csproj index 027b681..d335bd7 100644 --- a/src/UniTask.NetCore/UniTask.NetCore.csproj +++ b/src/UniTask.NetCore/UniTask.NetCore.csproj @@ -14,54 +14,4 @@ - - - True - True - MinMax.tt - - - True - True - Sum.tt - - - - - - TextTemplatingFileGenerator - Average.cs - - - TextTemplatingFileGenerator - MinMax.cs - - - TextTemplatingFileGenerator - Sum.cs - - - - - - - - - - True - True - Average.tt - - - True - True - MinMax.tt - - - True - True - Sum.tt - - - diff --git a/src/UniTask.NetCore/IAsyncEnumerable.cs b/src/UniTask/Assets/Plugins/UniTask/IAsyncEnumerable.cs similarity index 100% rename from src/UniTask.NetCore/IAsyncEnumerable.cs rename to src/UniTask/Assets/Plugins/UniTask/IAsyncEnumerable.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/IAsyncEnumerable.cs.meta b/src/UniTask/Assets/Plugins/UniTask/IAsyncEnumerable.cs.meta new file mode 100644 index 0000000..12f0fe5 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/IAsyncEnumerable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b20cf9f02ac585948a4372fa4ee06504 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq.meta b/src/UniTask/Assets/Plugins/UniTask/Linq.meta new file mode 100644 index 0000000..1dcbc32 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4cc94a232b1c1154b8084bdda29c3484 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Aggregate.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Aggregate.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Aggregate.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Aggregate.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Aggregate.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Aggregate.cs.meta new file mode 100644 index 0000000..837df4a --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Aggregate.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5dc68c05a4228c643937f6ebd185bcca +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/All.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/All.cs similarity index 100% rename from src/UniTask.NetCore/Linq/All.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/All.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/All.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/All.cs.meta new file mode 100644 index 0000000..d378ff0 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/All.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7271437e0033af2448b600ee248924dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Any.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Any.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Any.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Any.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Any.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Any.cs.meta new file mode 100644 index 0000000..1070bcc --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Any.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e2b2e65745263994fbe34f3e0ec8eb12 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/AppendPrepend.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/AppendPrepend.cs similarity index 100% rename from src/UniTask.NetCore/Linq/AppendPrepend.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/AppendPrepend.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/AppendPrepend.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/AppendPrepend.cs.meta new file mode 100644 index 0000000..6d2ee04 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/AppendPrepend.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3268ec424b8055f45aa2a26d17c80468 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/AsUniTaskAsyncEnumerable.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/AsUniTaskAsyncEnumerable.cs similarity index 100% rename from src/UniTask.NetCore/Linq/AsUniTaskAsyncEnumerable.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/AsUniTaskAsyncEnumerable.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/AsUniTaskAsyncEnumerable.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/AsUniTaskAsyncEnumerable.cs.meta new file mode 100644 index 0000000..90f6207 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/AsUniTaskAsyncEnumerable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 69866e262589ea643bbc62a1d696077a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/AsyncEnumeratorBase.cs similarity index 100% rename from src/UniTask.NetCore/Linq/AsyncEnumeratorBase.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/AsyncEnumeratorBase.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/AsyncEnumeratorBase.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/AsyncEnumeratorBase.cs.meta new file mode 100644 index 0000000..a4e96dc --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/AsyncEnumeratorBase.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 01ba1d3b17e13fb4c95740131c7e6e19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Average.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Average.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Average.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Average.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Average.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Average.cs.meta new file mode 100644 index 0000000..8f60dfc --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Average.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 58499f95012fb3c47bb7bcbc5862e562 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Average.tt b/src/UniTask/Assets/Plugins/UniTask/Linq/Average.tt similarity index 100% rename from src/UniTask.NetCore/Linq/Average.tt rename to src/UniTask/Assets/Plugins/UniTask/Linq/Average.tt diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Average.tt.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Average.tt.meta new file mode 100644 index 0000000..e0a43fd --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Average.tt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 84bce45768c171d4490153eb08630a98 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Buffer.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Buffer.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Buffer.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Buffer.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Buffer.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Buffer.cs.meta new file mode 100644 index 0000000..e7154e4 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Buffer.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 951310243334a3148a7872977cb31c5c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Cast.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Cast.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Cast.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Cast.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Cast.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Cast.cs.meta new file mode 100644 index 0000000..913b043 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Cast.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: edebeae8b61352b428abe9ce8f3fc71a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Concat.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Concat.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Concat.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Concat.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Concat.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Concat.cs.meta new file mode 100644 index 0000000..6bfcf31 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Concat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7cb9e19c449127a459851a135ce7d527 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Contains.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Contains.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Contains.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Contains.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Contains.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Contains.cs.meta new file mode 100644 index 0000000..9bd414b --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Contains.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 36ab06d30f3223048b4f676e05431a7f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Count.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Count.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Count.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Count.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Count.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Count.cs.meta new file mode 100644 index 0000000..35db332 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Count.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e606d38eed688574bb2ba89d983cc9bb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/DefaultIfEmpty.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/DefaultIfEmpty.cs similarity index 100% rename from src/UniTask.NetCore/Linq/DefaultIfEmpty.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/DefaultIfEmpty.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/DefaultIfEmpty.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/DefaultIfEmpty.cs.meta new file mode 100644 index 0000000..5aa5993 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/DefaultIfEmpty.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 19e437c039ad7e1478dbce1779ef8660 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Distinct.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Distinct.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Distinct.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Distinct.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Distinct.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Distinct.cs.meta new file mode 100644 index 0000000..61804b7 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Distinct.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8f09903be66e5d943b243d7c19cb3811 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/DistinctUntilChanged.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/DistinctUntilChanged.cs similarity index 100% rename from src/UniTask.NetCore/Linq/DistinctUntilChanged.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/DistinctUntilChanged.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/DistinctUntilChanged.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/DistinctUntilChanged.cs.meta new file mode 100644 index 0000000..84cddf8 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/DistinctUntilChanged.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0351f6767df7e644b935d4d599968162 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Do.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Do.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Do.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Do.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Do.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Do.cs.meta new file mode 100644 index 0000000..766bbb5 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Do.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dd83c8e12dedf75409b829b93146d130 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ElementAt.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ElementAt.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ElementAt.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ElementAt.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ElementAt.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ElementAt.cs.meta new file mode 100644 index 0000000..fb0850b --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ElementAt.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c835bd2dd8555234c8919c7b8ef3b69a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Empty.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Empty.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Empty.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Empty.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Empty.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Empty.cs.meta new file mode 100644 index 0000000..bfa577a --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Empty.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4fa123ad6258abb4184721b719a13810 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Except.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Except.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Except.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Except.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Except.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Except.cs.meta new file mode 100644 index 0000000..f61a1aa --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Except.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 38c1c4129f59dcb49a5b864eaf4ec63c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/First.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/First.cs similarity index 100% rename from src/UniTask.NetCore/Linq/First.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/First.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/First.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/First.cs.meta new file mode 100644 index 0000000..6924307 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/First.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 417946e97e9eed84db6f840f57037ca6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ForEach.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ForEach.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ForEach.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ForEach.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ForEach.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ForEach.cs.meta new file mode 100644 index 0000000..5317756 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ForEach.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ca8d7f8177ba16140920af405aea3fd4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/GroupBy.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/GroupBy.cs similarity index 100% rename from src/UniTask.NetCore/Linq/GroupBy.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/GroupBy.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/GroupBy.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/GroupBy.cs.meta new file mode 100644 index 0000000..1489701 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/GroupBy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a2de80df1cc8a1240ab0ee7badd334d0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/GroupJoin.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/GroupJoin.cs similarity index 100% rename from src/UniTask.NetCore/Linq/GroupJoin.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/GroupJoin.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/GroupJoin.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/GroupJoin.cs.meta new file mode 100644 index 0000000..f171ed1 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/GroupJoin.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7bf7759d03bf3f64190d3ae83b182c2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Intersect.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Intersect.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Intersect.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Intersect.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Intersect.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Intersect.cs.meta new file mode 100644 index 0000000..28cf8e3 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Intersect.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 93999a70f5d57134bbe971f3e988c4f2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Join.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Join.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Join.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Join.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Join.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Join.cs.meta new file mode 100644 index 0000000..3ab1015 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Join.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc4ff8cb6d7c9a64896f2f082124d6b3 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Last.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Last.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Last.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Last.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Last.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Last.cs.meta new file mode 100644 index 0000000..edfa124 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Last.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a0ccc93be1387fa4a975f06310127c11 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/LongCount.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/LongCount.cs similarity index 100% rename from src/UniTask.NetCore/Linq/LongCount.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/LongCount.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/LongCount.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/LongCount.cs.meta new file mode 100644 index 0000000..862c2bc --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/LongCount.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 198b39e58ced3ab4f97ccbe0916787d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Max.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Max.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Max.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Max.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Max.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Max.cs.meta new file mode 100644 index 0000000..2125edf --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Max.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5c8a118a6b664c441820b8a87d7f6e28 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Min.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Min.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Min.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Min.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Min.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Min.cs.meta new file mode 100644 index 0000000..91378dc --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Min.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57ac9da21d3457849a8e45548290a508 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/MinMax.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.cs similarity index 100% rename from src/UniTask.NetCore/Linq/MinMax.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.cs.meta new file mode 100644 index 0000000..3856b65 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d6da02d9ab970e4999daf7147d98e36 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/MinMax.tt b/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.tt similarity index 100% rename from src/UniTask.NetCore/Linq/MinMax.tt rename to src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.tt diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.tt.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.tt.meta new file mode 100644 index 0000000..f77d718 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/MinMax.tt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 18108e9feb2ec40498df573cfef2ea15 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Never.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Never.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Never.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Never.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Never.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Never.cs.meta new file mode 100644 index 0000000..ba9d358 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Never.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 8b307c3d3be71a94da251564bcdefa3d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/OfType.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/OfType.cs similarity index 100% rename from src/UniTask.NetCore/Linq/OfType.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/OfType.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/OfType.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/OfType.cs.meta new file mode 100644 index 0000000..6ace53f --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/OfType.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 111ffe87a7d700442a9ef5af554b252c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/OrderBy.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/OrderBy.cs similarity index 100% rename from src/UniTask.NetCore/Linq/OrderBy.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/OrderBy.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/OrderBy.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/OrderBy.cs.meta new file mode 100644 index 0000000..5c6b3e4 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/OrderBy.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 413883ceff8546143bdf200aafa4b8f7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Range.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Range.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Range.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Range.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Range.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Range.cs.meta new file mode 100644 index 0000000..36272fc --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Range.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d826418a813498648b10542d0a5fb173 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Repeat.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Repeat.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Repeat.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Repeat.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Repeat.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Repeat.cs.meta new file mode 100644 index 0000000..693d579 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Repeat.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3819a3925165a674d80ee848c8600379 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Return.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Return.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Return.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Return.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Return.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Return.cs.meta new file mode 100644 index 0000000..ad264d0 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Return.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4313cd8ecf705e44f9064ce46e293c2c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Reverse.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Reverse.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Reverse.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Reverse.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Reverse.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Reverse.cs.meta new file mode 100644 index 0000000..4a28306 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Reverse.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b2769e65c729b4f4ca6af9826d9c7b90 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Select.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Select.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Select.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Select.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Select.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Select.cs.meta new file mode 100644 index 0000000..476e972 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Select.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: dc68e598ca44a134b988dfaf5e53bfba +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/SelectMany.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/SelectMany.cs similarity index 100% rename from src/UniTask.NetCore/Linq/SelectMany.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/SelectMany.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/SelectMany.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/SelectMany.cs.meta new file mode 100644 index 0000000..a8dbbaf --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/SelectMany.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d81862f0eb12680479ccaaf2ac319d24 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/SequenceEqual.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/SequenceEqual.cs similarity index 100% rename from src/UniTask.NetCore/Linq/SequenceEqual.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/SequenceEqual.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/SequenceEqual.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/SequenceEqual.cs.meta new file mode 100644 index 0000000..ee2b75c --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/SequenceEqual.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b382772aba6128842928cdb6b2e034b0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Single.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Single.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Single.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Single.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Single.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Single.cs.meta new file mode 100644 index 0000000..c053dfd --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Single.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bcd3928b90472e43a3a92c3ba708967 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Skip.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Skip.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Skip.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Skip.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Skip.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Skip.cs.meta new file mode 100644 index 0000000..25ad847 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Skip.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9c46b6c7dce0cb049a73c81084c75154 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/SkipLast.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/SkipLast.cs similarity index 100% rename from src/UniTask.NetCore/Linq/SkipLast.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/SkipLast.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/SkipLast.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/SkipLast.cs.meta new file mode 100644 index 0000000..06b1ede --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/SkipLast.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: df1d7f44d4fe7754f972c9e0b6fa72d5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/SkipWhile.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/SkipWhile.cs similarity index 100% rename from src/UniTask.NetCore/Linq/SkipWhile.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/SkipWhile.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/SkipWhile.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/SkipWhile.cs.meta new file mode 100644 index 0000000..f2b210a --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/SkipWhile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 0b74b9fe361bf7148b51a29c8b2561e8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Sum.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Sum.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Sum.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.cs.meta new file mode 100644 index 0000000..5331e34 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4149754066a21a341be58c04357061f6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Sum.tt b/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.tt similarity index 100% rename from src/UniTask.NetCore/Linq/Sum.tt rename to src/UniTask/Assets/Plugins/UniTask/Linq/Sum.tt diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.tt.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.tt.meta new file mode 100644 index 0000000..eaec35c --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Sum.tt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: b61271ca8e712494ab1ce2d10b180b6f +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Take.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Take.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Take.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Take.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Take.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Take.cs.meta new file mode 100644 index 0000000..1cc91ab --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Take.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 42f02cb84e5875b488304755d0e1383d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/TakeLast.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/TakeLast.cs similarity index 100% rename from src/UniTask.NetCore/Linq/TakeLast.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/TakeLast.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/TakeLast.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/TakeLast.cs.meta new file mode 100644 index 0000000..d80037f --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/TakeLast.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 510aa9fd35b45fc40bcdb7e59f01fd1b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/TakeWhile.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/TakeWhile.cs similarity index 100% rename from src/UniTask.NetCore/Linq/TakeWhile.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/TakeWhile.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/TakeWhile.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/TakeWhile.cs.meta new file mode 100644 index 0000000..f2173d5 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/TakeWhile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bca55adabcc4b3141b50b8b09634f764 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Throw.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Throw.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Throw.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Throw.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Throw.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Throw.cs.meta new file mode 100644 index 0000000..c768ef1 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Throw.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 9d05a7d4f4161e549b4789e1022baae8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToArray.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToArray.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToArray.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToArray.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToArray.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToArray.cs.meta new file mode 100644 index 0000000..679d61c --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToArray.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: debb010bbb1622e43b94fe70ec0133dd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToDictionary.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToDictionary.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToDictionary.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToDictionary.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToDictionary.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToDictionary.cs.meta new file mode 100644 index 0000000..4deed19 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToDictionary.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 03b109b1fe1f2df46aa56ffb26747654 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToHashSet.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToHashSet.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToHashSet.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToHashSet.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToHashSet.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToHashSet.cs.meta new file mode 100644 index 0000000..8d3c4af --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToHashSet.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7a3e552113af96e4986805ec3c4fc80a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToList.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToList.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToList.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToList.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToList.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToList.cs.meta new file mode 100644 index 0000000..4f09373 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToList.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3859c1b31e81d9b44b282e7d97e11635 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToLookup.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToLookup.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToLookup.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToLookup.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToLookup.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToLookup.cs.meta new file mode 100644 index 0000000..7dd8ecd --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToLookup.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 57da22563bcd6ca4aaf256d941de5cb0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToObservable.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToObservable.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToObservable.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToObservable.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToObservable.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToObservable.cs.meta new file mode 100644 index 0000000..44d917e --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToObservable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: b4f6f48a532188e4c80b7ebe69aea3a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/ToUniTaskAsyncEnumerable.cs similarity index 100% rename from src/UniTask.NetCore/Linq/ToUniTaskAsyncEnumerable.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/ToUniTaskAsyncEnumerable.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/ToUniTaskAsyncEnumerable.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/ToUniTaskAsyncEnumerable.cs.meta new file mode 100644 index 0000000..45fd3b0 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/ToUniTaskAsyncEnumerable.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d7192de2a0581ec4db62962cc1404af5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Union.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Union.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Union.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Union.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Union.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Union.cs.meta new file mode 100644 index 0000000..1d9c7ad --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Union.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ae57a55bdeba98b4f8ff234d98d7dd76 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Where.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Where.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Where.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Where.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Where.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Where.cs.meta new file mode 100644 index 0000000..7e50337 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Where.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d882a3238d9535e4e8ce1ad3291eb7fb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask.NetCore/Linq/Zip.cs b/src/UniTask/Assets/Plugins/UniTask/Linq/Zip.cs similarity index 100% rename from src/UniTask.NetCore/Linq/Zip.cs rename to src/UniTask/Assets/Plugins/UniTask/Linq/Zip.cs diff --git a/src/UniTask/Assets/Plugins/UniTask/Linq/Zip.cs.meta b/src/UniTask/Assets/Plugins/UniTask/Linq/Zip.cs.meta new file mode 100644 index 0000000..bf12163 --- /dev/null +++ b/src/UniTask/Assets/Plugins/UniTask/Linq/Zip.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: acc1acff153e347418f0f30b1c535994 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/src/UniTask/Assets/Scenes/SandboxMain.cs b/src/UniTask/Assets/Scenes/SandboxMain.cs index 728483f..ff9c1e6 100644 --- a/src/UniTask/Assets/Scenes/SandboxMain.cs +++ b/src/UniTask/Assets/Scenes/SandboxMain.cs @@ -12,6 +12,7 @@ using Unity.Jobs; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; +using Cysharp.Threading.Tasks.Linq; public struct MyJob : IJob { @@ -89,11 +90,18 @@ public class SandboxMain : MonoBehaviour async UniTaskVoid Update2() { + UnityEngine.Debug.Log("async linq!"); + + await UniTaskAsyncEnumerable.Range(1, 10) + .Where(x => x % 2 == 0) + .Select(x => x * x) + .ForEachAsync(x => + { + UnityEngine.Debug.Log(x); + }); + + UnityEngine.Debug.Log("done"); - async foreach (var _ in this.GetAsyncUpdateTrigger()) - { - // do anything - } } @@ -106,6 +114,8 @@ public class SandboxMain : MonoBehaviour ShowPlayerLoop.DumpPlayerLoop("Current", playerLoop); + Update2().Forget(); + //RunStandardDelayAsync().Forget(); //for (int i = 0; i < 14; i++) diff --git a/src/UniTask/ProjectSettings/ProjectVersion.txt b/src/UniTask/ProjectSettings/ProjectVersion.txt index c7d3fa9..2873a29 100644 --- a/src/UniTask/ProjectSettings/ProjectVersion.txt +++ b/src/UniTask/ProjectSettings/ProjectVersion.txt @@ -1,2 +1,2 @@ -m_EditorVersion: 2019.3.11f1 -m_EditorVersionWithRevision: 2019.3.11f1 (ceef2d848e70) +m_EditorVersion: 2019.3.9f1 +m_EditorVersionWithRevision: 2019.3.9f1 (e6e740a1c473)