Loading files
c30bb7b85This file is pinned to the selected release. Download the original to open it in your design tool.
/******************************************************************************
* Copyright (C) Leap Motion, Inc. 2011-2018. *
* Leap Motion proprietary and confidential. *
* *
* Use subject to the terms of the Leap Motion SDK Agreement available at *
* https://developer.leapmotion.com/sdk_agreement, or another agreement *
* between Leap Motion and you, your company or other organization. *
******************************************************************************/
using System;
namespace Leap.Unity {
using Query;
public static class Maybe {
public static readonly NoneType None = new NoneType();
public static Maybe<T> Some<T>(T value) {
return new Maybe<T>(value);
}
public static void MatchAll<A, B>(Maybe<A> maybeA, Maybe<B> maybeB, Action<A, B> action) {
maybeA.Match(a => {
maybeB.Match(b => {
action(a, b);
});
});
}
public static void MatchAll<A, B, C>(Maybe<A> maybeA, Maybe<B> maybeB, Maybe<C> maybeC, Action<A, B, C> action) {
maybeA.Match(a => {
maybeB.Match(b => {
maybeC.Match(c => {
action(a, b, c);
});
});
});
}
public static void MatchAll<A, B, C, D>(Maybe<A> maybeA, Maybe<B> maybeB, Maybe<C> maybeC, Maybe<D> maybeD, Action<A, B, C, D> action) {
maybeA.Match(a => {
maybeB.Match(b => {
maybeC.Match(c => {
maybeD.Match(d => {
action(a, b, c, d);
});
});
});
});
}
public struct NoneType { }
}
/// <summary>
/// A struct that represents a value that could or could not exist. Unlike
/// the built-int nullable types, you are unable to access the value unless
/// it does exist, and will never recieve a null value.
/// </summary>
public struct Maybe<T> : IEquatable<Maybe<T>>, IComparable, IComparable<Maybe<T>> {
/// <summary>
/// Returns a Maybe for this type that represents no value.
/// </summary>
public readonly static Maybe<T> None = new Maybe<T>();
/// <summary>
/// Returns whether or not this Maybe contains a value.
/// </summary>
public readonly bool hasValue;
/// <summary>
/// Gets the value, or the type's default if it doesn't exist.
/// </summary>
public T valueOrDefault {
get {
T value;
if (TryGetValue(out value)) {
return value;
}
return default(T);
}
}
private readonly T _t;
/// <summary>
/// Constructs a Maybe given a value. If the value is not null, this maybe will have
/// a value. If the value is null, this maybe will have no value. For value types,
/// the Maybe struct will always have a value. (Use Maybe.None to refer to "no value.")
/// </summary>
public Maybe(T t) {
if (Type<T>.isValueType) {
hasValue = true;
} else {
hasValue = t != null;
}
_t = t;
}
/// <summary>
/// Constructs a Maybe given a specific value. This value needs to always be
/// non-null if the type is a reference type.
/// </summary>
public static Maybe<T> Some(T t) {
if (!Type<T>.isValueType && t == null) {
throw new ArgumentNullException("Cannot use Some with a null argument.");
}
return new Maybe<T>(t);
}
/// <summary>
/// If this Maybe has a value, the out argument is filled with that value and
/// this method returns true, else it returns false.
/// </summary>
public bool TryGetValue(out T t) {
t = _t;
return hasValue;
}
/// <summary>
/// If this Maybe has a value, the delegate is called with that value.
/// </summary>
public void Match(Action<T> ifValue) {
if (hasValue) {
ifValue(_t);
}
}
/// <summary>
/// If this Maybe has a value, the first delegate is called with that value,
/// else the second delegate is called.
/// </summary>
public void Match(Action<T> ifValue, Action ifNot) {
if (hasValue) {
if (ifValue != null) ifValue(_t);
} else {
ifNot();
}
}
/// <summary>
/// If this Maybe has a value, the first delegate is called with that value,
/// else the second delegate is called.
/// </summary>
public K Match<K>(Func<T, K> ifValue, Func<K> ifNot) {
if (hasValue) {
if (ifValue != null) {
return ifValue(_t);
} else {
return default(K);
}
} else {
return ifNot();
}
}
/// <summary>
/// If this Maybe has a value, returns the value, otherwise returns the argument
/// custom default value.
/// </summary>
public T ValueOr(T customDefault) {
if (hasValue) {
return _t;
} else {
return customDefault;
}
}
/// <summary>
/// Returns this Maybe if it has a value, otherwise returns the argument Maybe value.
/// Useful for overlaying multiple Maybe values.
/// For example, if I want to overlay a "maybe override font" variable with
/// another "maybe override font" variable, I can call:
/// this.font = other.font.ValueOr(this.font);
/// </summary>
public Maybe<T> ValueOr(Maybe<T> maybeCustomDefault) {
if (hasValue) {
return this;
} else {
return maybeCustomDefault;
}
}
public Query<T> Query() {
if (hasValue) {
return Values.Single(_t);
} else {
return Values.Empty<T>();
}
}
public override int GetHashCode() {
return hasValue ? _t.GetHashCode() : 0;
}
public override bool Equals(object obj) {
if (obj is Maybe<T>) {
return Equals((Maybe<T>)obj);
} else {
return false;
}
}
public bool Equals(Maybe<T> other) {
if (hasValue != other.hasValue) {
return false;
} else if (hasValue) {
return _t.Equals(other._t);
} else {
return true;
}
}
public int CompareTo(object obj) {
if (!(obj is Maybe<T>)) {
throw new ArgumentException();
} else {
return CompareTo((Maybe<T>)obj);
}
}
public int CompareTo(Maybe<T> other) {
if (hasValue != other.hasValue) {
return hasValue ? 1 : -1;
} else if (hasValue) {
IComparable<T> ct = _t as IComparable<T>;
if (ct != null) {
return ct.CompareTo(other._t);
} else {
IComparable c = _t as IComparable;
if (c != null) {
return c.CompareTo(other._t);
} else {
return 0;
}
}
} else {
return 0;
}
}
public static bool operator ==(Maybe<T> maybe0, Maybe<T> maybe1) {
return maybe0.Equals(maybe1);
}
public static bool operator !=(Maybe<T> maybe0, Maybe<T> maybe1) {
return !maybe0.Equals(maybe1);
}
public static bool operator >(Maybe<T> maybe0, Maybe<T> maybe1) {
return maybe0.CompareTo(maybe1) > 0;
}
public static bool operator >=(Maybe<T> maybe0, Maybe<T> maybe1) {
return maybe0.CompareTo(maybe1) >= 0;
}
public static bool operator <(Maybe<T> maybe0, Maybe<T> maybe1) {
return maybe0.CompareTo(maybe1) < 0;
}
public static bool operator <=(Maybe<T> maybe0, Maybe<T> maybe1) {
return maybe0.CompareTo(maybe1) <= 0;
}
public static implicit operator Maybe<T>(T t) {
return new Maybe<T>(t);
}
public static implicit operator Maybe<T>(Maybe.NoneType none) {
return None;
}
}
}