diff --git a/Base/Structures/OneOf.cs b/Base/Structures/OneOf.cs new file mode 100644 index 0000000..a485ea1 --- /dev/null +++ b/Base/Structures/OneOf.cs @@ -0,0 +1,109 @@ +namespace FruityFoundation.Base.Structures; + +public class OneOf +{ + private Maybe _itemOne { get; } + private Maybe _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 so we can pattern match on it + return null; + } + } + + public T Map(Func itemOneMap, Func 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 one, Maybe two) + { + _itemOne = one; + _itemTwo = two; + } + + public static implicit operator OneOf(T1 oneOf) => new(oneOf, default); + public static implicit operator OneOf(T2 oneOf) => new(default, oneOf); +} + +public class OneOf +{ + private Maybe _itemOne { get; } + private Maybe _itemTwo { get; } + private Maybe _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 so we can pattern match on it + return null; + } + } + + public T Map(Func itemOneMap, Func itemTwoMap, Func 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 so we can pattern match on it + return null; + } + } + + private OneOf(Maybe one, Maybe two, Maybe three) + { + _itemOne = one; + _itemTwo = two; + _itemThree = three; + } + + public static implicit operator OneOf(T1 oneOf) => new(oneOf, default, default); + public static implicit operator OneOf(T2 oneOf) => new(default, oneOf, default); + public static implicit operator OneOf(T3 oneOf) => new(default, default, oneOf); +} \ No newline at end of file