Skip, Take, TakeWhile, SkipWhile

master
neuecc 2020-05-11 12:02:02 +09:00
parent c0da316cb4
commit 1316328766
11 changed files with 1383 additions and 3189 deletions

View File

@ -201,7 +201,7 @@ namespace Cysharp.Threading.Tasks.Linq
// abstract // abstract
protected abstract UniTask<TAwait> TransformAsync(TSource sourceCurrent); protected abstract UniTask<TAwait> TransformAsync(TSource sourceCurrent);
protected abstract bool TrySetCurrentCore(TAwait awaitResult); protected abstract bool TrySetCurrentCore(TAwait awaitResult, out bool terminateIteration);
// Util // Util
protected TSource SourceCurrent => enumerator.Current; protected TSource SourceCurrent => enumerator.Current;
@ -282,7 +282,13 @@ namespace Cysharp.Threading.Tasks.Linq
var task = TransformAsync(enumerator.Current); var task = TransformAsync(enumerator.Current);
if (UnwarapTask(task, out var taskResult)) 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 else
{ {
@ -345,10 +351,11 @@ namespace Cysharp.Threading.Tasks.Linq
var self = (AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait>)state; var self = (AsyncEnumeratorAwaitSelectorBase<TSource, TResult, TAwait>)state;
bool doneSetCurrent; bool doneSetCurrent;
bool terminateIteration;
try try
{ {
var result = self.resultAwaiter.GetResult(); var result = self.resultAwaiter.GetResult();
doneSetCurrent = self.TrySetCurrentCore(result); doneSetCurrent = self.TrySetCurrentCore(result, out terminateIteration);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -367,11 +374,18 @@ namespace Cysharp.Threading.Tasks.Linq
self.completionSource.TrySetResult(true); self.completionSource.TrySetResult(true);
} }
else else
{
if (terminateIteration)
{
self.completionSource.TrySetResult(false);
}
else
{ {
self.SourceMoveNext(); self.SourceMoveNext();
} }
} }
} }
}
// if require additional resource to dispose, override and call base.DisposeAsync. // if require additional resource to dispose, override and call base.DisposeAsync.
public virtual UniTask DisposeAsync() public virtual UniTask DisposeAsync()

View File

@ -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<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext)
{
Error.ThrowArgumentNullException(source, nameof(source));
return source.Do(onNext, null, null);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
{
Error.ThrowArgumentNullException(source, nameof(source));
return source.Do(onNext, onError, null);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
{
Error.ThrowArgumentNullException(source, nameof(source));
return source.Do(onNext, null, onCompleted);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Do<TSource>(source, onNext, onError, onCompleted);
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, IObserver<TSource> observer)
{
Error.ThrowArgumentNullException(source, nameof(source));
Error.ThrowArgumentNullException(observer, nameof(observer));
return source.Do(observer.OnNext, observer.OnError, observer.OnCompleted); // alloc delegate.
}
// TODO:Rename -> DoAwait
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Task> onNext)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Task> onNext, Func<Exception, Task> onError)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Task> onNext, Func<Task> onCompleted)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Task> onNext, Func<Exception, Task> onError, Func<Task> onCompleted)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> onNext)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> onNext, Func<Exception, CancellationToken, Task> onError)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> onNext, Func<CancellationToken, Task> onCompleted)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Do<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, Task> onNext, Func<Exception, CancellationToken, Task> onError, Func<CancellationToken, Task> onCompleted)
{
throw new NotImplementedException();
}
}
internal sealed class Do<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Action<TSource> onNext;
readonly Action<Exception> onError;
readonly Action onCompleted;
public Do(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
{
this.source = source;
this.onNext = onNext;
this.onError = onError;
this.onCompleted = onCompleted;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, onNext, onError, onCompleted, cancellationToken);
}
sealed class Enumerator : MoveNextSource, IUniTaskAsyncEnumerator<TSource>
{
static readonly Action<object> MoveNextCoreDelegate = MoveNextCore;
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly Action<TSource> onNext;
readonly Action<Exception> onError;
readonly Action onCompleted;
CancellationToken cancellationToken;
IUniTaskAsyncEnumerator<TSource> enumerator;
UniTask<bool>.Awaiter awaiter;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted, CancellationToken cancellationToken)
{
this.source = source;
this.onNext = onNext;
this.onError = onError;
this.onCompleted = onCompleted;
this.cancellationToken = cancellationToken;
}
public TSource Current { get; private set; }
public UniTask<bool> MoveNextAsync()
{
cancellationToken.ThrowIfCancellationRequested();
completionSource.Reset();
bool isCompleted = false;
try
{
if (enumerator == null)
{
enumerator = source.GetAsyncEnumerator(cancellationToken);
}
awaiter = enumerator.MoveNextAsync().GetAwaiter();
isCompleted = awaiter.IsCompleted;
}
catch (Exception ex)
{
CallTrySetExceptionAfterNotification(ex);
return new UniTask<bool>(this, completionSource.Version);
}
if (isCompleted)
{
MoveNextCore(this);
}
else
{
awaiter.SourceOnCompleted(MoveNextCoreDelegate, this);
}
return new UniTask<bool>(this, completionSource.Version);
}
void CallTrySetExceptionAfterNotification(Exception ex)
{
if (onError != null)
{
try
{
onError(ex);
}
catch (Exception ex2)
{
completionSource.TrySetException(ex2);
return;
}
}
completionSource.TrySetException(ex);
}
bool TryGetResultWithNotification<T>(UniTask<T>.Awaiter awaiter, out T result)
{
try
{
result = awaiter.GetResult();
return true;
}
catch (Exception ex)
{
CallTrySetExceptionAfterNotification(ex);
result = default;
return false;
}
}
static void MoveNextCore(object state)
{
var self = (Enumerator)state;
if (self.TryGetResultWithNotification(self.awaiter, out var result))
{
if (result)
{
var v = self.enumerator.Current;
if (self.onNext != null)
{
try
{
self.onNext(v);
}
catch (Exception ex)
{
self.CallTrySetExceptionAfterNotification(ex);
}
}
self.Current = v;
self.completionSource.TrySetResult(true);
}
else
{
if (self.onCompleted != null)
{
try
{
self.onCompleted();
}
catch (Exception ex)
{
self.CallTrySetExceptionAfterNotification(ex);
return;
}
}
self.completionSource.TrySetResult(false);
}
}
}
public UniTask DisposeAsync()
{
if (enumerator != null)
{
return enumerator.DisposeAsync();
}
return default;
}
}
}
}

View File

@ -173,9 +173,10 @@ namespace Cysharp.Threading.Tasks.Linq
return selector(sourceCurrent); return selector(sourceCurrent);
} }
protected override bool TrySetCurrentCore(TResult awaitResult) protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{ {
Current = awaitResult; Current = awaitResult;
terminateIteration= false;
return true; return true;
} }
} }
@ -213,9 +214,10 @@ namespace Cysharp.Threading.Tasks.Linq
return selector(sourceCurrent, checked(index++)); return selector(sourceCurrent, checked(index++));
} }
protected override bool TrySetCurrentCore(TResult awaitResult) protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{ {
Current = awaitResult; Current = awaitResult;
terminateIteration= false;
return true; return true;
} }
} }
@ -252,9 +254,10 @@ namespace Cysharp.Threading.Tasks.Linq
return selector(sourceCurrent, cancellationToken); return selector(sourceCurrent, cancellationToken);
} }
protected override bool TrySetCurrentCore(TResult awaitResult) protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{ {
Current = awaitResult; Current = awaitResult;
terminateIteration= false;
return true; return true;
} }
} }
@ -292,9 +295,10 @@ namespace Cysharp.Threading.Tasks.Linq
return selector(sourceCurrent, checked(index++), cancellationToken); return selector(sourceCurrent, checked(index++), cancellationToken);
} }
protected override bool TrySetCurrentCore(TResult awaitResult) protected override bool TrySetCurrentCore(TResult awaitResult, out bool terminateIteration)
{ {
Current = awaitResult; Current = awaitResult;
terminateIteration= false;
return true; return true;
} }
} }

View File

@ -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<TSource> Skip<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Skip<TSource>(source, count);
}
} }
internal sealed class Skip<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public Skip(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly int count;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.count = count;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (count <= checked(index++))
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = default;
return false;
}
}
else
{
result = false;
return true;
}
}
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -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<TSource> Take<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
Error.ThrowArgumentNullException(source, nameof(source));
return new Take<TSource>(source, count);
}
} }
internal sealed class Take<TSource> : IUniTaskAsyncEnumerable<TSource>
{
readonly IUniTaskAsyncEnumerable<TSource> source;
readonly int count;
public Take(IUniTaskAsyncEnumerable<TSource> source, int count)
{
this.source = source;
this.count = count;
}
public IUniTaskAsyncEnumerator<TSource> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
return new Enumerator(source, count, cancellationToken);
}
sealed class Enumerator : AsyncEnumeratorBase<TSource, TSource>
{
readonly int count;
int index;
public Enumerator(IUniTaskAsyncEnumerable<TSource> source, int count, CancellationToken cancellationToken)
: base(source, cancellationToken)
{
this.count = count;
}
protected override bool TryMoveNextCore(bool sourceHasCurrent, out bool result)
{
if (sourceHasCurrent)
{
if (checked(index++) < count)
{
Current = SourceCurrent;
result = true;
return true;
}
else
{
result = false;
return true;
}
}
else
{
result = false;
return true;
}
}
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -188,8 +188,9 @@ namespace Cysharp.Threading.Tasks.Linq
return predicate(sourceCurrent); return predicate(sourceCurrent);
} }
protected override bool TrySetCurrentCore(bool awaitResult) protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{ {
terminateIteration = false;
if (awaitResult) if (awaitResult)
{ {
Current = SourceCurrent; Current = SourceCurrent;
@ -236,8 +237,9 @@ namespace Cysharp.Threading.Tasks.Linq
return predicate(sourceCurrent, checked(index++)); return predicate(sourceCurrent, checked(index++));
} }
protected override bool TrySetCurrentCore(bool awaitResult) protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{ {
terminateIteration = false;
if (awaitResult) if (awaitResult)
{ {
Current = SourceCurrent; Current = SourceCurrent;
@ -285,8 +287,9 @@ namespace Cysharp.Threading.Tasks.Linq
return predicate(sourceCurrent, cancellationToken); return predicate(sourceCurrent, cancellationToken);
} }
protected override bool TrySetCurrentCore(bool awaitResult) protected override bool TrySetCurrentCore(bool awaitResult, out bool terminateIteration)
{ {
terminateIteration = false;
if (awaitResult) if (awaitResult)
{ {
Current = SourceCurrent; Current = SourceCurrent;
@ -333,8 +336,9 @@ namespace Cysharp.Threading.Tasks.Linq
return predicate(sourceCurrent, checked(index++), cancellationToken); 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) if (awaitResult)
{ {
Current = SourceCurrent; Current = SourceCurrent;

View File

@ -308,87 +308,18 @@ namespace ___Dummy
public static IUniTaskAsyncEnumerable<TSource> Skip<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> SkipLast<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count) public static IUniTaskAsyncEnumerable<TSource> SkipLast<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public static IUniTaskAsyncEnumerable<TSource> SkipWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> SkipWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> Take<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> TakeLast<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count) public static IUniTaskAsyncEnumerable<TSource> TakeLast<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Int32 count)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public static IUniTaskAsyncEnumerable<TSource> TakeWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Boolean> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhile<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, Boolean> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwait<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TSource> TakeWhileAwaitWithCancellation<TSource>(this IUniTaskAsyncEnumerable<TSource> source, Func<TSource, Int32, CancellationToken, UniTask<Boolean>> predicate)
{
throw new NotImplementedException();
}
public static IOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector) public static IOrderedAsyncEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@ -467,26 +398,6 @@ namespace ___Dummy
public static IUniTaskAsyncEnumerable<ValueTuple<TFirst, TSecond>> Zip<TFirst, TSecond>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> selector)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TResult> ZipAwait<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, UniTask<TResult>> selector)
{
throw new NotImplementedException();
}
public static IUniTaskAsyncEnumerable<TResult> ZipAwaitWithCancellation<TFirst, TSecond, TResult>(this IUniTaskAsyncEnumerable<TFirst> first, IUniTaskAsyncEnumerable<TSecond> second, Func<TFirst, TSecond, CancellationToken, UniTask<TResult>> selector)
{
throw new NotImplementedException();
}
} }

View File

@ -39,8 +39,20 @@ namespace NetCoreSandbox
static async Task Main(string[] args) static async Task Main(string[] args)
{ {
var foo = Enumerable.Range(1, 10).ToArray().AsEnumerable().GetEnumerator() as IEnumerator<int>; await foreach (var item in UniTaskAsyncEnumerable.Range(1, 10).Do(x => Console.WriteLine("DO:" + x))
Console.WriteLine(foo.GetType().FullName); //.TakeWhileAwait(x => UniTask.FromResult(x < 5))
.Take(5)
)
{
Console.WriteLine(item);
}
} }
@ -48,7 +60,7 @@ namespace NetCoreSandbox
void Foo() void Foo()
{ {
// AsyncEnumerable.Range(1,10).Do(
// AsyncEnumerable.t // AsyncEnumerable.t

View File

@ -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<UniTaskTestException>(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<UniTaskTestException>(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<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.SkipWhile((x, i) => x < 2).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.SkipWhileAwait((x) => UniTask.Run(() => x < 2)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.SkipWhileAwait((x, i) => UniTask.Run(() => x < 2)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.SkipWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < 2)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.SkipWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < 2)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(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<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.TakeWhile((x, i) => x < 5).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.TakeWhileAwait((x) => UniTask.Run(() => x < 5)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.TakeWhileAwait((x, i) => UniTask.Run(() => x < 5)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.TakeWhileAwaitWithCancellation((x, _) => UniTask.Run(() => x < 5)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
foreach (var item in UniTaskTestException.Throws())
{
var xs = item.TakeWhileAwaitWithCancellation((x, i, _) => UniTask.Run(() => x < 5)).ToArrayAsync();
await Assert.ThrowsAsync<UniTaskTestException>(async () => await xs);
}
}
}
}