namespace InnovEnergy.Lib.Utils; // TODO: discriminated union public abstract record Result { public sealed record Success(T Value) : Result; public sealed record Failure(String Error) : Result; public Boolean IsError => this is Failure; public Boolean IsOk => this is Success; public static implicit operator Result(T t) => new Success(t); public static implicit operator Result(String e) => new Failure(e); } public abstract record Result { public sealed record Success(T Value) : Result; public sealed record Failure(E Error) : Result; public Boolean IsError => this is Failure; public Boolean IsOk => this is Success; public static implicit operator Result(T t) => new Success(t); public static implicit operator Result(E e) => new Failure(e); public R Map(Func onSuccess, Func onFailure) => this switch { Success s => onSuccess(s.Value), Failure f => onFailure(f.Error), _ => throw new ArgumentOutOfRangeException() }; public Result OnSuccess(Func onOk) => this switch { Success s => onOk(s.Value), Failure f => f.Error, _ => throw new ArgumentOutOfRangeException() }; public Result OnFailure(Func onError) => this switch { Success s => s.Value, Failure f => onError(f.Error), _ => throw new ArgumentOutOfRangeException() }; } public static class Result { public static Result Try(Func func) { try { return func(); } catch (Exception e) { return e; } } public static String? GetError(this Result r) { return r is Result.Failure err ? err.Error : null; } } public static class ResultClass { public static T? GetValue(this Result r) where T : class { return r is Result.Success ok ? ok.Value : null; } public static E? GetError(this Result r) where E : class { return r is Result.Failure err ? err.Error : null; } } public static class ResultStruct { public static T? GetValue(this Result r) where T : struct { return r is Result.Success ok ? ok.Value : null; } public static E? GetError(this Result r) where E : struct { return r is Result.Failure err ? err.Error : null; } }