using Cysharp.Threading.Tasks.Internal; using System; using System.Threading; namespace Cysharp.Threading.Tasks.Linq { 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 _TakeWhile(source, predicate, cancellationToken); } class _TakeWhile : AsyncEnumeratorBase { Func predicate; public _TakeWhile(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 _TakeWhileInt(source, predicate, cancellationToken); } class _TakeWhileInt : AsyncEnumeratorBase { readonly Func predicate; int index; public _TakeWhileInt(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 _TakeWhileAwait(source, predicate, cancellationToken); } class _TakeWhileAwait : AsyncEnumeratorAwaitSelectorBase { Func> predicate; public _TakeWhileAwait(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 _TakeWhileIntAwait(source, predicate, cancellationToken); } class _TakeWhileIntAwait : AsyncEnumeratorAwaitSelectorBase { readonly Func> predicate; int index; public _TakeWhileIntAwait(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 _TakeWhileAwaitWithCancellation(source, predicate, cancellationToken); } class _TakeWhileAwaitWithCancellation : AsyncEnumeratorAwaitSelectorBase { Func> predicate; public _TakeWhileAwaitWithCancellation(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 _TakeWhileIntAwaitWithCancellation(source, predicate, cancellationToken); } class _TakeWhileIntAwaitWithCancellation : AsyncEnumeratorAwaitSelectorBase { readonly Func> predicate; int index; public _TakeWhileIntAwaitWithCancellation(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; } } } } }