Files
Just.Railway/Railway/Result.cs
2023-11-27 20:41:39 +04:00

1280 lines
42 KiB
C#

namespace Just.Railway;
internal enum ResultState : byte
{
Bottom = 0, Error = 0b01, Success = 0b11,
}
public readonly struct Result : IEquatable<Result>
{
internal readonly Error? Error;
internal readonly ResultState State;
internal Result(Error? error)
{
Error = error;
State = error is null ? ResultState.Success : ResultState.Error;
}
[Pure] public static Result Success() => new(null);
[Pure] public static Result<T> Success<T>(T value) => new(value);
[Pure] public static Result Failure(Error error) => new(error ?? throw new ArgumentNullException(nameof(error)));
[Pure] public static Result<T> Failure<T>(Error error) => new(error ?? throw new ArgumentNullException(nameof(error)));
#region Combine 2 Results
[Pure] public static Result Combine(in Result result1, in Result result2)
{
Error? error = null;
if ((result1.State & result2.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
return new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result<T1> result1, in Result<T2> result2)
{
Error? error = null;
if ((result1.State & result2.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
return error is null
? new((result1.Value, result2.Value))
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result<T> result1, in Result result2)
{
Error? error = null;
if ((result1.State & result2.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
return error is null
? new(result1.Value)
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result result1, in Result<T> result2)
{
Error? error = null;
if ((result1.State & result2.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
return error is null
? new(result2.Value)
: new(error);
}
#endregion
#region Combine 3 Results
[Pure] public static Result Combine(in Result result1, in Result result2, in Result result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return new(error);
}
[Pure] public static Result<(T1, T2, T3)> Combine<T1, T2, T3>(in Result<T1> result1, in Result<T2> result2, in Result<T3> result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new((result1.Value, result2.Value, result3.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result<T1> result1, in Result<T2> result2, in Result result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new((result1.Value, result2.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result result1, in Result<T1> result2, in Result<T2> result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new((result2.Value, result3.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result<T1> result1, in Result result2, in Result<T2> result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new((result1.Value, result3.Value))
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result<T> result1, in Result result2, in Result result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new(result1.Value)
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result result1, in Result<T> result2, in Result result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new(result2.Value)
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result result1, in Result result2, in Result<T> result3)
{
Error? error = null;
if ((result1.State & result2.State & result3.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
return error is null
? new(result3.Value)
: new(error);
}
#endregion
#region Combine 4 Results
[Pure] public static Result Combine(in Result result1, in Result result2, in Result result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return new(error);
}
[Pure] public static Result<(T1, T2, T3, T4)> Combine<T1, T2, T3, T4>(in Result<T1> result1, in Result<T2> result2, in Result<T3> result3, in Result<T4> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result2.Value, result3.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2, T3)> Combine<T1, T2, T3>(in Result result1, in Result<T1> result2, in Result<T2> result3, in Result<T3> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result2.Value, result3.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2, T3)> Combine<T1, T2, T3>(in Result<T1> result1, in Result result2, in Result<T2> result3, in Result<T3> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result3.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2, T3)> Combine<T1, T2, T3>(in Result<T1> result1, in Result<T2> result2, in Result result3, in Result<T3> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result2.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2, T3)> Combine<T1, T2, T3>(in Result<T1> result1, in Result<T2> result2, in Result<T3> result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result2.Value, result3.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result result1, in Result result2, in Result<T1> result3, in Result<T2> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result3.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result result1, in Result<T1> result2, in Result result3, in Result<T2> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result2.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result result1, in Result<T1> result2, in Result<T2> result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result2.Value, result3.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result<T1> result1, in Result result2, in Result result3, in Result<T2> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result4.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result<T1> result1, in Result result2, in Result<T2> result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result3.Value))
: new(error);
}
[Pure] public static Result<(T1, T2)> Combine<T1, T2>(in Result<T1> result1, in Result<T2> result2, in Result result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new((result1.Value, result2.Value))
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result result1, in Result result2, in Result result3, in Result<T> result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new(result4.Value)
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result result1, in Result result2, in Result<T> result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new(result3.Value)
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result result1, in Result<T> result2, in Result result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new(result2.Value)
: new(error);
}
[Pure] public static Result<T> Combine<T>(in Result<T> result1, in Result result2, in Result result3, in Result result4)
{
Error? error = null;
if ((result1.State & result2.State & result3.State & result4.State) == ResultState.Bottom)
{
throw new ResultNotInitializedException(string.Join(';', GetBottom(result1.State, result2.State, result3.State, result4.State)));
static IEnumerable<string> GetBottom(ResultState r1, ResultState r2, ResultState r3, ResultState r4)
{
if (r1 == ResultState.Bottom)
yield return nameof(result1);
if (r2 == ResultState.Bottom)
yield return nameof(result2);
if (r3 == ResultState.Bottom)
yield return nameof(result3);
if (r4 == ResultState.Bottom)
yield return nameof(result4);
}
}
if (result1.IsFailure)
{
error += result1.Error;
}
if (result2.IsFailure)
{
error += result2.Error;
}
if (result3.IsFailure)
{
error += result3.Error;
}
if (result4.IsFailure)
{
error += result4.Error;
}
return error is null
? new(result1.Value)
: new(error);
}
#endregion
[Pure] public static implicit operator Result(Error error) => new(error ?? throw new ArgumentNullException(nameof(error)));
[Pure] public static implicit operator Result<SuccessUnit>(Result result) => result.State switch
{
ResultState.Success => new(new SuccessUnit()),
ResultState.Error => new(result.Error!),
_ => throw new ResultNotInitializedException(nameof(result))
};
[Pure] public bool IsSuccess => Error is null;
[Pure] public bool IsFailure => Error is not null;
[Pure] public bool TryGetError([MaybeNullWhen(false)]out Error error)
{
if (IsSuccess)
{
error = default;
return false;
}
if (IsFailure)
{
error = Error!;
return true;
}
throw new ResultNotInitializedException();
}
[Pure] public override string ToString() => State switch
{
ResultState.Success => "",
ResultState.Error => Error!.ToString(),
_ => throw new ResultNotInitializedException()
};
[Pure] public override int GetHashCode() => State switch
{
ResultState.Success => 0,
ResultState.Error => Error!.GetHashCode(),
_ => throw new ResultNotInitializedException()
};
[Pure] public override bool Equals(object? obj) => obj is Result other && Equals(other);
[Pure] public bool Equals(Result other)
{
if (State == ResultState.Bottom)
throw new ResultNotInitializedException();
return Error == other.Error;
}
[Pure] public static bool operator ==(Result left, Result right) => left.Equals(right);
[Pure] public static bool operator !=(Result left, Result right) => !(left == right);
}
public readonly struct Result<T> : IEquatable<Result<T>>
{
internal readonly Error? Error;
internal readonly T Value;
internal readonly ResultState State;
internal Result(Error error)
{
Error = error ?? throw new ArgumentNullException(nameof(error));
State = ResultState.Error;
Value = default!;
}
internal Result(T value)
{
Value = value;
State = ResultState.Success;
}
[Pure] public static explicit operator Result(Result<T> result) => result.State switch
{
ResultState.Success => new(null),
ResultState.Error => new(result.Error!),
_ => throw new ResultNotInitializedException(nameof(result))
};
[Pure] public static implicit operator Result<T>(Error error) => new(error);
[Pure] public static implicit operator Result<T>(T value) => new(value);
[Pure] public bool IsSuccess => State == ResultState.Success;
[Pure] public bool IsFailure => State == ResultState.Error;
[Pure] public bool Unwrap([MaybeNullWhen(false)]out T value, [MaybeNullWhen(true)]out Error error)
{
switch (State)
{
case ResultState.Success:
value = Value;
error = default;
return true;
case ResultState.Error:
value = default;
error = Error!;
return false;
default: throw new ResultNotInitializedException();
}
}
[Pure] public bool TryGetValue([MaybeNullWhen(false)]out T value)
{
switch (State)
{
case ResultState.Success:
value = Value;
return true;
case ResultState.Error:
value = default;
return false;
default: throw new ResultNotInitializedException();
}
}
[Pure] public bool TryGetError([MaybeNullWhen(false)]out Error error)
{
switch (State)
{
case ResultState.Success:
error = default;
return false;
case ResultState.Error:
error = Error!;
return true;
default: throw new ResultNotInitializedException();
}
}
[Pure] public Result<R> Cast<R>()
{
switch (State)
{
case ResultState.Error:
return Error!;
case ResultState.Success:
{
if (Value is R ret)
return ret;
if (typeof(R).IsAssignableFrom(typeof(T)) && Value is null)
return default(R)!;
return (R)(object)Value!;
}
default: throw new ResultNotInitializedException();
}
}
[Pure] public override string ToString() => State switch
{
ResultState.Success => Value?.ToString() ?? "",
ResultState.Error => Error!.ToString(),
_ => throw new ResultNotInitializedException()
};
[Pure] public override int GetHashCode() => State switch
{
ResultState.Success => Value?.GetHashCode() ?? 0,
ResultState.Error => Error!.GetHashCode(),
_ => throw new ResultNotInitializedException()
};
[Pure] public override bool Equals(object? obj) => obj is Result<T> other && Equals(other);
[Pure] public bool Equals(Result<T> other)
{
if (State == ResultState.Bottom)
throw new ResultNotInitializedException();
if (IsSuccess != other.IsSuccess)
return false;
return IsSuccess
? ReflectionHelper.IsEqual(Value, other.Value)
: Error == other.Error;
}
[Pure] public static bool operator ==(Result<T> left, Result<T> right) => left.Equals(right);
[Pure] public static bool operator !=(Result<T> left, Result<T> right) => !(left == right);
}
public readonly struct SuccessUnit : IEquatable<SuccessUnit>
{
public override bool Equals([NotNullWhen(true)] object? obj) => obj is SuccessUnit;
public bool Equals(SuccessUnit other) => true;
public override int GetHashCode() => 0;
public override string ToString() => "success";
public static bool operator ==(SuccessUnit left, SuccessUnit right) => left.Equals(right);
public static bool operator !=(SuccessUnit left, SuccessUnit right) => !(left == right);
}
[Serializable]
public class ResultNotInitializedException(string variableName = "this") : InvalidOperationException("Result was not properly initialized.")
{
public string VariableName { get; } = variableName;
}