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