#nullable enable using System; namespace Barotrauma { /// /// Implementation of Option type. /// /// /// Credit Jlobblet /// public abstract class Option { public static Option Some(T value) => Some.Create(value); public static Option None() => None.Create(); public bool IsNone() => this is None; public bool IsSome() => this is Some; public bool TryUnwrap(out T outValue) => TryUnwrap(out outValue); public bool TryUnwrap(out T1 outValue) where T1 : T { switch (this) { case Some { Value: T1 value }: outValue = value; return true; default: outValue = default!; return false; } } public Option Select(Func selector) => this switch { Some { Value: var value } => Option.Some(selector.Invoke(value)), None _ => Option.None(), _ => throw new ArgumentOutOfRangeException() }; public abstract Option Fallback(Option fallback); public abstract T Fallback(T fallback); public abstract bool ValueEquals(T value); public override bool Equals(object? obj) => obj switch { Some { Value: var value } => this is Some { Value: { } selfValue } && selfValue.Equals(value), None _ => IsNone(), T value => this is Some { Value: { } selfValue } && selfValue.Equals(value), _ => false }; public override int GetHashCode() => this is Some { Value: { } value } ? value.GetHashCode() : 0; public static bool operator ==(Option a, Option b) => a.Equals(b); public static bool operator !=(Option a, Option b) => !(a == b); public abstract override string ToString(); public static implicit operator Option(Option.UnspecifiedNone _) => None(); } public static class Option { public sealed class UnspecifiedNone { private UnspecifiedNone() { } internal static readonly UnspecifiedNone Instance = new(); } public static UnspecifiedNone None => UnspecifiedNone.Instance; public static Option Some(T value) => Option.Some(value); } }