using System;
namespace EscapeRoomEngine.Engine.Runtime.Utilities
{
///
/// Optional type with a subset of the functionality of the one described in the Rust documentation at https://doc.rust-lang.org/std/option/enum.Option.html.
///
public interface IOption
{
public bool IsSome();
public bool IsNone();
public T Expect(string message);
public T Unwrap();
public T UnwrapOr(T def);
public T UnwrapOrElse(Func f);
public IOption And(IOption other);
public IOption Or(IOption other);
public bool Contains(T value);
public T Match(Func some, Func none);
public void Match(Action some, Action none);
public void Match(Action some);
public void Match(Action none);
}
public class Some : IOption
{
private readonly T _value;
private Some(T value) => _value = value;
public bool IsSome() => true;
public bool IsNone() => false;
public T Expect(string message) => _value;
public T Unwrap() => _value;
public T UnwrapOr(T def) => _value;
public T UnwrapOrElse(Func f) => _value;
public IOption And(IOption other) => other;
public IOption Or(IOption other) => this;
public bool Contains(T value) => _value.Equals(value);
public T Match(Func some, Func none) => some(_value);
public void Match(Action some, Action none) => some(_value);
public void Match(Action some) => some(_value);
public void Match(Action none) {}
public static IOption Of(T value) => new Some(value);
}
public class None : IOption
{
public bool IsSome() => false;
public bool IsNone() => true;
public T Expect(string message) => throw new OptionException(message);
public T Unwrap() => throw new OptionException("Tried to unwrap None.");
public T UnwrapOr(T def) => def;
public T UnwrapOrElse(Func f) => f();
public IOption And(IOption other) => this;
public IOption Or(IOption other) => other;
public bool Contains(T value) => false;
public T Match(Func some, Func none) => none();
public void Match(Action some, Action none) => none();
public void Match(Action some) {}
public void Match(Action none) => none();
public static IOption New() => new None();
}
}