Skip to content

Commit

Permalink
feature: reverse from Result<TFailure, TSuccess> to `Result<TSucces…
Browse files Browse the repository at this point in the history
…s, TFailure>`
  • Loading branch information
daht-x committed Dec 5, 2023
1 parent 77f3ba9 commit 0b3a906
Show file tree
Hide file tree
Showing 4 changed files with 146 additions and 146 deletions.
144 changes: 72 additions & 72 deletions source/Monads/Result.cs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
namespace Daht.Sagitta.Core.Monads;

/// <summary>Reference point to initialize <see cref="Result{TFailure, TSuccess}"/>.</summary>
/// <summary>Reference point to initialize <see cref="Result{TSuccess, TFailure}"/>.</summary>
public static class Result
{
/// <summary>Creates a new failed result if <paramref name="success"/> is <see langword="null"/>; otherwise, creates a new successful result.</summary>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <param name="success">The expected success.</param>
/// <param name="failure">
/// <para>The possible failure.</para>
/// <para>If <paramref name="failure"/> is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new failed result if <paramref name="success"/> is <see langword="null"/>; otherwise, a new successful result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TFailure, TSuccess> Ensure<TFailure, TSuccess>(TSuccess? success, TFailure failure)
where TFailure : notnull
public static Result<TSuccess, TFailure> Ensure<TSuccess, TFailure>(TSuccess? success, TFailure failure)
where TSuccess : notnull
where TFailure : notnull
=> success is null
? Fail<TFailure, TSuccess>(failure)
: Succeed<TFailure, TSuccess>(success);
? Fail<TSuccess, TFailure>(failure)
: Succeed<TSuccess, TFailure>(success);

/// <summary>Creates a new failed result if the value of <paramref name="createSuccess"/> throws <typeparamref name="TException"/>; otherwise, creates a new successful result.</summary>
/// <typeparam name="TException">Type of possible exception.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <param name="createSuccess">
/// <para>Creates the expected success.</para>
/// <para>If <paramref name="createSuccess"/> is <see langword="null"/> or its value is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
Expand All @@ -34,129 +34,129 @@ public static class Result
/// </param>
/// <returns>A new failed result if the value of <paramref name="createSuccess"/> throws <typeparamref name="TException"/>; otherwise, a new successful result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TFailure, TSuccess> Catch<TException, TFailure, TSuccess>(Func<TSuccess> createSuccess, Func<TException, TFailure> createFailure)
public static Result<TSuccess, TFailure> Catch<TException, TSuccess, TFailure>(Func<TSuccess> createSuccess, Func<TException, TFailure> createFailure)
where TException : Exception
where TFailure : notnull
where TSuccess : notnull
where TFailure : notnull
{
try
{
return Succeed<TFailure, TSuccess>(createSuccess);
return Succeed<TSuccess, TFailure>(createSuccess);
}
catch (TException exception)
{
ArgumentNullException.ThrowIfNull(createFailure);
TFailure failure = createFailure(exception) ?? throw new ArgumentNullException(nameof(createFailure));
return Fail<TFailure, TSuccess>(failure);
return Fail<TSuccess, TFailure>(failure);
}
}

/// <summary>Creates a new failed result.</summary>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <param name="createFailure">
/// <para>Creates the possible failure.</para>
/// <para>If <paramref name="createFailure"/> is <see langword="null"/> or its value is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new failed result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TFailure, TSuccess> Fail<TFailure, TSuccess>(Func<TFailure> createFailure)
where TFailure : notnull
where TSuccess : notnull
{
ArgumentNullException.ThrowIfNull(createFailure);
TFailure failure = createFailure() ?? throw new ArgumentNullException(nameof(createFailure));
return Fail<TFailure, TSuccess>(failure);
}

/// <summary>Creates a new failed result.</summary>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <param name="failure">
/// <para>The possible failure.</para>
/// <para>If <paramref name="failure"/> is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new failed result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TFailure, TSuccess> Fail<TFailure, TSuccess>(TFailure failure)
where TFailure : notnull
where TSuccess : notnull
=> failure is null
? throw new ArgumentNullException(nameof(failure))
: new Result<TFailure, TSuccess>()
{
IsFailed = true,
Failure = failure
};

/// <summary>Creates a new successful result.</summary>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <param name="createSuccess">
/// <para>Creates the expected success.</para>
/// <para>If <paramref name="createSuccess"/> is <see langword="null"/> or its value is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new successful result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TFailure, TSuccess> Succeed<TFailure, TSuccess>(Func<TSuccess> createSuccess)
where TFailure : notnull
public static Result<TSuccess, TFailure> Succeed<TSuccess, TFailure>(Func<TSuccess> createSuccess)
where TSuccess : notnull
where TFailure : notnull
{
ArgumentNullException.ThrowIfNull(createSuccess);
TSuccess success = createSuccess() ?? throw new ArgumentNullException(nameof(createSuccess));
return Succeed<TFailure, TSuccess>(success);
return Succeed<TSuccess, TFailure>(success);
}

/// <summary>Creates a new successful result.</summary>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <param name="success">
/// <para>The expected success.</para>
/// <para>If <paramref name="success"/> is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new successful result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TFailure, TSuccess> Succeed<TFailure, TSuccess>(TSuccess success)
where TFailure : notnull
public static Result<TSuccess, TFailure> Succeed<TSuccess, TFailure>(TSuccess success)
where TSuccess : notnull
where TFailure : notnull
=> success is null
? throw new ArgumentNullException(nameof(success))
: new Result<TFailure, TSuccess>()
: new Result<TSuccess, TFailure>()
{
IsSuccessful = true,
Success = success
};

/// <summary>Creates a new failed result.</summary>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <param name="createFailure">
/// <para>Creates the possible failure.</para>
/// <para>If <paramref name="createFailure"/> is <see langword="null"/> or its value is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new failed result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TSuccess, TFailure> Fail<TSuccess, TFailure>(Func<TFailure> createFailure)
where TSuccess : notnull
where TFailure : notnull
{
ArgumentNullException.ThrowIfNull(createFailure);
TFailure failure = createFailure() ?? throw new ArgumentNullException(nameof(createFailure));
return Fail<TSuccess, TFailure>(failure);
}

/// <summary>Creates a new failed result.</summary>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <param name="failure">
/// <para>The possible failure.</para>
/// <para>If <paramref name="failure"/> is <see langword="null"/>, <seealso cref="ArgumentNullException"/> will be thrown.</para>
/// </param>
/// <returns>A new failed result.</returns>
/// <exception cref="ArgumentNullException"/>
public static Result<TSuccess, TFailure> Fail<TSuccess, TFailure>(TFailure failure)
where TSuccess : notnull
where TFailure : notnull
=> failure is null
? throw new ArgumentNullException(nameof(failure))
: new Result<TSuccess, TFailure>()
{
IsFailed = true,
Failure = failure
};
}

/// <summary>Type that encapsulates both the possible failure and the expected success of a given action</summary>
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
/// <summary>Type that encapsulates both the expected success and the possible failure of a given action.</summary>
/// <typeparam name="TSuccess">Type of expected success.</typeparam>
public readonly record struct Result<TFailure, TSuccess>
where TFailure : notnull
/// <typeparam name="TFailure">Type of possible failure.</typeparam>
public readonly record struct Result<TSuccess, TFailure>
where TSuccess : notnull
where TFailure : notnull
{
/// <summary>Indicates whether the status is failed or <see langword="default"/>.</summary>
public bool IsFailedOrDefault => IsFailed || IsDefault;

/// <summary>Indicates whether the status is successful or <see langword="default"/>.</summary>
public bool IsSuccessfulOrDefault => IsSuccessful || IsDefault;

/// <summary>Indicates whether the status is failed or <see langword="default"/>.</summary>
public bool IsFailedOrDefault => IsFailed || IsDefault;

/// <summary>Indicates whether the status is <see langword="default"/>.</summary>
public bool IsDefault => this is
{
IsFailed: false,
IsSuccessful: false
IsSuccessful: false,
IsFailed: false
};

/// <summary>Indicates whether the status is failed.</summary>
public bool IsFailed { get; internal init; }

/// <summary>The possible failure.</summary>
public TFailure Failure { get; internal init; }

/// <summary>Indicates whether the status is successful.</summary>
public bool IsSuccessful { get; internal init; }

/// <summary>The expected success.</summary>
public TSuccess Success { get; internal init; }

/// <summary>Indicates whether the status is failed.</summary>
public bool IsFailed { get; internal init; }

/// <summary>The possible failure.</summary>
public TFailure Failure { get; internal init; }
}
32 changes: 16 additions & 16 deletions test/unit/Monads/Asserters/ResultAsserter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,29 @@ namespace Daht.Sagitta.Core.UnitTest.Monads.Asserters;

internal static class ResultAsserter
{
internal static void AreFailed<TFailure, TSuccess>(TFailure expectedFailure, Result<TFailure, TSuccess> actualResult)
where TFailure : notnull
internal static void AreSuccessful<TSuccess, TFailure>(TSuccess expectedSuccess, Result<TSuccess, TFailure> actualResult)
where TSuccess : notnull
where TFailure : notnull
{
Assert.True(actualResult.IsFailedOrDefault);
Assert.False(actualResult.IsSuccessfulOrDefault);
Assert.True(actualResult.IsSuccessfulOrDefault);
Assert.False(actualResult.IsFailedOrDefault);
Assert.False(actualResult.IsDefault);
Assert.True(actualResult.IsFailed);
Assert.Equal(expectedFailure, actualResult.Failure);
Assert.False(actualResult.IsSuccessful);
Assert.Equal(default, actualResult.Success);
Assert.True(actualResult.IsSuccessful);
Assert.Equal(expectedSuccess, actualResult.Success);
Assert.False(actualResult.IsFailed);
Assert.Equal(default, actualResult.Failure);
}

internal static void AreSuccessful<TFailure, TSuccess>(TSuccess expectedSuccess, Result<TFailure, TSuccess> actualResult)
where TFailure : notnull
internal static void AreFailed<TSuccess, TFailure>(TFailure expectedFailure, Result<TSuccess, TFailure> actualResult)
where TSuccess : notnull
where TFailure : notnull
{
Assert.False(actualResult.IsFailedOrDefault);
Assert.True(actualResult.IsSuccessfulOrDefault);
Assert.False(actualResult.IsSuccessfulOrDefault);
Assert.True(actualResult.IsFailedOrDefault);
Assert.False(actualResult.IsDefault);
Assert.False(actualResult.IsFailed);
Assert.Equal(default, actualResult.Failure);
Assert.True(actualResult.IsSuccessful);
Assert.Equal(expectedSuccess, actualResult.Success);
Assert.False(actualResult.IsSuccessful);
Assert.Equal(default, actualResult.Success);
Assert.True(actualResult.IsFailed);
Assert.Equal(expectedFailure, actualResult.Failure);
}
}
4 changes: 2 additions & 2 deletions test/unit/Monads/Fixtures/ResultFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ namespace Daht.Sagitta.Core.UnitTest.Monads.Fixtures;

internal static class ResultFixture
{
internal const string Failure = nameof(Failure);

internal const string Success = nameof(Success);

internal const string Failure = nameof(Failure);
}
Loading

0 comments on commit 0b3a906

Please sign in to comment.