feat: add OneOf

This commit is contained in:
Kyle Ratti 2022-09-23 21:08:25 -04:00
parent c39fdd86ec
commit cdcfd671f0
No known key found for this signature in database
GPG Key ID: 321BA8EB09CD93F4

109
Base/Structures/OneOf.cs Normal file
View File

@ -0,0 +1,109 @@
namespace FruityFoundation.Base.Structures;
public class OneOf<T1, T2>
{
private Maybe<T1> _itemOne { get; }
private Maybe<T2> _itemTwo { get; }
public T1 ItemOne => _itemOne.OrThrow($"{nameof(ItemOne)} must have a value in order to be accessed");
public T2 ItemTwo => _itemTwo.OrThrow($"{nameof(ItemTwo)} must have a value in order to be accessed");
public object? RawItem
{
get
{
if (_itemOne.HasValue)
return _itemOne.Value;
else if (_itemTwo.HasValue)
return _itemTwo.Value;
// This is specifically a null and not a Maybe<object> so we can pattern match on it
return null;
}
}
public T Map<T>(Func<T1, T> itemOneMap, Func<T2, T> itemTwoMap)
{
if (_itemOne.Try(out var itemOne))
return itemOneMap(itemOne);
else if (_itemTwo.Try(out var itemTwo))
return itemTwoMap(itemTwo);
throw new NotImplementedException("Map condition not handled");
}
private OneOf(Maybe<T1> one, Maybe<T2> two)
{
_itemOne = one;
_itemTwo = two;
}
public static implicit operator OneOf<T1, T2>(T1 oneOf) => new(oneOf, default);
public static implicit operator OneOf<T1, T2>(T2 oneOf) => new(default, oneOf);
}
public class OneOf<T1, T2, T3>
{
private Maybe<T1> _itemOne { get; }
private Maybe<T2> _itemTwo { get; }
private Maybe<T3> _itemThree { get; }
public T1 ItemOne => _itemOne.OrThrow($"{nameof(ItemOne)} must have a value in order to be accessed");
public T2 ItemTwo => _itemTwo.OrThrow($"{nameof(ItemTwo)} must have a value in order to be accessed");
public T3 ItemThree => _itemThree.OrThrow($"{nameof(ItemThree)} must have a value in order to be accessed");
public object? RawItem
{
get
{
if (_itemOne.HasValue)
return _itemOne.Value;
else if (_itemTwo.HasValue)
return _itemTwo.Value;
else if (_itemThree.HasValue)
return _itemThree.Value;
// This is specifically a null and not a Maybe<object> so we can pattern match on it
return null;
}
}
public T Map<T>(Func<T1, T> itemOneMap, Func<T2, T> itemTwoMap, Func<T3, T> itemThreeMap)
{
if (_itemOne.Try(out var itemOne))
return itemOneMap(itemOne);
else if (_itemTwo.Try(out var itemTwo))
return itemTwoMap(itemTwo);
else if (_itemThree.Try(out var itemThree))
return itemThreeMap(itemThree);
throw new NotImplementedException("Map condition not handled");
}
public Type? ItemType
{
get
{
if (_itemOne.HasValue)
return typeof(T1);
else if (_itemTwo.HasValue)
return typeof(T2);
else if (_itemThree.HasValue)
return typeof(T3);
// This is specifically a null and not a Maybe<Type> so we can pattern match on it
return null;
}
}
private OneOf(Maybe<T1> one, Maybe<T2> two, Maybe<T3> three)
{
_itemOne = one;
_itemTwo = two;
_itemThree = three;
}
public static implicit operator OneOf<T1, T2, T3>(T1 oneOf) => new(oneOf, default, default);
public static implicit operator OneOf<T1, T2, T3>(T2 oneOf) => new(default, oneOf, default);
public static implicit operator OneOf<T1, T2, T3>(T3 oneOf) => new(default, default, oneOf);
}