From 03f53844b25230f799ba44ca9d45c0486766ada3 Mon Sep 17 00:00:00 2001 From: Brian Friesen Date: Tue, 2 May 2023 22:36:17 -0400 Subject: [PATCH] Add optional onNone parameter --- .../Rescue_methods.cs | 24 +++++++ RandomSkunk.Results/Operations/Rescue.cs | 64 ++++++++++++++++--- 2 files changed, 78 insertions(+), 10 deletions(-) diff --git a/RandomSkunk.Results.UnitTests/Rescue_methods.cs b/RandomSkunk.Results.UnitTests/Rescue_methods.cs index 7aca68c..44332f7 100644 --- a/RandomSkunk.Results.UnitTests/Rescue_methods.cs +++ b/RandomSkunk.Results.UnitTests/Rescue_methods.cs @@ -202,6 +202,17 @@ public void Given_None_Returns_source() actual.Should().Be(sourceResult); } + [Fact] + public void Given_None_Returns_result_from_onNone_rescue_function() + { + var sourceResult = Maybe.None; + var rescueResult = Maybe.Fail("b"); + + var actual = sourceResult.Rescue(error => Maybe.Fail("a"), () => rescueResult); + + actual.Should().Be(rescueResult); + } + [Fact] public void Given_IsFail_Returns_result_from_rescue_function() { @@ -257,6 +268,19 @@ public async Task Given_IsNone_Returns_source() actual.Should().Be(sourceResult); } + [Fact] + public async Task Given_IsNone_Returns_result_from_onNone_rescue_function() + { + var sourceResult = Maybe.None; + var rescueResult = Maybe.Fail("b"); + + var actual = await sourceResult.Rescue( + error => Task.FromResult(Maybe.Fail("a")), + () => Task.FromResult(rescueResult)); + + actual.Should().Be(rescueResult); + } + [Fact] public async Task Given_IsFail_Returns_result_from_rescue_function() { diff --git a/RandomSkunk.Results/Operations/Rescue.cs b/RandomSkunk.Results/Operations/Rescue.cs index 8b7af11..c102fc9 100644 --- a/RandomSkunk.Results/Operations/Rescue.cs +++ b/RandomSkunk.Results/Operations/Rescue.cs @@ -133,12 +133,14 @@ public partial struct Maybe { /// /// Rescues a Fail result by returning the output of the function. If the current result is - /// Success, nothing happens and the current result is returned. + /// Success, nothing happens and the current result is returned. Rescues a None result if the optional + /// function is provided. /// /// The function that rescues a failed operation. + /// An optional function that rescues a None result. /// The output of the function if the current result is Fail, or the same result if /// it is Success. - public Maybe Rescue(Func> onFail) + public Maybe Rescue(Func> onFail, Func>? onNone = null) { if (onFail is null) throw new ArgumentNullException(nameof(onFail)); @@ -157,18 +159,35 @@ public Maybe Rescue(Func> onFail) return Fail(ex, Error.GetMessageForExceptionThrownInCallback(nameof(onFail))); } } + else if (_outcome == Outcome.None && onNone is not null) + { + try + { + return onNone(); + } + catch (TaskCanceledException ex) + { + return Errors.Canceled(ex); + } + catch (Exception ex) + { + return Fail(ex, Error.GetMessageForExceptionThrownInCallback(nameof(onNone))); + } + } return this; } /// /// Rescues a Fail result by returning the output of the function. If the current result is - /// Success, nothing happens and the current result is returned. + /// Success, nothing happens and the current result is returned. Rescues a None result if the optional + /// function is provided. /// /// The function that rescues a failed operation. + /// An optional function that rescues a None result. /// The output of the function if the current result is Fail, or the same result if /// it is Success. - public async Task> Rescue(Func>> onFail) + public async Task> Rescue(Func>> onFail, Func>>? onNone = null) { if (onFail is null) throw new ArgumentNullException(nameof(onFail)); @@ -187,6 +206,21 @@ public async Task> Rescue(Func>> onFail) return Fail(ex, Error.GetMessageForExceptionThrownInCallback(nameof(onFail))); } } + else if (_outcome == Outcome.None && onNone is not null) + { + try + { + return await onNone(); + } + catch (TaskCanceledException ex) + { + return Errors.Canceled(ex); + } + catch (Exception ex) + { + return Fail(ex, Error.GetMessageForExceptionThrownInCallback(nameof(onNone))); + } + } return this; } @@ -243,25 +277,35 @@ public static async Task> Rescue(this Task> sourceResult, /// /// Rescues a Fail result by returning the output of the function. If the current result is - /// Success, nothing happens and the current result is returned. + /// Success, nothing happens and the current result is returned. Rescues a None result if the optional + /// function is provided. /// /// The type of the source result value. /// The source result. /// The function that rescues a failed operation. + /// An optional function that rescues a None result. /// The output of the function if the current result is Fail, or the same result if /// it is Success. - public static async Task> Rescue(this Task> sourceResult, Func> onFail) => - (await sourceResult.ConfigureAwait(ContinueOnCapturedContext)).Rescue(onFail); + public static async Task> Rescue( + this Task> sourceResult, + Func> onFail, + Func>? onNone = null) => + (await sourceResult.ConfigureAwait(ContinueOnCapturedContext)).Rescue(onFail, onNone); /// /// Rescues a Fail result by returning the output of the function. If the current result is - /// Success, nothing happens and the current result is returned. + /// Success, nothing happens and the current result is returned. Rescues a None result if the optional + /// function is provided. /// /// The type of the source result value. /// The source result. /// The function that rescues a failed operation. + /// An optional function that rescues a None result. /// The output of the function if the current result is Fail, or the same result if /// it is Success. - public static async Task> Rescue(this Task> sourceResult, Func>> onFail) => - await (await sourceResult.ConfigureAwait(ContinueOnCapturedContext)).Rescue(onFail).ConfigureAwait(ContinueOnCapturedContext); + public static async Task> Rescue( + this Task> sourceResult, + Func>> onFail, + Func>>? onNone = null) => + await (await sourceResult.ConfigureAwait(ContinueOnCapturedContext)).Rescue(onFail, onNone).ConfigureAwait(ContinueOnCapturedContext); }