diff --git a/src/MoreAsyncLINQ.Generators/FoldGenerator.cs b/src/MoreAsyncLINQ.Generators/FoldGenerator.cs
new file mode 100644
index 0000000..2edf90d
--- /dev/null
+++ b/src/MoreAsyncLINQ.Generators/FoldGenerator.cs
@@ -0,0 +1,176 @@
+using System.CodeDom.Compiler;
+using System.IO;
+using Microsoft.CodeAnalysis;
+
+namespace MoreAsyncLINQ.Generators;
+
+[Generator]
+public class FoldGenerator : IIncrementalGenerator
+{
+ public void Initialize(IncrementalGeneratorInitializationContext context) =>
+ context.RegisterPostInitializationOutput(postInitializationContext =>
+ {
+ var source = GenerateOverloads();
+ postInitializationContext.AddSource("MoreAsyncEnumerable.Fold.g.cs", source);
+ });
+
+ private string GenerateOverloads()
+ {
+ using var stringWriter = new StringWriter();
+ using var writer = Writers.CreateSourceWriter(stringWriter);
+
+ using (writer.BeginBracketsScope())
+ using (writer.BeginIndentScope())
+ {
+ // Sync overloads: arity 1-16
+ for (var arity = 1; arity <= 16; arity++)
+ {
+ GenerateSyncOverload(writer, arity);
+ writer.WriteLine();
+ }
+
+ // Async overloads: arity 1-15 (limited by Func delegate having max 16 input params,
+ // and async needs CancellationToken as additional input)
+ for (var arity = 1; arity <= 15; arity++)
+ {
+ GenerateAsyncOverload(writer, arity);
+
+ if (arity < 15)
+ {
+ writer.WriteLine();
+ }
+ }
+ }
+
+ return stringWriter.ToString();
+ }
+
+ private void GenerateSyncOverload(IndentedTextWriter writer, int arity)
+ {
+ WriteXmlDocumentation(writer, arity);
+ WriteMethodSignature(writer, arity, isAsync: false);
+
+ using (writer.BeginBracketsScope())
+ using (writer.BeginIndentScope())
+ {
+ WriteNullChecks(writer);
+ writer.WriteLine();
+
+ writer.WriteLine("return Core(source, folder, cancellationToken);");
+ writer.WriteLine();
+ WriteCoreMethod(writer, arity, isAsync: false);
+ }
+ }
+
+ private void GenerateAsyncOverload(IndentedTextWriter writer, int arity)
+ {
+ WriteXmlDocumentation(writer, arity);
+ WriteMethodSignature(writer, arity, isAsync: true);
+
+ using (writer.BeginBracketsScope())
+ using (writer.BeginIndentScope())
+ {
+ WriteNullChecks(writer);
+ writer.WriteLine();
+
+ writer.WriteLine("return Core(source, folder, cancellationToken);");
+ writer.WriteLine();
+ WriteCoreMethod(writer, arity, isAsync: true);
+ }
+ }
+
+ private void WriteXmlDocumentation(IndentedTextWriter writer, int arity)
+ {
+ writer = Writers.CreateXmlDocWriter(writer);
+
+ writer.WriteLine("");
+ writer.WriteLine("Returns the result of applying a function to a sequence of");
+ writer.WriteLine($"{arity} element{(arity == 1 ? "" : "s")}.");
+ writer.WriteLine("");
+ writer.WriteLine("");
+ writer.WriteLine("This operator uses immediate execution and effectively buffers");
+ writer.WriteLine("as many items of the source sequence as necessary.");
+ writer.WriteLine("");
+ writer.WriteLine("Type of element in the source sequence");
+ writer.WriteLine("Type of the result");
+ writer.WriteLine("The sequence of items to fold.");
+ writer.WriteLine("Function to apply to the elements in the sequence.");
+ writer.WriteLine("The optional cancellation token to be used for cancelling the sequence at any time.");
+ writer.WriteLine("The folded value returned by .");
+ writer.WriteLine(" is null");
+ writer.WriteLine(" is null");
+ writer.WriteLine($" does not contain exactly {arity} element{(arity == 1 ? "" : "s")}");
+ }
+
+ private void WriteMethodSignature(IndentedTextWriter writer, int arity, bool isAsync)
+ {
+ var folderType = GetFolderFuncType(arity, isAsync);
+
+ writer.WriteLine("public static ValueTask FoldAsync(");
+
+ using var _ = writer.BeginIndentScope();
+
+ writer.WriteLine("this IAsyncEnumerable source,");
+ writer.WriteLine($"{folderType} folder,");
+ writer.WriteLine("CancellationToken cancellationToken = default)");
+ }
+
+ private void WriteNullChecks(IndentedTextWriter writer)
+ {
+ Writers.WriteNullCheck(writer, "source");
+ Writers.WriteNullCheck(writer, "folder");
+ }
+
+ private void WriteCoreMethod(IndentedTextWriter writer, int arity, bool isAsync)
+ {
+ var folderType = GetFolderFuncType(arity, isAsync);
+
+ writer.WriteLine("static async ValueTask Core(");
+
+ using (writer.BeginIndentScope())
+ {
+ writer.WriteLine("IAsyncEnumerable source,");
+ writer.WriteLine($"{folderType} folder,");
+ writer.WriteLine("CancellationToken cancellationToken)");
+ }
+
+ using (writer.BeginBracketsScope())
+ using (writer.BeginIndentScope())
+ {
+ writer.WriteLine($"var elements = await GetFoldElementsAsync(source, count: {arity}, cancellationToken);");
+ writer.WriteLine(isAsync ? "return await folder(" : "return folder(");
+
+ using (writer.BeginIndentScope())
+ {
+ for (var index = 0; index < arity; index++)
+ {
+ var isLast = index == arity - 1;
+
+ if (isAsync)
+ {
+ writer.WriteLine($"elements[{index}],");
+ }
+ else
+ {
+ writer.WriteLine(isLast ? $"elements[{index}]);" : $"elements[{index}],");
+ }
+ }
+
+ if (isAsync)
+ {
+ writer.WriteLine("cancellationToken);");
+ }
+ }
+ }
+ }
+
+ private static string GetFolderFuncType(int arity, bool isAsync)
+ {
+ var sourceParams = string.Join(", ", System.Linq.Enumerable.Repeat("TSource", arity));
+
+ return isAsync
+ ? $"Func<{sourceParams}, CancellationToken, ValueTask>"
+ : $"Func<{sourceParams}, TResult>";
+ }
+}
+
diff --git a/src/MoreAsyncLINQ/Operators/Fold.cs b/src/MoreAsyncLINQ/Operators/Fold.cs
index a1043d5..19e5675 100644
--- a/src/MoreAsyncLINQ/Operators/Fold.cs
+++ b/src/MoreAsyncLINQ/Operators/Fold.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -8,1421 +7,6 @@ namespace MoreAsyncLINQ;
static partial class MoreAsyncEnumerable
{
- ///
- /// Returns the result of applying a function to a sequence of
- /// 1 element.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 1 element
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 1, cancellationToken);
- return folder(elements[0]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 2 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 2 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 2, cancellationToken);
- return folder(
- elements[0],
- elements[1]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 3 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 3 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 3, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 4 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 4 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 4, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 5 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 5 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 5, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 6 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 6 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 6, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 7 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 7 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 7, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 8 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 8 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 8, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 9 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 9 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 9, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 10 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 10 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 10, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 11 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 11 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 11, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 12 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 12 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 12, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 13 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 13 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 13, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 14 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 14 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 14, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12],
- elements[13]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 15 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 15 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 15, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12],
- elements[13],
- elements[14]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 16 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 16, cancellationToken);
- return folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12],
- elements[13],
- elements[14],
- elements[15]);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// one element.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 1, cancellationToken);
- return await folder(elements[0], cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 2 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 2, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 3 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 3, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 4 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 4, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 5 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 5, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 6 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 6, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 7 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 7, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 8 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 8, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 9 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 9, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 10 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 10, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 11 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 11, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 12 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 12, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 13 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 13, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 14 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 14, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12],
- elements[13],
- cancellationToken);
- }
- }
-
- ///
- /// Returns the result of applying a function to a sequence of
- /// 15 elements.
- ///
- ///
- /// This operator uses immediate execution and effectively buffers
- /// as many items of the source sequence as necessary.
- ///
- /// Type of element in the source sequence
- /// Type of the result
- /// The sequence of items to fold.
- /// Function to apply to the elements in the sequence.
- /// The optional cancellation token to be used for cancelling the sequence at any time.
- /// The folded value returned by .
- /// is null
- /// is null
- /// does not contain exactly 16 elements
- public static ValueTask FoldAsync(
- this IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken = default)
- {
- if (source is null) throw new ArgumentNullException(nameof(source));
- if (folder is null) throw new ArgumentNullException(nameof(folder));
-
- return Core(source, folder, cancellationToken);
-
- static async ValueTask Core(
- IAsyncEnumerable source,
- Func> folder,
- CancellationToken cancellationToken)
- {
- var elements = await GetFoldElementsAsync(source, count: 15, cancellationToken);
- return await folder(
- elements[0],
- elements[1],
- elements[2],
- elements[3],
- elements[4],
- elements[5],
- elements[6],
- elements[7],
- elements[8],
- elements[9],
- elements[10],
- elements[11],
- elements[12],
- elements[13],
- elements[14],
- cancellationToken);
- }
- }
-
private static async ValueTask GetFoldElementsAsync(
IAsyncEnumerable source,
int count,
@@ -1436,4 +20,4 @@ private static async ValueTask GetFoldElementsAsync(
return elements;
}
-}
\ No newline at end of file
+}
diff --git a/tests/MoreAsyncLINQ.Tests/Operators/FoldTests.cs b/tests/MoreAsyncLINQ.Tests/Operators/FoldTests.cs
new file mode 100644
index 0000000..2069f2f
--- /dev/null
+++ b/tests/MoreAsyncLINQ.Tests/Operators/FoldTests.cs
@@ -0,0 +1,412 @@
+using MoreLinq;
+
+namespace MoreAsyncLINQ.Tests;
+
+// ReSharper disable StringLiteralTypo
+
+public class FoldTests : AsyncEnumerableTests
+{
+ [Fact]
+ public void InvalidInputs_Throws()
+ {
+ Assert.Throws("source", () => MoreAsyncEnumerable.FoldAsync(null!, _ => 0));
+ Assert.Throws("folder", () => AsyncEnumerable.Empty().FoldAsync((Func)null!));
+
+ Assert.Throws("source", () => MoreAsyncEnumerable.FoldAsync(null!, (_, _) => ValueTask.FromResult(0)));
+ Assert.Throws("folder", () => AsyncEnumerable.Empty().FoldAsync((Func>)null!));
+
+ Assert.Throws("source", () => MoreAsyncEnumerable.FoldAsync(null!, (a, b) => a + b));
+ Assert.Throws("folder", () => AsyncEnumerable.Empty().FoldAsync((Func)null!));
+
+ Assert.Throws("source", () => MoreAsyncEnumerable.FoldAsync(null!, (a, b, _) => ValueTask.FromResult(a + b)));
+ Assert.Throws("folder", () => AsyncEnumerable.Empty().FoldAsync((Func>)null!));
+
+ Assert.Throws("source", () => MoreAsyncEnumerable.FoldAsync(null!, (a, b, c, d) => a + b + c + d));
+ Assert.Throws("folder", () => AsyncEnumerable.Empty().FoldAsync((Func)null!));
+
+ Assert.Throws("source", () => MoreAsyncEnumerable.FoldAsync