go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/projects/nodes/pkg/incrutil/node_helpers.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package incrutil
     9  
    10  import (
    11  	"fmt"
    12  
    13  	"github.com/wcharczuk/go-incr"
    14  	"go.charczuk.com/projects/nodes/pkg/types"
    15  )
    16  
    17  // LinkNodes adds inputs to a given child, associating the two nodes in the graph.
    18  func LinkNodes(child incr.INode, inputs ...incr.INode) error {
    19  	for _, input := range inputs {
    20  		if err := incr.ExpertGraph(incr.GraphForNode(child)).AddChild(child, input); err != nil {
    21  			return err
    22  		}
    23  	}
    24  	return nil
    25  }
    26  
    27  // Unlink nodes removes the metadata association between two nodes
    28  // but does _not_ remove node type specific input tracking.
    29  func UnlinkNodes(child incr.INode, inputs ...incr.INode) {
    30  	for _, input := range inputs {
    31  		incr.ExpertGraph(incr.GraphForNode(child)).RemoveParent(child, input)
    32  	}
    33  }
    34  
    35  // LabelOrID returns either the node's label or it's short id.
    36  func LabelOrID(n incr.INode) string {
    37  	if n.Node().Label() != "" {
    38  		return n.Node().Label()
    39  	}
    40  	return n.Node().ID().Short()
    41  }
    42  
    43  // SetNodeValueOnline calls set on a given node with the appropriate type.
    44  //
    45  // If the node is a var node, it will be marked as stale.
    46  func SetNodeValueOnline(n incr.INode, value any) error {
    47  	if typed, ok := n.(VarIncr[*types.Table]); ok {
    48  		if valueTyped, ok := value.(*types.Table); ok {
    49  			typed.Set(valueTyped)
    50  			return nil
    51  		}
    52  		if valueTyped, ok := value.(map[string]any); ok {
    53  			parsedTable, err := types.TableFromJSON(valueTyped)
    54  			if err != nil {
    55  				return err
    56  			}
    57  			typed.Set(parsedTable)
    58  			return nil
    59  		}
    60  		return fmt.Errorf("invalid var type to set value for: %T", value)
    61  	}
    62  	if typed, ok := n.(VarIncr[types.SVG]); ok {
    63  		if valueTyped, ok := value.(types.SVG); ok {
    64  			typed.Set(valueTyped)
    65  			return nil
    66  		}
    67  		if valueTyped, ok := value.(map[string]any); ok {
    68  			parsedSVG, err := types.SVGFromJSON(valueTyped)
    69  			if err != nil {
    70  				return err
    71  			}
    72  			typed.Set(*parsedSVG)
    73  			return nil
    74  		}
    75  		return fmt.Errorf("invalid var type to set value for: %T", value)
    76  	}
    77  	if typed, ok := n.(ISetRawValue); ok {
    78  		return typed.SetRawValue(value)
    79  	}
    80  	return nil
    81  }
    82  
    83  // SetNodeValueDuringDeserialization sets the underlying value for the node
    84  // but does _not_ mark the node as stale if it's a var!
    85  func SetNodeValueDuringDeserialization(n incr.INode, value any) error {
    86  	var typedValue any
    87  	switch GetNodeValue(n).(type) {
    88  	case *types.Table:
    89  		if valueTyped, ok := value.(*types.Table); ok {
    90  			typedValue = valueTyped
    91  		} else if valueTyped, ok := value.(map[string]any); ok {
    92  			parsedTable, err := types.TableFromJSON(valueTyped)
    93  			if err != nil {
    94  				return err
    95  			}
    96  			typedValue = parsedTable
    97  		}
    98  	case types.SVG:
    99  		if valueTyped, ok := value.(types.SVG); ok {
   100  			typedValue = valueTyped
   101  		} else if valueTyped, ok := value.(map[string]any); ok {
   102  			parsedSVG, err := types.SVGFromJSON(valueTyped)
   103  			if err != nil {
   104  				return err
   105  			}
   106  			typedValue = *parsedSVG
   107  		}
   108  	default:
   109  		typedValue = value
   110  	}
   111  	if typed, ok := n.(ISetRawVarValue); ok {
   112  		return typed.SetRawVarValue(typedValue)
   113  	}
   114  	if typed, ok := n.(ISetRawValue); ok {
   115  		return typed.SetRawValue(typedValue)
   116  	}
   117  	return nil
   118  }
   119  
   120  // GetNodeValue gets the raw value of a node.
   121  func GetNodeValue(n incr.INode) any {
   122  	switch typed := n.(type) {
   123  	case IRawValue:
   124  		return typed.RawValue()
   125  	default:
   126  		return nil
   127  	}
   128  }
   129  
   130  // ApplyNodeTableOps applies node table operations.
   131  //
   132  // This is only valid for incr types of table.
   133  func ApplyNodeTableOps(g *incr.Graph, n incr.INode, ops ...types.TableOp) error {
   134  	switch typed := n.(type) {
   135  	case VarIncr[*types.Table]:
   136  		if err := typed.Value().ApplyOps(ops...); err != nil {
   137  			return err
   138  		}
   139  		g.SetStale(n)
   140  		return nil
   141  	default:
   142  		return fmt.Errorf("invalid node value type for table ops apply: %T", typed)
   143  	}
   144  }