Code/Nodes/Core/Cast.cs
namespace Nodebox.Nodes {
    [Description("Cast a value of one type destination another")]
    [Tag("Core")]
    // [UI.Panel<UI.Cast>]
    public class Cast<TSource, TDestination> : Node {
        public override bool AreValidGenerics =>
            typeof(TSource) != typeof(object) &&
            typeof(TDestination) != typeof(object) &&
            typeof(TSource) != typeof(TDestination) &&
            (typeof(TSource).IsAssignableTo(typeof(TDestination)) ||
            TestCast()
            );
        private static bool TestCast() {
            if (
                TypeLibrary.GetType<TSource>().IsEnum &&
                TypeLibrary.GetType<TDestination>().IsEnum
            ) {
                return false;
            }

            try {
                _ = NumericCast.Cast<TSource, TDestination>(default);
                return true;
            }
            catch (Exception) { }

            try {
                _ = (TDestination)(object)default(TSource);
                return true;
            }
            catch (Exception) {
                return false;
            }
        }

        public override (List<Pin> In, List<Pin> Out) InitialPins => (
            [
                Pin.New<TSource>()
            ],
            [
                Pin.New<TDestination>()
            ]
        );
    }
}

namespace Nodebox.Execution {
    using Nodebox.Nodes;
    using static ExecutionContext;

    public class CastImplementation<TSource, TDestination> : Implementation {
        public override Type Target => typeof(Cast<TSource, TDestination>);
        public override bool IsValid => Node.GetAreValidGenerics(Target);
        public override void Evaluate(ExecutionContext context, Node node) {
            var io = context.Store[node];
            var src = io.GetInput<TSource>(0);
            TDestination dst;
            try {
                dst = (TDestination)(object)src;
            }
            catch (Exception) { }

            dst = NumericCast.Cast<TSource, TDestination>(src);


            io.SetOutput(0, dst);
        }
    }
}