// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. #nullable disable using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Labs.Linq; using System.Threading.Tasks; namespace FasterLinq { class Program { static void Main(string[] args) { var N = 4; Sync(N); Async1(N).Wait(); Async2(N).Wait(); } static void Sync(int n) { Console.WriteLine("IEnumerable and IFastEnumerable"); Console.WriteLine(); var sw = new Stopwatch(); var N = 10_000_000; var next = new Action(_ => { }); var slowRange = Enumerable.Range(0, N); var fastRange = FastEnumerable.Range(0, N); var brdgRange = slowRange.ToFastEnumerable(); var slow = slowRange.Where(x => x % 2 == 0).Select(x => x + 1); var fast = fastRange.Where(x => x % 2 == 0).Select(x => x + 1); var brdg = brdgRange.Where(x => x % 2 == 0).Select(x => x + 1).ToEnumerable(); Console.WriteLine("slow.Sum() = " + slow.Aggregate(0, (sum, x) => sum + x)); Console.WriteLine("fast.Sum() = " + fast.Aggregate(0, (sum, x) => sum + x)); Console.WriteLine("brdg.Sum() = " + brdg.Aggregate(0, (sum, x) => sum + x)); Console.WriteLine(); for (var i = 0; i < n; i++) { sw.Restart(); { slow.ForEach(next); } Console.WriteLine("SLOW " + sw.Elapsed); sw.Restart(); { fast.ForEach(next); } Console.WriteLine("FAST " + sw.Elapsed); sw.Restart(); { brdg.ForEach(next); } Console.WriteLine("BRDG " + sw.Elapsed); Console.WriteLine(); } Console.WriteLine(); } static async Task Async1(int n) { Console.WriteLine("IAsyncEnumerable and IAsyncFastEnumerable - Synchronous query operators"); Console.WriteLine(); var sw = new Stopwatch(); var N = 10_000_000; var next = new Func(_ => Task.CompletedTask); var slowRange = AsyncEnumerable.Range(0, N); var fastRange = AsyncFastEnumerable.Range(0, N); var brdgRange = slowRange.ToAsyncFastEnumerable(); var slow = slowRange.Where(x => x % 2 == 0).Select(x => x + 1); var fast = fastRange.Where(x => x % 2 == 0).Select(x => x + 1); var brdg = brdgRange.Where(x => x % 2 == 0).Select(x => x + 1).ToAsyncEnumerable(); Console.WriteLine("slow.Sum() = " + slow.Aggregate(0, (sum, x) => sum + x).Result); Console.WriteLine("fast.Sum() = " + fast.Aggregate(0, (sum, x) => sum + x).Result); Console.WriteLine("brdg.Sum() = " + brdg.Aggregate(0, (sum, x) => sum + x).Result); Console.WriteLine(); for (var i = 0; i < n; i++) { sw.Restart(); { await slow.ForEachAsync(next); } Console.WriteLine("SLOW " + sw.Elapsed); sw.Restart(); { await fast.ForEachAsync(next); } Console.WriteLine("FAST " + sw.Elapsed); sw.Restart(); { await brdg.ForEachAsync(next); } Console.WriteLine("BRDG " + sw.Elapsed); Console.WriteLine(); } Console.WriteLine(); } static async Task Async2(int n) { Console.WriteLine("IAsyncEnumerable and IAsyncFastEnumerable - Asynchronous query operators"); Console.WriteLine(); var sw = new Stopwatch(); var N = 10_000_000; var next = new Func(_ => Task.CompletedTask); var slowRange = AsyncEnumerable.Range(0, N); var fastRange = AsyncFastEnumerable.Range(0, N); var brdgRange = slowRange.ToAsyncFastEnumerable(); var slow = slowRange.Where(x => Task.FromResult(x % 2 == 0)).Select(x => Task.FromResult(x + 1)); var fast = fastRange.Where(x => Task.FromResult(x % 2 == 0)).Select(x => Task.FromResult(x + 1)); var brdg = brdgRange.Where(x => Task.FromResult(x % 2 == 0)).Select(x => Task.FromResult(x + 1)).ToAsyncEnumerable(); Console.WriteLine("slow.Sum() = " + slow.Aggregate(0, (sum, x) => sum + x).Result); Console.WriteLine("fast.Sum() = " + fast.Aggregate(0, (sum, x) => sum + x).Result); Console.WriteLine("brdg.Sum() = " + brdg.Aggregate(0, (sum, x) => sum + x).Result); Console.WriteLine(); for (var i = 0; i < n; i++) { sw.Restart(); { await slow.ForEachAsync(next); } Console.WriteLine("SLOW " + sw.Elapsed); sw.Restart(); { await fast.ForEachAsync(next); } Console.WriteLine("FAST " + sw.Elapsed); sw.Restart(); { await brdg.ForEachAsync(next); } Console.WriteLine("BRDG " + sw.Elapsed); Console.WriteLine(); } Console.WriteLine(); } } } namespace System { public interface IAsyncDisposable { Task DisposeAsync(); } } namespace System.Collections.Generic { public interface IAsyncEnumerable { IAsyncEnumerator GetAsyncEnumerator(); } public interface IAsyncEnumerator : IAsyncDisposable { Task MoveNextAsync(); T Current { get; } } public interface IFastEnumerable { IFastEnumerator GetEnumerator(); } public interface IFastEnumerator : IDisposable { T TryGetNext(out bool success); } public interface IAsyncFastEnumerable { IAsyncFastEnumerator GetAsyncEnumerator(); } public interface IAsyncFastEnumerator : IAsyncDisposable { Task WaitForNextAsync(); T TryGetNext(out bool success); } } namespace System.Labs.Linq { internal abstract class Iterator : IEnumerable, IEnumerator { private readonly int _threadId; internal int _state; protected T _current; protected Iterator() { _threadId = Environment.CurrentManagedThreadId; } public abstract Iterator Clone(); public virtual void Dispose() { _state = -1; } public IEnumerator GetEnumerator() { Iterator enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone(); enumerator._state = 1; return enumerator; } public abstract bool MoveNext(); public T Current => _current; object IEnumerator.Current => _current; IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public void Reset() => throw new NotSupportedException(); } internal abstract class AsyncIterator : IAsyncEnumerable, IAsyncEnumerator { private readonly int _threadId; internal int _state; protected T _current; protected AsyncIterator() { _threadId = Environment.CurrentManagedThreadId; } public abstract AsyncIterator Clone(); public virtual Task DisposeAsync() { _state = -1; return Task.CompletedTask; } public IAsyncEnumerator GetAsyncEnumerator() { AsyncIterator enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone(); enumerator._state = 1; return enumerator; } public abstract Task MoveNextAsync(); public T Current => _current; } internal abstract class FastIterator : IFastEnumerable, IFastEnumerator { private readonly int _threadId; internal int _state; protected FastIterator() { _threadId = Environment.CurrentManagedThreadId; } public abstract FastIterator Clone(); public virtual void Dispose() { _state = -1; } public IFastEnumerator GetEnumerator() { FastIterator enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone(); enumerator._state = 1; return enumerator; } public abstract T TryGetNext(out bool success); } internal abstract class AsyncFastIterator : IAsyncFastEnumerable, IAsyncFastEnumerator { private readonly int _threadId; internal int _state; protected AsyncFastIterator() { _threadId = Environment.CurrentManagedThreadId; } public abstract AsyncFastIterator Clone(); public virtual Task DisposeAsync() { _state = -1; return Task.CompletedTask; } public IAsyncFastEnumerator GetAsyncEnumerator() { AsyncFastIterator enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : Clone(); enumerator._state = 1; return enumerator; } public abstract Task WaitForNextAsync(); public abstract T TryGetNext(out bool success); } public static class Enumerable { public static R Aggregate(this IEnumerable source, R seed, Func aggregate) { var res = seed; foreach (var item in source) { res = aggregate(res, item); } return res; } public static IEnumerable Empty() => EmptyIterator.Instance; public static void ForEach(this IEnumerable source, Action next) { foreach (var item in source) { next(item); } } public static IEnumerable Range(int start, int count) => new RangeIterator(start, count); public static IEnumerable Select(this IEnumerable source, Func selector) => new SelectIterator(source, selector); public static IEnumerable Where(this IEnumerable source, Func predicate) => new WhereIterator(source, predicate); private sealed class EmptyIterator : IEnumerable, IEnumerator { public static readonly EmptyIterator Instance = new EmptyIterator(); public T Current => default(T); object IEnumerator.Current => default(T); public void Dispose() { } public IEnumerator GetEnumerator() => this; public bool MoveNext() => false; public void Reset() { } IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); } private sealed class RangeIterator : Iterator { private readonly int _start; private readonly int _end; private int _next; public RangeIterator(int start, int count) { _start = start; _end = start + count; } public override Iterator Clone() => new RangeIterator(_start, _end - _start); public override bool MoveNext() { switch (_state) { case 1: _next = _start; _state = 2; goto case 2; case 2: if (_next < _end) { _current = _next++; return true; } break; } return false; } } private sealed class SelectIterator : Iterator { private readonly IEnumerable _source; private readonly Func _selector; private IEnumerator _enumerator; public SelectIterator(IEnumerable source, Func selector) { _source = source; _selector = selector; } public override Iterator Clone() => new SelectIterator(_source, _selector); public override bool MoveNext() { switch (_state) { case 1: _enumerator = _source.GetEnumerator(); _state = 2; goto case 2; case 2: if (_enumerator.MoveNext()) { _current = _selector(_enumerator.Current); return true; } break; } return false; } public override void Dispose() => _enumerator?.Dispose(); } private sealed class WhereIterator : Iterator { private readonly IEnumerable _source; private readonly Func _predicate; private IEnumerator _enumerator; public WhereIterator(IEnumerable source, Func predicate) { _source = source; _predicate = predicate; } public override Iterator Clone() => new WhereIterator(_source, _predicate); public override bool MoveNext() { switch (_state) { case 1: _enumerator = _source.GetEnumerator(); _state = 2; goto case 2; case 2: while (_enumerator.MoveNext()) { var item = _enumerator.Current; if (_predicate(item)) { _current = item; return true; } } break; } return false; } public override void Dispose() => _enumerator?.Dispose(); } } public static class FastEnumerable { public static R Aggregate(this IFastEnumerable source, R seed, Func aggregate) { var res = seed; using (var e = source.GetEnumerator()) { while (true) { var item = e.TryGetNext(out var success); if (!success) { break; } res = aggregate(res, item); } } return res; } public static IFastEnumerable Empty() => EmptyIterator.Instance; public static void ForEach(this IFastEnumerable source, Action next) { using (var e = source.GetEnumerator()) { while (true) { var item = e.TryGetNext(out var success); if (!success) { break; } next(item); } } } public static IFastEnumerable Range(int start, int count) => new RangeIterator(start, count); public static IFastEnumerable Select(this IFastEnumerable source, Func selector) => new SelectFastIterator(source, selector); public static IFastEnumerable ToFastEnumerable(this IEnumerable source) => new EnumerableToFastEnumerable(source); public static IEnumerable ToEnumerable(this IFastEnumerable source) => new FastEnumerableToEnumerable(source); public static IFastEnumerable Where(this IFastEnumerable source, Func predicate) => new WhereFastIterator(source, predicate); private sealed class EmptyIterator : IFastEnumerable, IFastEnumerator { public static readonly EmptyIterator Instance = new EmptyIterator(); public void Dispose() { } public IFastEnumerator GetEnumerator() => this; public T TryGetNext(out bool success) { success = false; return default(T); } } private sealed class EnumerableToFastEnumerable : FastIterator { private readonly IEnumerable _source; private IEnumerator _enumerator; public EnumerableToFastEnumerable(IEnumerable source) { _source = source; } public override FastIterator Clone() => new EnumerableToFastEnumerable(_source); public override T TryGetNext(out bool success) { switch (_state) { case 1: _enumerator = _source.GetEnumerator(); _state = 2; goto case 2; case 2: success = _enumerator.MoveNext(); if (success) { return _enumerator.Current; } break; } success = false; return default(T); } public override void Dispose() => _enumerator?.Dispose(); } private sealed class FastEnumerableToEnumerable : Iterator { private readonly IFastEnumerable _source; private IFastEnumerator _enumerator; public FastEnumerableToEnumerable(IFastEnumerable source) { _source = source; } public override Iterator Clone() => new FastEnumerableToEnumerable(_source); public override bool MoveNext() { switch (_state) { case 1: _enumerator = _source.GetEnumerator(); _state = 2; goto case 2; case 2: _current = _enumerator.TryGetNext(out var success); return success; } return false; } public override void Dispose() => _enumerator?.Dispose(); } private sealed class RangeIterator : FastIterator { private readonly int _start; private readonly int _end; private int _next; public RangeIterator(int start, int count) { _start = start; _end = start + count; } public override FastIterator Clone() => new RangeIterator(_start, _end - _start); public override int TryGetNext(out bool success) { switch (_state) { case 1: _next = _start; _state = 2; goto case 2; case 2: if (_next < _end) { success = true; return _next++; } break; } success = false; return default(int); } } private sealed class SelectFastIterator : FastIterator { private readonly IFastEnumerable _source; private readonly Func _selector; private IFastEnumerator _enumerator; public SelectFastIterator(IFastEnumerable source, Func selector) { _source = source; _selector = selector; } public override FastIterator Clone() => new SelectFastIterator(_source, _selector); public override R TryGetNext(out bool success) { switch (_state) { case 1: _enumerator = _source.GetEnumerator(); _state = 2; goto case 2; case 2: var item = _enumerator.TryGetNext(out success); if (success) { return _selector(item); } break; } success = false; return default(R); } public override void Dispose() => _enumerator?.Dispose(); } private sealed class WhereFastIterator : FastIterator { private readonly IFastEnumerable _source; private readonly Func _predicate; private IFastEnumerator _enumerator; public WhereFastIterator(IFastEnumerable source, Func predicate) { _source = source; _predicate = predicate; } public override FastIterator Clone() => new WhereFastIterator(_source, _predicate); public override T TryGetNext(out bool success) { switch (_state) { case 1: _enumerator = _source.GetEnumerator(); _state = 2; goto case 2; case 2: while (true) { var item = _enumerator.TryGetNext(out success); if (!success) { break; } if (_predicate(item)) { return item; } } break; } success = false; return default(T); } public override void Dispose() => _enumerator?.Dispose(); } } public static class AsyncEnumerable { private static readonly Task True = Task.FromResult(true); private static readonly Task False = Task.FromResult(false); public static async Task Aggregate(this IAsyncEnumerable source, R seed, Func aggregate) { var res = seed; var e = source.GetAsyncEnumerator(); try { while (await e.MoveNextAsync().ConfigureAwait(false)) { res = aggregate(res, e.Current); } } finally { await e.DisposeAsync().ConfigureAwait(false); } return res; } public static async Task Aggregate(this IAsyncEnumerable source, R seed, Func> aggregate) { var res = seed; var e = source.GetAsyncEnumerator(); try { while (true) { while (await e.MoveNextAsync().ConfigureAwait(false)) { res = await aggregate(res, e.Current).ConfigureAwait(false); } } } finally { await e.DisposeAsync().ConfigureAwait(false); } return res; } public static IAsyncEnumerable Empty() => EmptyIterator.Instance; public static async Task ForEachAsync(this IAsyncEnumerable source, Func next) { var e = source.GetAsyncEnumerator(); try { while (await e.MoveNextAsync().ConfigureAwait(false)) { var item = e.Current; await next(item).ConfigureAwait(false); } } finally { await e.DisposeAsync().ConfigureAwait(false); } } public static IAsyncEnumerable Range(int start, int count) => new RangeIterator(start, count); public static IAsyncEnumerable Select(this IAsyncEnumerable source, Func selector) => new SelectIterator(source, selector); public static IAsyncEnumerable Select(this IAsyncEnumerable source, Func> selector) => new SelectIteratorWithTask(source, selector); public static IAsyncEnumerable Where(this IAsyncEnumerable source, Func predicate) => new WhereIterator(source, predicate); public static IAsyncEnumerable Where(this IAsyncEnumerable source, Func> predicate) => new WhereIteratorWithTask(source, predicate); private sealed class EmptyIterator : IAsyncEnumerable, IAsyncEnumerator { public static readonly EmptyIterator Instance = new EmptyIterator(); public T Current => default(T); public Task DisposeAsync() => Task.CompletedTask; public IAsyncEnumerator GetAsyncEnumerator() => this; public Task MoveNextAsync() => False; } private sealed class RangeIterator : AsyncIterator { private readonly int _start; private readonly int _end; private int _next; public RangeIterator(int start, int count) { _start = start; _end = start + count; } public override AsyncIterator Clone() => new RangeIterator(_start, _end - _start); public override Task MoveNextAsync() { switch (_state) { case 1: _next = _start; _state = 2; goto case 2; case 2: if (_next < _end) { _current = _next++; return True; } break; } return False; } } private sealed class SelectIterator : AsyncIterator { private readonly IAsyncEnumerable _source; private readonly Func _selector; private IAsyncEnumerator _enumerator; public SelectIterator(IAsyncEnumerable source, Func selector) { _source = source; _selector = selector; } public override AsyncIterator Clone() => new SelectIterator(_source, _selector); public override async Task MoveNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: if (await _enumerator.MoveNextAsync().ConfigureAwait(false)) { _current = _selector(_enumerator.Current); return true; } break; } return false; } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; } private sealed class SelectIteratorWithTask : AsyncIterator { private readonly IAsyncEnumerable _source; private readonly Func> _selector; private IAsyncEnumerator _enumerator; public SelectIteratorWithTask(IAsyncEnumerable source, Func> selector) { _source = source; _selector = selector; } public override AsyncIterator Clone() => new SelectIteratorWithTask(_source, _selector); public override async Task MoveNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: if (await _enumerator.MoveNextAsync().ConfigureAwait(false)) { _current = await _selector(_enumerator.Current).ConfigureAwait(false); return true; } break; } return false; } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; } private sealed class WhereIterator : AsyncIterator { private readonly IAsyncEnumerable _source; private readonly Func _predicate; private IAsyncEnumerator _enumerator; public WhereIterator(IAsyncEnumerable source, Func predicate) { _source = source; _predicate = predicate; } public override AsyncIterator Clone() => new WhereIterator(_source, _predicate); public override async Task MoveNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: while (await _enumerator.MoveNextAsync().ConfigureAwait(false)) { var item = _enumerator.Current; if (_predicate(item)) { _current = item; return true; } } break; } return false; } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; } private sealed class WhereIteratorWithTask : AsyncIterator { private readonly IAsyncEnumerable _source; private readonly Func> _predicate; private IAsyncEnumerator _enumerator; public WhereIteratorWithTask(IAsyncEnumerable source, Func> predicate) { _source = source; _predicate = predicate; } public override AsyncIterator Clone() => new WhereIteratorWithTask(_source, _predicate); public override async Task MoveNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: while (await _enumerator.MoveNextAsync().ConfigureAwait(false)) { var item = _enumerator.Current; if (await _predicate(item).ConfigureAwait(false)) { _current = item; return true; } } break; } return false; } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; } } public static class AsyncFastEnumerable { private static readonly Task True = Task.FromResult(true); private static readonly Task False = Task.FromResult(false); public static async Task Aggregate(this IAsyncFastEnumerable source, R seed, Func aggregate) { var res = seed; var e = source.GetAsyncEnumerator(); try { while (await e.WaitForNextAsync().ConfigureAwait(false)) { while (true) { var item = e.TryGetNext(out var success); if (!success) { break; } res = aggregate(res, item); } } } finally { await e.DisposeAsync().ConfigureAwait(false); } return res; } public static async Task Aggregate(this IAsyncFastEnumerable source, R seed, Func> aggregate) { var res = seed; var e = source.GetAsyncEnumerator(); try { while (await e.WaitForNextAsync().ConfigureAwait(false)) { while (true) { var item = e.TryGetNext(out var success); if (!success) { break; } res = await aggregate(res, item).ConfigureAwait(false); } } } finally { await e.DisposeAsync().ConfigureAwait(false); } return res; } public static IAsyncFastEnumerable Empty() => EmptyIterator.Instance; public static async Task ForEachAsync(this IAsyncFastEnumerable source, Func next) { var e = source.GetAsyncEnumerator(); try { while (await e.WaitForNextAsync().ConfigureAwait(false)) { while (true) { var item = e.TryGetNext(out var success); if (!success) { break; } await next(item).ConfigureAwait(false); } } } finally { await e.DisposeAsync().ConfigureAwait(false); } } public static IAsyncFastEnumerable Range(int start, int count) => new RangeIterator(start, count); public static IAsyncFastEnumerable Select(this IAsyncFastEnumerable source, Func selector) => new SelectFastIterator(source, selector); public static IAsyncFastEnumerable Select(this IAsyncFastEnumerable source, Func> selector) => new SelectFastIteratorWithTask(source, selector); public static IAsyncFastEnumerable ToAsyncFastEnumerable(this IAsyncEnumerable source) => new AsyncEnumerableToAsyncFastEnumerable(source); public static IAsyncEnumerable ToAsyncEnumerable(this IAsyncFastEnumerable source) => new AsyncFastEnumerableToAsyncEnumerable(source); public static IAsyncFastEnumerable Where(this IAsyncFastEnumerable source, Func predicate) => new WhereFastIterator(source, predicate); public static IAsyncFastEnumerable Where(this IAsyncFastEnumerable source, Func> predicate) => new WhereFastIteratorWithTask(source, predicate); private sealed class EmptyIterator : IAsyncFastEnumerable, IAsyncFastEnumerator { public static readonly EmptyIterator Instance = new EmptyIterator(); public Task DisposeAsync() => Task.CompletedTask; public IAsyncFastEnumerator GetAsyncEnumerator() => this; public T TryGetNext(out bool success) { success = false; return default(T); } public Task WaitForNextAsync() => False; } private sealed class AsyncEnumerableToAsyncFastEnumerable : AsyncFastIterator { private readonly IAsyncEnumerable _source; private IAsyncEnumerator _enumerator; private bool _hasNext; public AsyncEnumerableToAsyncFastEnumerable(IAsyncEnumerable source) { _source = source; } public override AsyncFastIterator Clone() => new AsyncEnumerableToAsyncFastEnumerable(_source); public override T TryGetNext(out bool success) { success = _hasNext; _hasNext = false; return success ? _enumerator.Current : default(T); } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; public override async Task WaitForNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: _hasNext = await _enumerator.MoveNextAsync().ConfigureAwait(false); return _hasNext; } return false; } } private sealed class AsyncFastEnumerableToAsyncEnumerable : AsyncIterator { private readonly IAsyncFastEnumerable _source; private IAsyncFastEnumerator _enumerator; public AsyncFastEnumerableToAsyncEnumerable(IAsyncFastEnumerable source) { _source = source; } public override AsyncIterator Clone() => new AsyncFastEnumerableToAsyncEnumerable(_source); public override async Task MoveNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: do { while (true) { var item = _enumerator.TryGetNext(out var success); if (!success) { break; } else { _current = item; return true; } } } while (await _enumerator.WaitForNextAsync().ConfigureAwait(false)); break; } return false; } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; } private sealed class RangeIterator : AsyncFastIterator { private readonly int _start; private readonly int _end; private int _next; public RangeIterator(int start, int count) { _start = start; _end = start + count; } public override AsyncFastIterator Clone() => new RangeIterator(_start, _end - _start); public override int TryGetNext(out bool success) { if (_state == 2 && _next < _end) { success = true; return _next++; } success = false; return default(int); } public override Task WaitForNextAsync() { switch (_state) { case 1: _next = _start; _state = 2; goto case 2; case 2: if (_next < _end) { return True; } break; } return False; } } private sealed class SelectFastIterator : AsyncFastIterator { private readonly IAsyncFastEnumerable _source; private readonly Func _selector; private IAsyncFastEnumerator _enumerator; public SelectFastIterator(IAsyncFastEnumerable source, Func selector) { _source = source; _selector = selector; } public override AsyncFastIterator Clone() => new SelectFastIterator(_source, _selector); public override R TryGetNext(out bool success) { if (_enumerator != null) { var item = _enumerator.TryGetNext(out success); if (success) { return _selector(item); } } success = false; return default(R); } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; public override Task WaitForNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: return _enumerator.WaitForNextAsync(); } return False; } } private sealed class SelectFastIteratorWithTask : AsyncFastIterator { private readonly IAsyncFastEnumerable _source; private readonly Func> _selector; private IAsyncFastEnumerator _enumerator; private bool _hasNext; private R _next; public SelectFastIteratorWithTask(IAsyncFastEnumerable source, Func> selector) { _source = source; _selector = selector; } public override AsyncFastIterator Clone() => new SelectFastIteratorWithTask(_source, _selector); public override R TryGetNext(out bool success) { success = _hasNext; _hasNext = false; return success ? _next : default(R); } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; public override async Task WaitForNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: do { while (true) { var item = _enumerator.TryGetNext(out var success); if (!success) { break; } else { _hasNext = true; _next = await _selector(item).ConfigureAwait(false); return true; } } } while (await _enumerator.WaitForNextAsync().ConfigureAwait(false)); break; } _hasNext = false; _next = default(R); return false; } } private sealed class WhereFastIterator : AsyncFastIterator { private readonly IAsyncFastEnumerable _source; private readonly Func _predicate; private IAsyncFastEnumerator _enumerator; public WhereFastIterator(IAsyncFastEnumerable source, Func predicate) { _source = source; _predicate = predicate; } public override AsyncFastIterator Clone() => new WhereFastIterator(_source, _predicate); public override T TryGetNext(out bool success) { if (_enumerator != null) { while (true) { var item = _enumerator.TryGetNext(out success); if (!success) { break; } if (_predicate(item)) { return item; } } } success = false; return default(T); } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; public override Task WaitForNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: return _enumerator.WaitForNextAsync(); } return False; } } private sealed class WhereFastIteratorWithTask : AsyncFastIterator { private readonly IAsyncFastEnumerable _source; private readonly Func> _predicate; private IAsyncFastEnumerator _enumerator; private bool _hasNext; private T _next; public WhereFastIteratorWithTask(IAsyncFastEnumerable source, Func> predicate) { _source = source; _predicate = predicate; } public override AsyncFastIterator Clone() => new WhereFastIteratorWithTask(_source, _predicate); public override T TryGetNext(out bool success) { success = _hasNext; _hasNext = false; return success ? _next : default(T); } public override Task DisposeAsync() => _enumerator?.DisposeAsync() ?? Task.CompletedTask; public override async Task WaitForNextAsync() { switch (_state) { case 1: _enumerator = _source.GetAsyncEnumerator(); _state = 2; goto case 2; case 2: do { while (true) { var item = _enumerator.TryGetNext(out var success); if (!success) { break; } else { if (await _predicate(item).ConfigureAwait(false)) { _hasNext = true; _next = item; return true; } } } } while (await _enumerator.WaitForNextAsync().ConfigureAwait(false)); break; } _hasNext = false; _next = default(T); return false; } } } }