|
@@ -30,66 +30,6 @@ namespace System.Linq
|
|
|
return new SkipAsyncIterator<TSource>(source, count);
|
|
|
}
|
|
|
|
|
|
- public static IAsyncEnumerable<TSource> SkipLast<TSource>(this IAsyncEnumerable<TSource> source, int count)
|
|
|
- {
|
|
|
- if (source == null)
|
|
|
- throw new ArgumentNullException(nameof(source));
|
|
|
-
|
|
|
- if (count <= 0)
|
|
|
- {
|
|
|
- // Return source if not actually skipping, but only if it's a type from here, to avoid
|
|
|
- // issues if collections are used as keys or otherwise must not be aliased.
|
|
|
- if (source is AsyncIterator<TSource>)
|
|
|
- {
|
|
|
- return source;
|
|
|
- }
|
|
|
-
|
|
|
- count = 0;
|
|
|
- }
|
|
|
-
|
|
|
- return new SkipLastAsyncIterator<TSource>(source, count);
|
|
|
- }
|
|
|
-
|
|
|
- public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
|
|
|
- {
|
|
|
- if (source == null)
|
|
|
- throw new ArgumentNullException(nameof(source));
|
|
|
- if (predicate == null)
|
|
|
- throw new ArgumentNullException(nameof(predicate));
|
|
|
-
|
|
|
- return new SkipWhileAsyncIterator<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
|
|
|
- {
|
|
|
- if (source == null)
|
|
|
- throw new ArgumentNullException(nameof(source));
|
|
|
- if (predicate == null)
|
|
|
- throw new ArgumentNullException(nameof(predicate));
|
|
|
-
|
|
|
- return new SkipWhileWithIndexAsyncIterator<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<bool>> predicate)
|
|
|
- {
|
|
|
- if (source == null)
|
|
|
- throw new ArgumentNullException(nameof(source));
|
|
|
- if (predicate == null)
|
|
|
- throw new ArgumentNullException(nameof(predicate));
|
|
|
-
|
|
|
- return new SkipWhileAsyncIteratorWithTask<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public static IAsyncEnumerable<TSource> SkipWhile<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int, Task<bool>> predicate)
|
|
|
- {
|
|
|
- if (source == null)
|
|
|
- throw new ArgumentNullException(nameof(source));
|
|
|
- if (predicate == null)
|
|
|
- throw new ArgumentNullException(nameof(predicate));
|
|
|
-
|
|
|
- return new SkipWhileWithIndexAsyncIteratorWithTask<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
private sealed class SkipAsyncIterator<TSource> : AsyncIterator<TSource>
|
|
|
{
|
|
|
private readonly int count;
|
|
@@ -158,391 +98,5 @@ namespace System.Linq
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- private sealed class SkipLastAsyncIterator<TSource> : AsyncIterator<TSource>
|
|
|
- {
|
|
|
- private readonly int count;
|
|
|
- private readonly IAsyncEnumerable<TSource> source;
|
|
|
-
|
|
|
- private IAsyncEnumerator<TSource> enumerator;
|
|
|
- private Queue<TSource> queue;
|
|
|
-
|
|
|
- public SkipLastAsyncIterator(IAsyncEnumerable<TSource> source, int count)
|
|
|
- {
|
|
|
- Debug.Assert(source != null);
|
|
|
-
|
|
|
- this.source = source;
|
|
|
- this.count = count;
|
|
|
- }
|
|
|
-
|
|
|
- public override AsyncIterator<TSource> Clone()
|
|
|
- {
|
|
|
- return new SkipLastAsyncIterator<TSource>(source, count);
|
|
|
- }
|
|
|
-
|
|
|
- public override async Task DisposeAsync()
|
|
|
- {
|
|
|
- if (enumerator != null)
|
|
|
- {
|
|
|
- await enumerator.DisposeAsync().ConfigureAwait(false);
|
|
|
- enumerator = null;
|
|
|
- }
|
|
|
-
|
|
|
- queue = null; // release the memory
|
|
|
-
|
|
|
- await base.DisposeAsync().ConfigureAwait(false);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- protected override async Task<bool> MoveNextCore()
|
|
|
- {
|
|
|
- switch (state)
|
|
|
- {
|
|
|
- case AsyncIteratorState.Allocated:
|
|
|
- enumerator = source.GetAsyncEnumerator();
|
|
|
- queue = new Queue<TSource>();
|
|
|
-
|
|
|
- state = AsyncIteratorState.Iterating;
|
|
|
- goto case AsyncIteratorState.Iterating;
|
|
|
-
|
|
|
-
|
|
|
- case AsyncIteratorState.Iterating:
|
|
|
- while (await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- var item = enumerator.Current;
|
|
|
- queue.Enqueue(item);
|
|
|
-
|
|
|
- if (queue.Count > count)
|
|
|
- {
|
|
|
- current = queue.Dequeue();
|
|
|
- return true;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- await DisposeAsync().ConfigureAwait(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private sealed class SkipWhileAsyncIterator<TSource> : AsyncIterator<TSource>
|
|
|
- {
|
|
|
- private readonly Func<TSource, bool> predicate;
|
|
|
- private readonly IAsyncEnumerable<TSource> source;
|
|
|
-
|
|
|
- private bool doMoveNext;
|
|
|
- private IAsyncEnumerator<TSource> enumerator;
|
|
|
-
|
|
|
- public SkipWhileAsyncIterator(IAsyncEnumerable<TSource> source, Func<TSource, bool> predicate)
|
|
|
- {
|
|
|
- Debug.Assert(predicate != null);
|
|
|
- Debug.Assert(source != null);
|
|
|
-
|
|
|
- this.source = source;
|
|
|
- this.predicate = predicate;
|
|
|
- }
|
|
|
-
|
|
|
- public override AsyncIterator<TSource> Clone()
|
|
|
- {
|
|
|
- return new SkipWhileAsyncIterator<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public override async Task DisposeAsync()
|
|
|
- {
|
|
|
- if (enumerator != null)
|
|
|
- {
|
|
|
- await enumerator.DisposeAsync().ConfigureAwait(false);
|
|
|
- enumerator = null;
|
|
|
- }
|
|
|
-
|
|
|
- await base.DisposeAsync().ConfigureAwait(false);
|
|
|
- }
|
|
|
-
|
|
|
- protected override async Task<bool> MoveNextCore()
|
|
|
- {
|
|
|
- switch (state)
|
|
|
- {
|
|
|
- case AsyncIteratorState.Allocated:
|
|
|
- enumerator = source.GetAsyncEnumerator();
|
|
|
-
|
|
|
- // skip elements as requested
|
|
|
- while (await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- var element = enumerator.Current;
|
|
|
- if (!predicate(element))
|
|
|
- {
|
|
|
- doMoveNext = false;
|
|
|
- state = AsyncIteratorState.Iterating;
|
|
|
- goto case AsyncIteratorState.Iterating;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case AsyncIteratorState.Iterating:
|
|
|
- if (doMoveNext && await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (!doMoveNext)
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- doMoveNext = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- await DisposeAsync().ConfigureAwait(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private sealed class SkipWhileWithIndexAsyncIterator<TSource> : AsyncIterator<TSource>
|
|
|
- {
|
|
|
- private readonly Func<TSource, int, bool> predicate;
|
|
|
- private readonly IAsyncEnumerable<TSource> source;
|
|
|
-
|
|
|
- private bool doMoveNext;
|
|
|
- private IAsyncEnumerator<TSource> enumerator;
|
|
|
- private int index;
|
|
|
-
|
|
|
- public SkipWhileWithIndexAsyncIterator(IAsyncEnumerable<TSource> source, Func<TSource, int, bool> predicate)
|
|
|
- {
|
|
|
- Debug.Assert(predicate != null);
|
|
|
- Debug.Assert(source != null);
|
|
|
-
|
|
|
- this.source = source;
|
|
|
- this.predicate = predicate;
|
|
|
- }
|
|
|
-
|
|
|
- public override AsyncIterator<TSource> Clone()
|
|
|
- {
|
|
|
- return new SkipWhileWithIndexAsyncIterator<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public override async Task DisposeAsync()
|
|
|
- {
|
|
|
- if (enumerator != null)
|
|
|
- {
|
|
|
- await enumerator.DisposeAsync().ConfigureAwait(false);
|
|
|
- enumerator = null;
|
|
|
- }
|
|
|
-
|
|
|
- await base.DisposeAsync().ConfigureAwait(false);
|
|
|
- }
|
|
|
-
|
|
|
- protected override async Task<bool> MoveNextCore()
|
|
|
- {
|
|
|
- switch (state)
|
|
|
- {
|
|
|
- case AsyncIteratorState.Allocated:
|
|
|
- enumerator = source.GetAsyncEnumerator();
|
|
|
- index = -1;
|
|
|
-
|
|
|
- // skip elements as requested
|
|
|
- while (await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- checked
|
|
|
- {
|
|
|
- index++;
|
|
|
- }
|
|
|
-
|
|
|
- var element = enumerator.Current;
|
|
|
- if (!predicate(element, index))
|
|
|
- {
|
|
|
- doMoveNext = false;
|
|
|
- state = AsyncIteratorState.Iterating;
|
|
|
- goto case AsyncIteratorState.Iterating;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case AsyncIteratorState.Iterating:
|
|
|
- if (doMoveNext && await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (!doMoveNext)
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- doMoveNext = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- await DisposeAsync().ConfigureAwait(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private sealed class SkipWhileAsyncIteratorWithTask<TSource> : AsyncIterator<TSource>
|
|
|
- {
|
|
|
- private readonly Func<TSource, Task<bool>> predicate;
|
|
|
- private readonly IAsyncEnumerable<TSource> source;
|
|
|
-
|
|
|
- private bool doMoveNext;
|
|
|
- private IAsyncEnumerator<TSource> enumerator;
|
|
|
-
|
|
|
- public SkipWhileAsyncIteratorWithTask(IAsyncEnumerable<TSource> source, Func<TSource, Task<bool>> predicate)
|
|
|
- {
|
|
|
- Debug.Assert(predicate != null);
|
|
|
- Debug.Assert(source != null);
|
|
|
-
|
|
|
- this.source = source;
|
|
|
- this.predicate = predicate;
|
|
|
- }
|
|
|
-
|
|
|
- public override AsyncIterator<TSource> Clone()
|
|
|
- {
|
|
|
- return new SkipWhileAsyncIteratorWithTask<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public override async Task DisposeAsync()
|
|
|
- {
|
|
|
- if (enumerator != null)
|
|
|
- {
|
|
|
- await enumerator.DisposeAsync().ConfigureAwait(false);
|
|
|
- enumerator = null;
|
|
|
- }
|
|
|
-
|
|
|
- await base.DisposeAsync().ConfigureAwait(false);
|
|
|
- }
|
|
|
-
|
|
|
- protected override async Task<bool> MoveNextCore()
|
|
|
- {
|
|
|
- switch (state)
|
|
|
- {
|
|
|
- case AsyncIteratorState.Allocated:
|
|
|
- enumerator = source.GetAsyncEnumerator();
|
|
|
-
|
|
|
- // skip elements as requested
|
|
|
- while (await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- var element = enumerator.Current;
|
|
|
- if (!await predicate(element).ConfigureAwait(false))
|
|
|
- {
|
|
|
- doMoveNext = false;
|
|
|
- state = AsyncIteratorState.Iterating;
|
|
|
- goto case AsyncIteratorState.Iterating;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case AsyncIteratorState.Iterating:
|
|
|
- if (doMoveNext && await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (!doMoveNext)
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- doMoveNext = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- await DisposeAsync().ConfigureAwait(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private sealed class SkipWhileWithIndexAsyncIteratorWithTask<TSource> : AsyncIterator<TSource>
|
|
|
- {
|
|
|
- private readonly Func<TSource, int, Task<bool>> predicate;
|
|
|
- private readonly IAsyncEnumerable<TSource> source;
|
|
|
-
|
|
|
- private bool doMoveNext;
|
|
|
- private IAsyncEnumerator<TSource> enumerator;
|
|
|
- private int index;
|
|
|
-
|
|
|
- public SkipWhileWithIndexAsyncIteratorWithTask(IAsyncEnumerable<TSource> source, Func<TSource, int, Task<bool>> predicate)
|
|
|
- {
|
|
|
- Debug.Assert(predicate != null);
|
|
|
- Debug.Assert(source != null);
|
|
|
-
|
|
|
- this.source = source;
|
|
|
- this.predicate = predicate;
|
|
|
- }
|
|
|
-
|
|
|
- public override AsyncIterator<TSource> Clone()
|
|
|
- {
|
|
|
- return new SkipWhileWithIndexAsyncIteratorWithTask<TSource>(source, predicate);
|
|
|
- }
|
|
|
-
|
|
|
- public override async Task DisposeAsync()
|
|
|
- {
|
|
|
- if (enumerator != null)
|
|
|
- {
|
|
|
- await enumerator.DisposeAsync().ConfigureAwait(false);
|
|
|
- enumerator = null;
|
|
|
- }
|
|
|
-
|
|
|
- await base.DisposeAsync().ConfigureAwait(false);
|
|
|
- }
|
|
|
-
|
|
|
- protected override async Task<bool> MoveNextCore()
|
|
|
- {
|
|
|
- switch (state)
|
|
|
- {
|
|
|
- case AsyncIteratorState.Allocated:
|
|
|
- enumerator = source.GetAsyncEnumerator();
|
|
|
- index = -1;
|
|
|
-
|
|
|
- // skip elements as requested
|
|
|
- while (await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- checked
|
|
|
- {
|
|
|
- index++;
|
|
|
- }
|
|
|
-
|
|
|
- var element = enumerator.Current;
|
|
|
- if (!await predicate(element, index).ConfigureAwait(false))
|
|
|
- {
|
|
|
- doMoveNext = false;
|
|
|
- state = AsyncIteratorState.Iterating;
|
|
|
- goto case AsyncIteratorState.Iterating;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
-
|
|
|
- case AsyncIteratorState.Iterating:
|
|
|
- if (doMoveNext && await enumerator.MoveNextAsync().ConfigureAwait(false))
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- if (!doMoveNext)
|
|
|
- {
|
|
|
- current = enumerator.Current;
|
|
|
- doMoveNext = true;
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- await DisposeAsync().ConfigureAwait(false);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
}
|