Skip to content

Commit 8216bde

Browse files
committed
Added more monad chaining options for Result<T>
1 parent 53e9c0d commit 8216bde

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/DotNext/Result.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,30 @@ private Result<TResult> Convert<TResult, TConverter>(TConverter converter)
231231
return result;
232232
}
233233

234+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
235+
private Result<TResult> ConvertResult<TResult, TConverter>(TConverter converter)
236+
where TConverter : struct, ISupplier<T, Result<TResult>>
237+
{
238+
Result<TResult> result;
239+
if (exception is null)
240+
{
241+
try
242+
{
243+
result = converter.Invoke(value);
244+
}
245+
catch (Exception e)
246+
{
247+
result = new(e);
248+
}
249+
}
250+
else
251+
{
252+
result = new(exception);
253+
}
254+
255+
return result;
256+
}
257+
234258
/// <summary>
235259
/// If the successful result is present, apply the provided mapping function hiding any exception
236260
/// caused by the converter.
@@ -241,6 +265,16 @@ private Result<TResult> Convert<TResult, TConverter>(TConverter converter)
241265
public Result<TResult> Convert<TResult>(Converter<T, TResult> converter)
242266
=> Convert<TResult, DelegatingConverter<T, TResult>>(converter);
243267

268+
/// <summary>
269+
/// If successful result is present, apply the provided mapping function. If not,
270+
/// forward the exception.
271+
/// </summary>
272+
/// <param name="converter">A mapping function to be applied to the value, if present.</param>
273+
/// <typeparam name="TResult">The type of the result of the mapping function.</typeparam>
274+
/// <returns>The conversion result.</returns>
275+
public Result<TResult> Convert<TResult>(Converter<T, Result<TResult>> converter)
276+
=> ConvertResult<TResult, DelegatingConverter<T, Result<TResult>>>(converter);
277+
244278
/// <summary>
245279
/// If the successful result is present, apply the provided mapping function hiding any exception
246280
/// caused by the converter.
@@ -252,6 +286,17 @@ public Result<TResult> Convert<TResult>(Converter<T, TResult> converter)
252286
public unsafe Result<TResult> Convert<TResult>(delegate*<T, TResult> converter)
253287
=> Convert<TResult, Supplier<T, TResult>>(converter);
254288

289+
/// <summary>
290+
/// If successful result is present, apply the provided mapping function. If not,
291+
/// forward the exception.
292+
/// </summary>
293+
/// <param name="converter">A mapping function to be applied to the value, if present.</param>
294+
/// <typeparam name="TResult">The type of the result of the mapping function.</typeparam>
295+
/// <returns>The conversion result.</returns>
296+
[CLSCompliant(false)]
297+
public unsafe Result<TResult> Convert<TResult>(delegate*<T, Result<TResult>> converter)
298+
=> ConvertResult<TResult, Supplier<T, Result<TResult>>>(converter);
299+
255300
/// <summary>
256301
/// Attempts to extract value from the container if it is present.
257302
/// </summary>
@@ -563,6 +608,11 @@ private Result<TResult, TError> Convert<TResult, TConverter>(TConverter converte
563608
where TConverter : struct, ISupplier<T, TResult>
564609
=> IsSuccessful ? new(converter.Invoke(value)) : new(Error);
565610

611+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
612+
private Result<TResult, TError> ConvertResult<TResult, TConverter>(TConverter converter)
613+
where TConverter : struct, ISupplier<T, Result<TResult, TError>>
614+
=> IsSuccessful ? converter.Invoke(value) : new(Error);
615+
566616
/// <summary>
567617
/// If the successful result is present, apply the provided mapping function hiding any exception
568618
/// caused by the converter.
@@ -573,6 +623,16 @@ private Result<TResult, TError> Convert<TResult, TConverter>(TConverter converte
573623
public Result<TResult, TError> Convert<TResult>(Converter<T, TResult> converter)
574624
=> Convert<TResult, DelegatingConverter<T, TResult>>(converter);
575625

626+
/// <summary>
627+
/// If successful result is present, apply the provided mapping function. If not,
628+
/// forward the error.
629+
/// </summary>
630+
/// <param name="converter">A mapping function to be applied to the value, if present.</param>
631+
/// <typeparam name="TResult">The type of the result of the mapping function.</typeparam>
632+
/// <returns>The conversion result.</returns>
633+
public Result<TResult, TError> Convert<TResult>(Converter<T, Result<TResult, TError>> converter)
634+
=> ConvertResult<TResult, DelegatingConverter<T, Result<TResult, TError>>>(converter);
635+
576636
/// <summary>
577637
/// If the successful result is present, apply the provided mapping function hiding any exception
578638
/// caused by the converter.
@@ -584,6 +644,17 @@ public Result<TResult, TError> Convert<TResult>(Converter<T, TResult> converter)
584644
public unsafe Result<TResult, TError> Convert<TResult>(delegate*<T, TResult> converter)
585645
=> Convert<TResult, Supplier<T, TResult>>(converter);
586646

647+
/// <summary>
648+
/// If successful result is present, apply the provided mapping function. If not,
649+
/// forward the error.
650+
/// </summary>
651+
/// <param name="converter">A mapping function to be applied to the value, if present.</param>
652+
/// <typeparam name="TResult">The type of the result of the mapping function.</typeparam>
653+
/// <returns>The conversion result.</returns>
654+
[CLSCompliant(false)]
655+
public unsafe Result<TResult, TError> Convert<TResult>(delegate*<T, Result<TResult, TError>> converter)
656+
=> ConvertResult<TResult, Supplier<T, Result<TResult, TError>>>(converter);
657+
587658
[MethodImpl(MethodImplOptions.AggressiveInlining)]
588659
private T OrInvoke<TSupplier>(TSupplier defaultFunc)
589660
where TSupplier : struct, ISupplier<T>

0 commit comments

Comments
 (0)