github.com/egonelbre/exp@v0.0.0-20240430123955-ed1d3aa93911/view/parse.go (about)

     1  package view
     2  
     3  import "reflect"
     4  
     5  type Element interface{}
     6  
     7  type Prop struct {
     8  	Type  string
     9  	Value reflect.Value
    10  }
    11  
    12  type Node struct {
    13  	Name  string
    14  	Type  string
    15  	Value reflect.Value
    16  	Slice bool
    17  
    18  	Props    map[string]*Prop
    19  	Children []*Node
    20  }
    21  
    22  func parse(name string, v reflect.Value) (*Node, error) {
    23  	for v.Kind() == reflect.Ptr {
    24  		v = v.Elem()
    25  	}
    26  
    27  	if v.Kind() != reflect.Struct && v.Kind() != reflect.Slice {
    28  		panic("ViewModel should be a struct or slice.")
    29  	}
    30  
    31  	t := v.Type()
    32  
    33  	node := &Node{
    34  		Name:  name,
    35  		Type:  t.Name(),
    36  		Slice: v.Kind() == reflect.Slice,
    37  		Value: v,
    38  	}
    39  
    40  	if node.Type == "" {
    41  		node.Type = node.Name
    42  	}
    43  
    44  	if v.Kind() == reflect.Slice {
    45  		for i := 0; i < v.Len(); i++ {
    46  			f := v.Index(i)
    47  			child, err := parse("", f)
    48  			if err != nil {
    49  				return nil, err
    50  			}
    51  			node.Children = append(node.Children, child)
    52  		}
    53  		return node, nil
    54  	}
    55  
    56  	for i := 0; i < v.NumField(); i++ {
    57  		f := v.Field(i)
    58  		if f.Kind() == reflect.Struct || f.Kind() == reflect.Slice {
    59  			child, err := parse(t.Field(i).Name, f)
    60  			if err != nil {
    61  				return nil, err
    62  			}
    63  			node.Children = append(node.Children, child)
    64  		} else {
    65  			if node.Props == nil {
    66  				node.Props = make(map[string]*Prop)
    67  			}
    68  
    69  			name := t.Field(i).Name
    70  			node.Props[name] = &Prop{
    71  				Type:  f.Type().Name(),
    72  				Value: f,
    73  			}
    74  		}
    75  	}
    76  
    77  	return node, nil
    78  }
    79  
    80  func (n *Node) prop(name string) (*Prop, bool) {
    81  	if n.Props == nil {
    82  		return nil, false
    83  	}
    84  	prop, ok := n.Props[name]
    85  	return prop, ok
    86  }
    87  
    88  func (n *Node) Str(name string) (string, bool) {
    89  	v, ok := n.prop(name)
    90  	if !ok {
    91  		return "", false
    92  	}
    93  	return v.Value.String(), true
    94  }
    95  
    96  func (n *Node) Bool(name string) (bool, bool) {
    97  	v, ok := n.prop(name)
    98  	if !ok {
    99  		return false, false
   100  	}
   101  	return v.Value.Bool(), true
   102  }
   103  
   104  func Parse(name string, v interface{}) (*Node, error) {
   105  	return parse(name, reflect.ValueOf(v))
   106  }