canto/Assets/Scripts/System/Result.cs
2025-07-14 22:22:25 -04:00

216 lines
6 KiB
C#

using System;
using UnityEngine.Rendering.Universal;
namespace KitsuneCafe.System
{
public static class Result
{
/// <summary>
/// Creates a successful Result with the specified value.
/// Type inference for TError often occurs from the assignment context.
/// </summary>
public static IResult<TValue, TError> Ok<TValue, TError>(TValue value)
{
return new Ok<TValue, TError>(value);
}
/// <summary>
/// Creates an erroneous Result with the specified error.
/// Type inference for TValue often occurs from the assignment context.
/// </summary>
public static IResult<TValue, TError> Err<TValue, TError>(TError error)
{
return new Err<TValue, TError>(error);
}
}
public interface IResult<TValue, TError>
{
public abstract bool IsOk { get; }
public static IResult<TValue, TError> Ok(TValue value) => new Ok<TValue, TError>(value);
public static IResult<TValue, TError> Err(TError error) => new Err<TValue, TError>(error);
public abstract TValue Unwrap();
public abstract TError UnwrapErr();
public abstract IResult<TResult, TError> SelectMany<TResult>(Func<TValue, IResult<TResult, TError>> func);
public abstract IResult<TResult, TError> Select<TResult>(Func<TValue, TResult> func);
public abstract IResult<TValue, TResult> SelectErr<TResult>(Func<TError, TResult> func);
public abstract IResult<TValue, TError> Where(Func<TValue, bool> predicate);
public abstract TResult Match<TResult>(Func<TValue, TResult> okFunc, Func<TError, TResult> errFunc);
public abstract TValue UnwrapOrDefault(TValue defaultValue = default);
public abstract TValue UnwrapOrElse(Func<TValue> func);
public virtual IResult<TValue, TError> Do(Action<TValue> func)
{
if (IsOk) { func(Unwrap()); }
return this;
}
public virtual IResult<TValue, TError> DoIfErr(Action<TError> func)
{
if (!IsOk) { func(UnwrapErr()); }
return this;
}
}
public readonly struct Ok<TValue, TError> : IResult<TValue, TError>
{
private readonly TValue value;
public readonly bool IsOk => true;
internal Ok(TValue value)
{
this.value = value;
}
public void Deconstruct(out TValue value)
{
value = this.value;
}
public IResult<TResult, TError> SelectMany<TResult>(Func<TValue, IResult<TResult, TError>> func)
{
return func(value);
}
public TValue Unwrap()
{
return value;
}
public TError UnwrapErr()
{
throw new InvalidOperationException("Attempted to UnwrapErr an Ok");
}
public IResult<TResult, TError> Select<TResult>(Func<TValue, TResult> func)
{
return IResult<TResult, TError>.Ok(func(value));
}
public IResult<TValue, TResult> SelectErr<TResult>(Func<TError, TResult> func)
{
return IResult<TValue, TResult>.Ok(value);
}
public IResult<TValue, TError> Where(Func<TValue, bool> predicate)
{
if (predicate(value))
{
return this;
}
return IResult<TValue, TError>.Err(default);
}
public TResult Match<TResult>(Func<TValue, TResult> okFunc, Func<TError, TResult> errFunc)
{
return okFunc(value);
}
public TValue UnwrapOrDefault(TValue defaultValue = default)
{
return value;
}
public TValue UnwrapOrElse(Func<TValue> func)
{
return value;
}
public override bool Equals(object obj)
{
return obj is Ok<TValue, TError> other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(value);
}
public override string ToString()
{
return $"Ok({value})";
}
}
public readonly struct Err<TValue, TError> : IResult<TValue, TError>
{
private readonly TError error;
public readonly bool IsOk => false;
internal Err(TError error)
{
this.error = error;
}
public void Deconstruct(out TError error)
{
error = this.error;
}
public IResult<TResult, TError> SelectMany<TResult>(Func<TValue, IResult<TResult, TError>> func)
{
return IResult<TResult, TError>.Err(error);
}
public TValue Unwrap()
{
throw new InvalidOperationException("Attempted to unwrap value of an Err.");
}
public TError UnwrapErr()
{
return error;
}
public IResult<TResult, TError> Select<TResult>(Func<TValue, TResult> func)
{
return IResult<TResult, TError>.Err(error);
}
public IResult<TValue, TResult> SelectErr<TResult>(Func<TError, TResult> func)
{
return IResult<TValue, TResult>.Err(func(error));
}
public IResult<TValue, TError> Where(Func<TValue, bool> predicate)
{
return IResult<TValue, TError>.Err(error);
}
public TResult Match<TResult>(Func<TValue, TResult> okFunc, Func<TError, TResult> errFunc)
{
return errFunc(error);
}
public TValue UnwrapOrDefault(TValue defaultValue = default)
{
return defaultValue;
}
public TValue UnwrapOrElse(Func<TValue> func)
{
return func();
}
public override bool Equals(object obj)
{
return obj is Err<TValue, TError> other && Equals(other);
}
public override int GetHashCode()
{
return HashCode.Combine(error);
}
public override string ToString()
{
return $"Err({error})";
}
}
}