mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			323 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			323 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package treeprint
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"reflect"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
type StructTreeOption int
 | 
						|
 | 
						|
const (
 | 
						|
	StructNameTree StructTreeOption = iota
 | 
						|
	StructValueTree
 | 
						|
	StructTagTree
 | 
						|
	StructTypeTree
 | 
						|
	StructTypeSizeTree
 | 
						|
)
 | 
						|
 | 
						|
func FromStruct(v interface{}, opt ...StructTreeOption) (Tree, error) {
 | 
						|
	var treeOpt StructTreeOption
 | 
						|
	if len(opt) > 0 {
 | 
						|
		treeOpt = opt[0]
 | 
						|
	}
 | 
						|
	switch treeOpt {
 | 
						|
	case StructNameTree:
 | 
						|
		tree := New()
 | 
						|
		err := nameTree(tree, v)
 | 
						|
		return tree, err
 | 
						|
	case StructValueTree:
 | 
						|
		tree := New()
 | 
						|
		err := valueTree(tree, v)
 | 
						|
		return tree, err
 | 
						|
	case StructTagTree:
 | 
						|
		tree := New()
 | 
						|
		err := tagTree(tree, v)
 | 
						|
		return tree, err
 | 
						|
	case StructTypeTree:
 | 
						|
		tree := New()
 | 
						|
		err := typeTree(tree, v)
 | 
						|
		return tree, err
 | 
						|
	case StructTypeSizeTree:
 | 
						|
		tree := New()
 | 
						|
		err := typeSizeTree(tree, v)
 | 
						|
		return tree, err
 | 
						|
	default:
 | 
						|
		err := fmt.Errorf("treeprint: invalid StructTreeOption %v", treeOpt)
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type FmtFunc func(name string, v interface{}) (string, bool)
 | 
						|
 | 
						|
func FromStructWithMeta(v interface{}, fmtFunc FmtFunc) (Tree, error) {
 | 
						|
	if fmtFunc == nil {
 | 
						|
		tree := New()
 | 
						|
		err := nameTree(tree, v)
 | 
						|
		return tree, err
 | 
						|
	}
 | 
						|
	tree := New()
 | 
						|
	err := metaTree(tree, v, fmtFunc)
 | 
						|
	return tree, err
 | 
						|
}
 | 
						|
 | 
						|
func Repr(v interface{}) string {
 | 
						|
	tree := New()
 | 
						|
	vType := reflect.TypeOf(v)
 | 
						|
	vValue := reflect.ValueOf(v)
 | 
						|
	_, val, isStruct := getValue(vType, &vValue)
 | 
						|
	if !isStruct {
 | 
						|
		return fmt.Sprintf("%+v", val.Interface())
 | 
						|
	}
 | 
						|
	err := valueTree(tree, val.Interface())
 | 
						|
	if err != nil {
 | 
						|
		return err.Error()
 | 
						|
	}
 | 
						|
	return tree.String()
 | 
						|
}
 | 
						|
 | 
						|
func nameTree(tree Tree, v interface{}) error {
 | 
						|
	typ, val, err := checkType(v)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	fields := typ.NumField()
 | 
						|
	for i := 0; i < fields; i++ {
 | 
						|
		field := typ.Field(i)
 | 
						|
		fieldValue := val.Field(i)
 | 
						|
		name, skip, omit := getMeta(field.Name, field.Tag)
 | 
						|
		if skip || omit && isEmpty(&fieldValue) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		typ, val, isStruct := getValue(field.Type, &fieldValue)
 | 
						|
		if !isStruct {
 | 
						|
			tree.AddNode(name)
 | 
						|
			continue
 | 
						|
		} else if subNum := typ.NumField(); subNum == 0 {
 | 
						|
			tree.AddNode(name)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		branch := tree.AddBranch(name)
 | 
						|
		if err := nameTree(branch, val.Interface()); err != nil {
 | 
						|
			err := fmt.Errorf("%v on struct branch %s", err, name)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func getMeta(fieldName string, tag reflect.StructTag) (name string, skip, omit bool) {
 | 
						|
	if tagStr := tag.Get("tree"); len(tagStr) > 0 {
 | 
						|
		name, omit = tagSpec(tagStr)
 | 
						|
	}
 | 
						|
	if name == "-" {
 | 
						|
		return fieldName, true, omit
 | 
						|
	}
 | 
						|
	if len(name) == 0 {
 | 
						|
		name = fieldName
 | 
						|
	} else if trimmed := strings.TrimSpace(name); len(trimmed) == 0 {
 | 
						|
		name = fieldName
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func valueTree(tree Tree, v interface{}) error {
 | 
						|
	typ, val, err := checkType(v)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	fields := typ.NumField()
 | 
						|
	for i := 0; i < fields; i++ {
 | 
						|
		field := typ.Field(i)
 | 
						|
		fieldValue := val.Field(i)
 | 
						|
		name, skip, omit := getMeta(field.Name, field.Tag)
 | 
						|
		if skip || omit && isEmpty(&fieldValue) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		typ, val, isStruct := getValue(field.Type, &fieldValue)
 | 
						|
		if !isStruct {
 | 
						|
			tree.AddMetaNode(val.Interface(), name)
 | 
						|
			continue
 | 
						|
		} else if subNum := typ.NumField(); subNum == 0 {
 | 
						|
			tree.AddMetaNode(val.Interface(), name)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		branch := tree.AddBranch(name)
 | 
						|
		if err := valueTree(branch, val.Interface()); err != nil {
 | 
						|
			err := fmt.Errorf("%v on struct branch %s", err, name)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func tagTree(tree Tree, v interface{}) error {
 | 
						|
	typ, val, err := checkType(v)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	fields := typ.NumField()
 | 
						|
	for i := 0; i < fields; i++ {
 | 
						|
		field := typ.Field(i)
 | 
						|
		fieldValue := val.Field(i)
 | 
						|
		name, skip, omit := getMeta(field.Name, field.Tag)
 | 
						|
		if skip || omit && isEmpty(&fieldValue) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		filteredTag := filterTags(field.Tag)
 | 
						|
		typ, val, isStruct := getValue(field.Type, &fieldValue)
 | 
						|
		if !isStruct {
 | 
						|
			tree.AddMetaNode(filteredTag, name)
 | 
						|
			continue
 | 
						|
		} else if subNum := typ.NumField(); subNum == 0 {
 | 
						|
			tree.AddMetaNode(filteredTag, name)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		branch := tree.AddMetaBranch(filteredTag, name)
 | 
						|
		if err := tagTree(branch, val.Interface()); err != nil {
 | 
						|
			err := fmt.Errorf("%v on struct branch %s", err, name)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func typeTree(tree Tree, v interface{}) error {
 | 
						|
	typ, val, err := checkType(v)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	fields := typ.NumField()
 | 
						|
	for i := 0; i < fields; i++ {
 | 
						|
		field := typ.Field(i)
 | 
						|
		fieldValue := val.Field(i)
 | 
						|
		name, skip, omit := getMeta(field.Name, field.Tag)
 | 
						|
		if skip || omit && isEmpty(&fieldValue) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		typ, val, isStruct := getValue(field.Type, &fieldValue)
 | 
						|
		typename := fmt.Sprintf("%T", val.Interface())
 | 
						|
		if !isStruct {
 | 
						|
			tree.AddMetaNode(typename, name)
 | 
						|
			continue
 | 
						|
		} else if subNum := typ.NumField(); subNum == 0 {
 | 
						|
			tree.AddMetaNode(typename, name)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		branch := tree.AddMetaBranch(typename, name)
 | 
						|
		if err := typeTree(branch, val.Interface()); err != nil {
 | 
						|
			err := fmt.Errorf("%v on struct branch %s", err, name)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func typeSizeTree(tree Tree, v interface{}) error {
 | 
						|
	typ, val, err := checkType(v)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	fields := typ.NumField()
 | 
						|
	for i := 0; i < fields; i++ {
 | 
						|
		field := typ.Field(i)
 | 
						|
		fieldValue := val.Field(i)
 | 
						|
		name, skip, omit := getMeta(field.Name, field.Tag)
 | 
						|
		if skip || omit && isEmpty(&fieldValue) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		typ, val, isStruct := getValue(field.Type, &fieldValue)
 | 
						|
		typesize := typ.Size()
 | 
						|
		if !isStruct {
 | 
						|
			tree.AddMetaNode(typesize, name)
 | 
						|
			continue
 | 
						|
		} else if subNum := typ.NumField(); subNum == 0 {
 | 
						|
			tree.AddMetaNode(typesize, name)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		branch := tree.AddMetaBranch(typesize, name)
 | 
						|
		if err := typeSizeTree(branch, val.Interface()); err != nil {
 | 
						|
			err := fmt.Errorf("%v on struct branch %s", err, name)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func metaTree(tree Tree, v interface{}, fmtFunc FmtFunc) error {
 | 
						|
	typ, val, err := checkType(v)
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	fields := typ.NumField()
 | 
						|
	for i := 0; i < fields; i++ {
 | 
						|
		field := typ.Field(i)
 | 
						|
		fieldValue := val.Field(i)
 | 
						|
		name, skip, omit := getMeta(field.Name, field.Tag)
 | 
						|
		if skip || omit && isEmpty(&fieldValue) {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		typ, val, isStruct := getValue(field.Type, &fieldValue)
 | 
						|
		formatted, show := fmtFunc(name, val.Interface())
 | 
						|
		if !isStruct {
 | 
						|
			if show {
 | 
						|
				tree.AddMetaNode(formatted, name)
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			tree.AddNode(name)
 | 
						|
			continue
 | 
						|
		} else if subNum := typ.NumField(); subNum == 0 {
 | 
						|
			if show {
 | 
						|
				tree.AddMetaNode(formatted, name)
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			tree.AddNode(name)
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		var branch Tree
 | 
						|
		if show {
 | 
						|
			branch = tree.AddMetaBranch(formatted, name)
 | 
						|
		} else {
 | 
						|
			branch = tree.AddBranch(name)
 | 
						|
		}
 | 
						|
		if err := metaTree(branch, val.Interface(), fmtFunc); err != nil {
 | 
						|
			err := fmt.Errorf("%v on struct branch %s", err, name)
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func getValue(typ reflect.Type, val *reflect.Value) (reflect.Type, *reflect.Value, bool) {
 | 
						|
	switch typ.Kind() {
 | 
						|
	case reflect.Ptr:
 | 
						|
		typ = typ.Elem()
 | 
						|
		if typ.Kind() == reflect.Struct {
 | 
						|
			elem := val.Elem()
 | 
						|
			return typ, &elem, true
 | 
						|
		}
 | 
						|
	case reflect.Struct:
 | 
						|
		return typ, val, true
 | 
						|
	}
 | 
						|
	return typ, val, false
 | 
						|
}
 | 
						|
 | 
						|
func checkType(v interface{}) (reflect.Type, *reflect.Value, error) {
 | 
						|
	typ := reflect.TypeOf(v)
 | 
						|
	val := reflect.ValueOf(v)
 | 
						|
	switch typ.Kind() {
 | 
						|
	case reflect.Ptr:
 | 
						|
		typ = typ.Elem()
 | 
						|
		if typ.Kind() != reflect.Struct {
 | 
						|
			err := fmt.Errorf("treeprint: %T is not a struct we could work with", v)
 | 
						|
			return nil, nil, err
 | 
						|
		}
 | 
						|
		val = val.Elem()
 | 
						|
	case reflect.Struct:
 | 
						|
	default:
 | 
						|
		err := fmt.Errorf("treeprint: %T is not a struct we could work with", v)
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
	return typ, &val, nil
 | 
						|
}
 |