namespace Just.Railway; public static partial class Ensure { public delegate Error ErrorFactory(string valueExpression); public const string DefaultErrorType = "EnsureFailed"; [Pure] public static Ensure That(T value, [CallerArgumentExpression(nameof(value))]string valueExpression = "") => new(value, valueExpression); [Pure] public static Result Result(this in Ensure ensure) => ensure.State switch { ResultState.Success => new(ensure.Value), ResultState.Error => new(ensure.Error!), _ => throw new EnsureNotInitializedException(nameof(ensure)) }; [Pure] public static async Task> Result(this Task> ensureTask) { var ensure = await ensureTask.ConfigureAwait(false); return ensure.State switch { ResultState.Success => new(ensure.Value), ResultState.Error => new(ensure.Error!), _ => throw new EnsureNotInitializedException(nameof(ensureTask)) }; } [Pure] public static async ValueTask> Result(this ValueTask> ensureTask) { var ensure = await ensureTask.ConfigureAwait(false); return ensure.State switch { ResultState.Success => new(ensure.Value), ResultState.Error => new(ensure.Error!), _ => throw new EnsureNotInitializedException(nameof(ensureTask)) }; } } public readonly struct Ensure { internal readonly ResultState State; internal readonly Error? Error; internal readonly T Value; internal readonly string ValueExpression; internal Ensure(T value, string valueExpression) { Value = value; ValueExpression = valueExpression; State = ResultState.Success; Error = default; } internal Ensure(Error error, string valueExpression) { Error = error; ValueExpression = valueExpression; Value = default!; State = ResultState.Error; } } [Serializable] public class EnsureNotInitializedException : InvalidOperationException { public EnsureNotInitializedException(string variableName = "this") : base("Ensure was not properly initialized.") { VariableName = variableName; } public string VariableName { get; } }