From 6726ba07b30f1cb4560e27eb6584eda48ff3f604 Mon Sep 17 00:00:00 2001 From: JustFixMe Date: Tue, 28 Nov 2023 21:41:01 +0400 Subject: [PATCH] added Bind, Map and Match extensions generators --- Railway.SourceGenerator/IGeneratorExecutor.cs | 9 + Railway.SourceGenerator/ResultBindExecutor.cs | 84 +++ ...eGenerator.cs => ResultCombineExecutor.cs} | 20 +- .../ResultExtensionsExecutor.cs | 65 ++ Railway.SourceGenerator/ResultMapExecutor.cs | 83 +++ .../ResultMatchExecutor.cs | 87 +++ .../ResultMethodGenerator.cs | 28 + Railway/ResultExtensions.cs | 606 +----------------- 8 files changed, 365 insertions(+), 617 deletions(-) create mode 100644 Railway.SourceGenerator/IGeneratorExecutor.cs create mode 100644 Railway.SourceGenerator/ResultBindExecutor.cs rename Railway.SourceGenerator/{ResultCombineGenerator.cs => ResultCombineExecutor.cs} (93%) create mode 100644 Railway.SourceGenerator/ResultExtensionsExecutor.cs create mode 100644 Railway.SourceGenerator/ResultMapExecutor.cs create mode 100644 Railway.SourceGenerator/ResultMatchExecutor.cs create mode 100644 Railway.SourceGenerator/ResultMethodGenerator.cs diff --git a/Railway.SourceGenerator/IGeneratorExecutor.cs b/Railway.SourceGenerator/IGeneratorExecutor.cs new file mode 100644 index 0000000..f4c5e89 --- /dev/null +++ b/Railway.SourceGenerator/IGeneratorExecutor.cs @@ -0,0 +1,9 @@ +using System; +using Microsoft.CodeAnalysis; + +namespace Just.Railway.SourceGen; + +internal interface IGeneratorExecutor +{ + public abstract void Execute(SourceProductionContext context, Compilation source); +} diff --git a/Railway.SourceGenerator/ResultBindExecutor.cs b/Railway.SourceGenerator/ResultBindExecutor.cs new file mode 100644 index 0000000..81bdf4d --- /dev/null +++ b/Railway.SourceGenerator/ResultBindExecutor.cs @@ -0,0 +1,84 @@ +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Just.Railway.SourceGen; + +internal sealed class ResultBindExecutor : ResultExtensionsExecutor +{ + protected override string ExtensionType => "Bind"; + + protected override void GenerateMethodsForArgCount(StringBuilder sb, int argCount) + { + var templateArgNames = Enumerable.Range(1, argCount) + .Select(i => $"T{i}") + .ToImmutableArray(); + string separatedTemplateArgs = string.Join(", ", templateArgNames); + + sb.AppendLine($"#region <{separatedTemplateArgs}>"); + + string resultValueType = templateArgNames.Length == 1 ? separatedTemplateArgs : $"({separatedTemplateArgs})"; + string resultValueExpansion = GenerateResultValueExpansion(templateArgNames); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultBindExecutor)}}", "1.0.0.0")] + public static Result Bind<{{separatedTemplateArgs}}, R>(this in Result<{{resultValueType}}> result, Func<{{separatedTemplateArgs}}, Result> binding) + { + return result.State switch + { + ResultState.Success => binding({{resultValueExpansion}}), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(result)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultBindExecutor)}}", "1.0.0.0")] + public static Task> Bind<{{separatedTemplateArgs}}, R>(this in Result<{{resultValueType}}> result, Func<{{separatedTemplateArgs}}, Task>> binding) + { + return result.State switch + { + ResultState.Success => binding({{resultValueExpansion}}), + ResultState.Error => Task.FromResult>(result.Error!), + _ => throw new ResultNotInitializedException(nameof(result)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultBindExecutor)}}", "1.0.0.0")] + public static async Task> Bind<{{separatedTemplateArgs}}, R>(this Task> resultTask, Func<{{separatedTemplateArgs}}, Result> binding) + { + var result = await resultTask.ConfigureAwait(false); + return result.State switch + { + ResultState.Success => binding({{resultValueExpansion}}), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(resultTask)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultBindExecutor)}}", "1.0.0.0")] + public static async Task> Bind<{{separatedTemplateArgs}}, R>(this Task> resultTask, Func<{{separatedTemplateArgs}}, Task>> binding) + { + var result = await resultTask.ConfigureAwait(false); + return result.State switch + { + ResultState.Success => await binding({{resultValueExpansion}}).ConfigureAwait(false), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(resultTask)) + }; + } + """); + + sb.AppendLine("#endregion"); + } +} diff --git a/Railway.SourceGenerator/ResultCombineGenerator.cs b/Railway.SourceGenerator/ResultCombineExecutor.cs similarity index 93% rename from Railway.SourceGenerator/ResultCombineGenerator.cs rename to Railway.SourceGenerator/ResultCombineExecutor.cs index 5bf911e..9f36dc8 100644 --- a/Railway.SourceGenerator/ResultCombineGenerator.cs +++ b/Railway.SourceGenerator/ResultCombineExecutor.cs @@ -7,19 +7,9 @@ using Microsoft.CodeAnalysis; namespace Just.Railway.SourceGen; -[Generator] -public class ResultCombineGenerator : IIncrementalGenerator +internal sealed class ResultCombineExecutor : IGeneratorExecutor { - public ResultCombineGenerator() - { - } - - public void Initialize(IncrementalGeneratorInitializationContext context) - { - context.RegisterSourceOutput(context.CompilationProvider, Execute); - } - - private void Execute(SourceProductionContext context, Compilation source) + public void Execute(SourceProductionContext context, Compilation source) { var methods = GenerateCombineMethods(); var code = $$""" @@ -40,6 +30,7 @@ public class ResultCombineGenerator : IIncrementalGenerator context.AddSource("Result.Combine.g.cs", code); } + private string GenerateCombineMethods() { var sb = new StringBuilder(); @@ -95,7 +86,7 @@ public class ResultCombineGenerator : IIncrementalGenerator .Select(i => $"result{i}") .ToImmutableArray(); var argsDecl = string.Join(", ", args.Select(x => $"ResultState {x}")); - sb.AppendLine($"[GeneratedCodeAttribute(\"{nameof(ResultCombineGenerator)}\", \"1.0.0.0\")]"); + sb.AppendLine($"[GeneratedCodeAttribute(\"{nameof(ResultCombineExecutor)}\", \"1.0.0.0\")]"); sb.AppendLine($"private static IEnumerable GetBottom({argsDecl})"); sb.AppendLine("{"); foreach (var arg in args) @@ -185,7 +176,7 @@ public class ResultCombineGenerator : IIncrementalGenerator string returnExpr = $"return error is null ? new({resultExpansion}) : new(error);"; var method = $$""" - [GeneratedCodeAttribute("{{nameof(ResultCombineGenerator)}}", "1.0.0.0")] + [GeneratedCodeAttribute("{{nameof(ResultCombineExecutor)}}", "1.0.0.0")] [PureAttribute] public static {{resultTypeDecl}} Combine{{templateDecl}}({{paramDecl}}) { @@ -211,4 +202,3 @@ public class ResultCombineGenerator : IIncrementalGenerator } } } - diff --git a/Railway.SourceGenerator/ResultExtensionsExecutor.cs b/Railway.SourceGenerator/ResultExtensionsExecutor.cs new file mode 100644 index 0000000..7821f2d --- /dev/null +++ b/Railway.SourceGenerator/ResultExtensionsExecutor.cs @@ -0,0 +1,65 @@ +using System.Collections.Immutable; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Just.Railway.SourceGen; + +internal abstract class ResultExtensionsExecutor : IGeneratorExecutor +{ + public void Execute(SourceProductionContext context, Compilation source) + { + var methods = GenerateMethods(); + var code = $$""" + #nullable enable + using System; + using System.Collections.Generic; + using System.Diagnostics.Contracts; + using System.CodeDom.Compiler; + + namespace Just.Railway; + + public static partial class ResultExtensions + { + {{methods}} + } + """; + + context.AddSource($"ResultExtensions.{ExtensionType}.g.cs", code); + } + + private string GenerateMethods() + { + var sb = new StringBuilder(); + + for (int i = 1; i <= Constants.MaxResultTupleSize; i++) + { + GenerateMethodsForArgCount(sb, argCount: i); + } + + return sb.ToString(); + } + + protected string GenerateResultValueExpansion(ImmutableArray templateArgNames) + { + string resultExpansion; + if (templateArgNames.Length > 1) + { + var resultExpansionBuilder = new StringBuilder(); + for (int i = 1; i <= templateArgNames.Length; i++) + { + resultExpansionBuilder.Append($"result.Value.Item{i}, "); + } + resultExpansionBuilder.Remove(resultExpansionBuilder.Length - 2, 2); + resultExpansion = resultExpansionBuilder.ToString(); + } + else + { + resultExpansion = "result.Value"; + } + + return resultExpansion; + } + + protected abstract string ExtensionType { get; } + protected abstract void GenerateMethodsForArgCount(StringBuilder sb, int argCount); +} diff --git a/Railway.SourceGenerator/ResultMapExecutor.cs b/Railway.SourceGenerator/ResultMapExecutor.cs new file mode 100644 index 0000000..454c5d9 --- /dev/null +++ b/Railway.SourceGenerator/ResultMapExecutor.cs @@ -0,0 +1,83 @@ +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Just.Railway.SourceGen; + +internal sealed class ResultMapExecutor : ResultExtensionsExecutor +{ + protected override string ExtensionType => "Map"; + protected override void GenerateMethodsForArgCount(StringBuilder sb, int argCount) + { + var templateArgNames = Enumerable.Range(1, argCount) + .Select(i => $"T{i}") + .ToImmutableArray(); + string separatedTemplateArgs = string.Join(", ", templateArgNames); + + sb.AppendLine($"#region <{separatedTemplateArgs}>"); + + string resultValueType = templateArgNames.Length == 1 ? separatedTemplateArgs : $"({separatedTemplateArgs})"; + string resultValueExpansion = GenerateResultValueExpansion(templateArgNames); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMapExecutor)}}", "1.0.0.0")] + public static Result Map<{{separatedTemplateArgs}}, R>(this in Result<{{resultValueType}}> result, Func<{{separatedTemplateArgs}}, R> mapping) + { + return result.State switch + { + ResultState.Success => mapping({{resultValueExpansion}}), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(result)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMapExecutor)}}", "1.0.0.0")] + public static async Task> Map<{{separatedTemplateArgs}}, R>(this Result<{{resultValueType}}> result, Func<{{separatedTemplateArgs}}, Task> mapping) + { + return result.State switch + { + ResultState.Success => await mapping({{resultValueExpansion}}).ConfigureAwait(false), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(result)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMapExecutor)}}", "1.0.0.0")] + public static async Task> Map<{{separatedTemplateArgs}}, R>(this Task> resultTask, Func<{{separatedTemplateArgs}}, R> mapping) + { + var result = await resultTask.ConfigureAwait(false); + return result.State switch + { + ResultState.Success => mapping({{resultValueExpansion}}), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(resultTask)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMapExecutor)}}", "1.0.0.0")] + public static async Task> Map<{{separatedTemplateArgs}}, R>(this Task> resultTask, Func<{{separatedTemplateArgs}}, Task> mapping) + { + var result = await resultTask.ConfigureAwait(false); + return result.State switch + { + ResultState.Success => await mapping({{resultValueExpansion}}).ConfigureAwait(false), + ResultState.Error => result.Error!, + _ => throw new ResultNotInitializedException(nameof(resultTask)) + }; + } + """); + + sb.AppendLine("#endregion"); + } +} diff --git a/Railway.SourceGenerator/ResultMatchExecutor.cs b/Railway.SourceGenerator/ResultMatchExecutor.cs new file mode 100644 index 0000000..946e2cc --- /dev/null +++ b/Railway.SourceGenerator/ResultMatchExecutor.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Just.Railway.SourceGen; + +internal sealed class ResultMatchExecutor : ResultExtensionsExecutor +{ + protected override string ExtensionType => "Match"; + + protected override void GenerateMethodsForArgCount(StringBuilder sb, int argCount) + { + var templateArgNames = Enumerable.Range(1, argCount) + .Select(i => $"T{i}") + .ToImmutableArray(); + string separatedTemplateArgs = string.Join(", ", templateArgNames); + + sb.AppendLine($"#region <{separatedTemplateArgs}>"); + + string resultValueType = templateArgNames.Length == 1 ? separatedTemplateArgs : $"({separatedTemplateArgs})"; + string resultValueExpansion = GenerateResultValueExpansion(templateArgNames); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMatchExecutor)}}", "1.0.0.0")] + public static R Match<{{separatedTemplateArgs}}, R>(this in Result<{{resultValueType}}> result, Func<{{separatedTemplateArgs}}, R> onSuccess, Func onFailure) + { + return result.State switch + { + ResultState.Success => onSuccess({{resultValueExpansion}}), + ResultState.Error => onFailure(result.Error!), + _ => throw new ResultNotInitializedException(nameof(result)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMatchExecutor)}}", "1.0.0.0")] + public static Task Match<{{separatedTemplateArgs}}, R>(this in Result<{{resultValueType}}> result, Func<{{separatedTemplateArgs}}, Task> onSuccess, Func> onFailure) + { + return result.State switch + { + ResultState.Success => onSuccess({{resultValueExpansion}}), + ResultState.Error => onFailure(result.Error!), + _ => throw new ResultNotInitializedException(nameof(result)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMatchExecutor)}}", "1.0.0.0")] + public static async Task Match<{{separatedTemplateArgs}}, R>(this Task> resultTask, Func<{{separatedTemplateArgs}}, R> onSuccess, Func onFailure) + { + var result = await resultTask.ConfigureAwait(false); + return result.State switch + { + ResultState.Success => onSuccess({{resultValueExpansion}}), + ResultState.Error => onFailure(result.Error!), + _ => throw new ResultNotInitializedException(nameof(resultTask)) + }; + } + """); + + sb.AppendLine($$""" + [PureAttribute] + [GeneratedCodeAttribute("{{nameof(ResultMatchExecutor)}}", "1.0.0.0")] + public static async Task Match<{{separatedTemplateArgs}}, R>(this Task> resultTask, Func<{{separatedTemplateArgs}}, Task> onSuccess, Func> onFailure) + { + var result = await resultTask.ConfigureAwait(false); + var matchTask = result.State switch + { + ResultState.Success => onSuccess({{resultValueExpansion}}), + ResultState.Error => onFailure(result.Error!), + _ => throw new ResultNotInitializedException(nameof(resultTask)) + }; + return await matchTask.ConfigureAwait(false); + } + """); + + sb.AppendLine("#endregion"); + } +} diff --git a/Railway.SourceGenerator/ResultMethodGenerator.cs b/Railway.SourceGenerator/ResultMethodGenerator.cs new file mode 100644 index 0000000..8e917c6 --- /dev/null +++ b/Railway.SourceGenerator/ResultMethodGenerator.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis; + +namespace Just.Railway.SourceGen; + +[Generator] +public class ResultMethodGenerator : IIncrementalGenerator +{ + private readonly IEnumerable _executors = new IGeneratorExecutor[] + { + new ResultCombineExecutor(), + new ResultMatchExecutor(), + new ResultMapExecutor(), + new ResultBindExecutor(), + }; + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + foreach (var executor in _executors) + { + context.RegisterSourceOutput(context.CompilationProvider, executor.Execute); + } + } +} diff --git a/Railway/ResultExtensions.cs b/Railway/ResultExtensions.cs index 64c5443..19d4230 100644 --- a/Railway/ResultExtensions.cs +++ b/Railway/ResultExtensions.cs @@ -1,10 +1,9 @@ namespace Just.Railway; -public static class ResultExtensions +public static partial class ResultExtensions { - #region Match + #region Match<> - #region <> [Pure] public static R Match(this in Result result, Func onSuccess, Func onFailure) { @@ -52,211 +51,7 @@ public static class ResultExtensions #endregion - #region - [Pure] - public static R Match(this in Result result, Func onSuccess, Func onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static Task Match(this in Result result, Func> onSuccess, Func> onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func onSuccess, Func onFailure) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => onSuccess(result.Value), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func> onSuccess, Func> onFailure) - { - var result = await resultTask.ConfigureAwait(false); - var matchTask = result.State switch - { - ResultState.Success => onSuccess(result.Value), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - return await matchTask.ConfigureAwait(false); - } - - #endregion - - #region - [Pure] - public static R Match(this in Result<(T1, T2)> result, Func onSuccess, Func onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static Task Match(this in Result<(T1, T2)> result, Func> onSuccess, Func> onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func onSuccess, Func onFailure) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func> onSuccess, Func> onFailure) - { - var result = await resultTask.ConfigureAwait(false); - var matchTask = result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - return await matchTask.ConfigureAwait(false); - } - - #endregion - - #region - [Pure] - public static R Match(this in Result<(T1, T2, T3)> result, Func onSuccess, Func onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static Task Match(this in Result<(T1, T2, T3)> result, Func> onSuccess, Func> onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func onSuccess, Func onFailure) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func> onSuccess, Func> onFailure) - { - var result = await resultTask.ConfigureAwait(false); - var matchTask = result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - return await matchTask.ConfigureAwait(false); - } - - #endregion - - #region - [Pure] - public static R Match(this in Result<(T1, T2, T3, T4)> result, Func onSuccess, Func onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static Task Match(this in Result<(T1, T2, T3, T4)> result, Func> onSuccess, Func> onFailure) - { - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func onSuccess, Func onFailure) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task Match(this Task> resultTask, Func> onSuccess, Func> onFailure) - { - var result = await resultTask.ConfigureAwait(false); - var matchTask = result.State switch - { - ResultState.Success => onSuccess(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => onFailure(result.Error!), - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - return await matchTask.ConfigureAwait(false); - } - - #endregion - - #endregion - - #region Map - - #region <> + #region Map<> [Pure] public static Result Map(this in Result result, Func mapping) @@ -306,211 +101,7 @@ public static class ResultExtensions #endregion - #region - - [Pure] - public static Result Map(this in Result result, Func mapping) - { - return result.State switch - { - ResultState.Success => mapping(result.Value), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Result result, Func> mapping) - { - return result.State switch - { - ResultState.Success => await mapping(result.Value).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => mapping(result.Value), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func> mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await mapping(result.Value).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #region - - [Pure] - public static Result Map(this in Result<(T1, T2)> result, Func mapping) - { - return result.State switch - { - ResultState.Success => mapping(result.Value.Item1, result.Value.Item2), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Result<(T1, T2)> result, Func> mapping) - { - return result.State switch - { - ResultState.Success => await mapping(result.Value.Item1, result.Value.Item2).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => mapping(result.Value.Item1, result.Value.Item2), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func> mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await mapping(result.Value.Item1, result.Value.Item2).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #region - - [Pure] - public static Result Map(this in Result<(T1, T2, T3)> result, Func mapping) - { - return result.State switch - { - ResultState.Success => mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Result<(T1, T2, T3)> result, Func> mapping) - { - return result.State switch - { - ResultState.Success => await mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func> mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #region - - [Pure] - public static Result Map(this in Result<(T1, T2, T3, T4)> result, Func mapping) - { - return result.State switch - { - ResultState.Success => mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Result<(T1, T2, T3, T4)> result, Func> mapping) - { - return result.State switch - { - ResultState.Success => await mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - [Pure] - public static async Task> Map(this Task> resultTask, Func> mapping) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await mapping(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #endregion - - #region Bind - - #region <> + #region Bind<> [Pure] public static Result Bind(this in Result result, Func binding) @@ -600,195 +191,6 @@ public static class ResultExtensions #endregion - #region - - [Pure] - public static Result Bind(this in Result result, Func> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static Task> Bind(this in Result result, Func>> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value), - ResultState.Error => Task.FromResult>(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => binding(result.Value), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func>> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await binding(result.Value).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #region - - [Pure] - public static Result Bind(this in Result<(T1, T2)> result, Func> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static Task> Bind(this in Result<(T1, T2)> result, Func>> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2), - ResultState.Error => Task.FromResult>(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func>> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await binding(result.Value.Item1, result.Value.Item2).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #region - - [Pure] - public static Result Bind(this in Result<(T1, T2, T3)> result, Func> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static Task> Bind(this in Result<(T1, T2, T3)> result, Func>> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => Task.FromResult>(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2, result.Value.Item3), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func>> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await binding(result.Value.Item1, result.Value.Item2, result.Value.Item3).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - - #region - - [Pure] - public static Result Bind(this in Result<(T1, T2, T3, T4)> result, Func> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static Task> Bind(this in Result<(T1, T2, T3, T4)> result, Func>> binding) - { - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => Task.FromResult>(result.Error!), - _ => throw new ResultNotInitializedException(nameof(result)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => binding(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - [Pure] - public static async Task> Bind(this Task> resultTask, Func>> binding) - { - var result = await resultTask.ConfigureAwait(false); - return result.State switch - { - ResultState.Success => await binding(result.Value.Item1, result.Value.Item2, result.Value.Item3, result.Value.Item4).ConfigureAwait(false), - ResultState.Error => result.Error!, - _ => throw new ResultNotInitializedException(nameof(resultTask)) - }; - } - - #endregion - #endregion - #region Append #region <>