static bool HandleVariable(GraphBuilder builder, out INode node,
                                   out PortMapper portToOffsetMapping, out uint?preAllocatedDataIndex, IVariableModel variableModel)
        {
            if (variableModel.DeclarationModel.IsInputOrOutputTrigger())
            {
                preAllocatedDataIndex = null;
                portToOffsetMapping   = new PortMapper();
                if (variableModel.DeclarationModel.Modifiers == ModifierFlags.ReadOnly) // Input
                {
                    var trigger = builder.DeclareInputTrigger(variableModel.DeclarationModel.VariableName);
                    node = MapPort(portToOffsetMapping, variableModel.OutputPort, ref trigger.Output.Port, trigger);
                }
                else
                {
                    var trigger = builder.DeclareOutputTrigger(variableModel.DeclarationModel.VariableName);
                    node = MapPort(portToOffsetMapping, variableModel.OutputPort, ref trigger.Input.Port, trigger);
                }
                return(true);
            }

            var valueType = variableModel.DeclarationModel.DataType.ToValueType();
            var type      = GraphBuilder.GetVariableType(variableModel.DeclarationModel);

            switch (type)
            {
            case GraphBuilder.VariableType.ObjectReference:
                switch (valueType)
                {
                case ValueType.Entity:
                    preAllocatedDataIndex = builder.GetVariableDataIndex(variableModel.DeclarationModel).DataIndex;
                    portToOffsetMapping   = new PortMapper();
                    var cf = new ConstantEntity();
                    node = MapPort(portToOffsetMapping, variableModel.OutputPort, ref cf.ValuePort.Port, cf);
                    return(true);
                }
                break;

            case GraphBuilder.VariableType.Variable:     // Data
                throw new NotImplementedException();

            case GraphBuilder.VariableType.InputOutput:
                // Just create an edge later
                node = default;
                portToOffsetMapping   = null;
                preAllocatedDataIndex = null;
                return(false);

            default:
                throw new ArgumentOutOfRangeException("Variable type not supported: " + type);
            }

            throw new ArgumentOutOfRangeException(valueType.ToString());
        }
        static bool TranslateNode(GraphBuilder builder, INodeModel nodeModel, out INode node,
                                  out PortMapper portToOffsetMapping, out uint?preAllocatedDataIndex)
        {
            Assert.IsNotNull(nodeModel);
            preAllocatedDataIndex = null;

            switch (nodeModel)
            {
            case SetVariableNodeModel setVariableNodeModel:
            {
                node = setVariableNodeModel.Node;
                portToOffsetMapping = setVariableNodeModel.PortToOffsetMapping;
                if (setVariableNodeModel.DeclarationModel == null)
                {
                    return(false);
                }
                preAllocatedDataIndex = builder.GetVariableDataIndex(setVariableNodeModel.DeclarationModel).DataIndex;
                return(true);
            }

            case IEventNodeModel eventNodeModel:
                node = eventNodeModel.Node;
                var type = eventNodeModel.TypeHandle.Resolve(nodeModel.VSGraphModel.Stencil);
                ((IEventNode)node).EventId = TypeHash.CalculateStableTypeHash(type);

                if (node is IEventDispatcherNode eventDispatcherNode)
                {
                    eventDispatcherNode.EventTypeSize = Marshal.SizeOf(type);
                }

                portToOffsetMapping = eventNodeModel.PortToOffsetMapping;
                return(true);

            case SubgraphReferenceNodeModel subgraphReferenceNodeModel:
                node = subgraphReferenceNodeModel.Node;
                portToOffsetMapping = subgraphReferenceNodeModel.PortToOffsetMapping;
                return(true);

            case IDotsNodeModel dotsNodeModel:
                node = dotsNodeModel.Node;
                portToOffsetMapping = dotsNodeModel.PortToOffsetMapping;
                if (nodeModel is IReferenceComponentTypes referenceComponentTypes)
                {
                    foreach (var typeReference in referenceComponentTypes.ReferencedTypes)
                    {
                        if (typeReference.TypeIndex != -1)
                        {
                            builder.AddReferencedComponent(typeReference);
                        }
                    }
                }
                return(true);

            case IConstantNodeModel constantNodeModel:
                HandleConstants(builder, out node, out portToOffsetMapping, constantNodeModel);
                return(true);

            case IVariableModel variableModel:
                return(HandleVariable(builder, out node, out portToOffsetMapping,
                                      out preAllocatedDataIndex, variableModel));

            case ExpressionNodeModel exp:
                return(exp.Translate(builder, out node, out portToOffsetMapping, out preAllocatedDataIndex));

            default:
                throw new NotImplementedException(
                          $"Don't know how to translate a node of type {nodeModel.GetType()}: {nodeModel}");
            }
        }
        static void HandleConstants(GraphBuilder builder, out INode node, out PortMapper portToOffsetMapping,
                                    IConstantNodeModel constantNodeModel)
        {
            portToOffsetMapping = new PortMapper();
            var outputPortId = constantNodeModel.OutputPort?.UniqueId ?? "";

            switch (constantNodeModel)
            {
            case StringConstantModel stringConstantModel:
            {
                var index = builder.StoreStringConstant(stringConstantModel.value ?? string.Empty);
                var cf    = new ConstantString {
                    Value = new StringReference(index, StringReference.Storage.Managed)
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case BooleanConstantNodeModel booleanConstantNodeModel:
            {
                var cf = new ConstantBool {
                    Value = booleanConstantNodeModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case IntConstantModel intConstantModel:
            {
                var cf = new ConstantInt {
                    Value = intConstantModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case FloatConstantModel floatConstantModel:
            {
                var cf = new ConstantFloat {
                    Value = floatConstantModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case Vector2ConstantModel vector2ConstantModel:
            {
                var cf = new ConstantFloat2 {
                    Value = vector2ConstantModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case Vector3ConstantModel vector3ConstantModel:
            {
                var cf = new ConstantFloat3 {
                    Value = vector3ConstantModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case Vector4ConstantModel vector4ConstantModel:
            {
                var cf = new ConstantFloat4 {
                    Value = vector4ConstantModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case QuaternionConstantModel quaternionConstantModel:
            {
                var cf = new ConstantQuaternion {
                    Value = quaternionConstantModel.value
                };
                node = MapPort(portToOffsetMapping, outputPortId, Direction.Output, ref cf.ValuePort.Port, cf);
                return;
            }

            case ObjectConstantModel _:
            {
                throw new NotImplementedException(
                          "Conversion and all - either a prefab (might live in a graph) or a scene object (must be injected during runtime bootstrap)");

                // portToOffsetMapping = new Dictionary<IPortModel, uint>();
                // var cf = new ConstantEntity {Value = objectConstantModel.value};
                // MapPort(portToOffsetMapping, objectConstantModel.OutputPort, ref cf.ValuePort.Port, nodeId);
                // node = cf;
                // return;
            }

            default:
                throw new NotImplementedException();
            }
        }