func isValid(id string) bool {
	ok := id != "" && id != "_"
	for j, c := range id {
		ok = ok && (j > 0 || !unicode.IsDigit(c))
		ok = ok && (c == '_' || unicode.IsLetter(c) || unicode.IsDigit(c))
	}
	return ok
}
isValid reports whether the identifier is valid.
Empty and underscore-only strings are not valid.
package cmp
import (
	"fmt"
	"reflect"
	"strings"
	"unicode"
	"unicode/utf8"
)
type (
	Path []PathStep
	PathStep interface {
		String() string
		Type() reflect.Type  
		isPathStep()
	}
	SliceIndex interface {
		PathStep
		Key() int  
		SplitKeys() (x int, y int)
		isSliceIndex()
	}
	MapIndex interface {
		PathStep
		Key() reflect.Value
		isMapIndex()
	}
	TypeAssertion interface {
		PathStep
		isTypeAssertion()
	}
	StructField interface {
		PathStep
		Name() string
		Index() int
		isStructField()
	}
	Indirect interface {
		PathStep
		isIndirect()
	}
	Transform interface {
		PathStep
		Name() string
		Func() reflect.Value
		Option() Option
		isTransform()
	}
)
func (pa *Path) push(s PathStep) {
	*pa = append(*pa, s)
}
func (pa *Path) pop() {
	*pa = (*pa)[:len(*pa)-1]
}
func (pa Path) Last() PathStep {
	return pa.Index(-1)
}
func (pa Path) Index(i int) PathStep {
	if i < 0 {
		i = len(pa) + i
	}
	if i < 0 || i >= len(pa) {
		return pathStep{}
	}
	return pa[i]
}
func (pa Path) String() string {
	var ss []string
	for _, s := range pa {
		if _, ok := s.(*structField); ok {
			ss = append(ss, s.String())
		}
	}
	return strings.TrimPrefix(strings.Join(ss, ""), ".")
}
func (pa Path) GoString() string {
	var ssPre, ssPost []string
	var numIndirect int
	for i, s := range pa {
		var nextStep PathStep
		if i+1 < len(pa) {
			nextStep = pa[i+1]
		}
		switch s := s.(type) {
		case *indirect:
			numIndirect++
			pPre, pPost := "(", ")"
			switch nextStep.(type) {
			case *indirect:
				continue  
			case *structField:
				numIndirect--  
			case nil:
				pPre, pPost = "", ""  
			}
			if numIndirect > 0 {
				ssPre = append(ssPre, pPre+strings.Repeat("*", numIndirect))
				ssPost = append(ssPost, pPost)
			}
			numIndirect = 0
			continue
		case *transform:
			ssPre = append(ssPre, s.trans.name+"(")
			ssPost = append(ssPost, ")")
			continue
		case *typeAssertion:
			if s.Type().PkgPath() == "" {
				continue
			}
		}
		ssPost = append(ssPost, s.String())
	}
	for i, j := 0, len(ssPre)-1; i < j; i, j = i+1, j-1 {
		ssPre[i], ssPre[j] = ssPre[j], ssPre[i]
	}
	return strings.Join(ssPre, "") + strings.Join(ssPost, "")
}
type (
	pathStep struct {
		typ reflect.Type
	}
	sliceIndex struct {
		pathStep
		xkey, ykey int
	}
	mapIndex struct {
		pathStep
		key reflect.Value
	}
	typeAssertion struct {
		pathStep
	}
	structField struct {
		pathStep
		name string
		idx  int
		unexported bool
		force      bool                 
		pvx, pvy   reflect.Value        
		field      reflect.StructField  
	}
	indirect struct {
		pathStep
	}
	transform struct {
		pathStep
		trans *transformer
	}
)
func (ps pathStep) Type() reflect.Type { return ps.typ }
func (ps pathStep) String() string {
	if ps.typ == nil {
		return "<nil>"
	}
	s := ps.typ.String()
	if s == "" || strings.ContainsAny(s, "{}\n") {
		return "root"  
	}
	return fmt.Sprintf("{%s}", s)
}
func (si sliceIndex) String() string {
	switch {
	case si.xkey == si.ykey:
		return fmt.Sprintf("[%d]", si.xkey)
	case si.ykey == -1:
		return fmt.Sprintf("[%d->?]", si.xkey)
	case si.xkey == -1:
		return fmt.Sprintf("[?->%d]", si.ykey)
	default:
		return fmt.Sprintf("[%d->%d]", si.xkey, si.ykey)
	}
}
func (mi mapIndex) String() string      { return fmt.Sprintf("[%#v]", mi.key) }
func (ta typeAssertion) String() string { return fmt.Sprintf(".(%v)", ta.typ) }
func (sf structField) String() string   { return fmt.Sprintf(".%s", sf.name) }
func (in indirect) String() string      { return "*" }
func (tf transform) String() string     { return fmt.Sprintf("%s()", tf.trans.name) }
func (si sliceIndex) Key() int {
	if si.xkey != si.ykey {
		return -1
	}
	return si.xkey
}
func (si sliceIndex) SplitKeys() (x, y int) { return si.xkey, si.ykey }
func (mi mapIndex) Key() reflect.Value      { return mi.key }
func (sf structField) Name() string         { return sf.name }
func (sf structField) Index() int           { return sf.idx }
func (tf transform) Name() string           { return tf.trans.name }
func (tf transform) Func() reflect.Value    { return tf.trans.fnc }
func (tf transform) Option() Option         { return tf.trans }
func (pathStep) isPathStep()           {}
func (sliceIndex) isSliceIndex()       {}
func (mapIndex) isMapIndex()           {}
func (typeAssertion) isTypeAssertion() {}
func (structField) isStructField()     {}
func (indirect) isIndirect()           {}
func (transform) isTransform()         {}
var (
	_ SliceIndex    = sliceIndex{}
	_ MapIndex      = mapIndex{}
	_ TypeAssertion = typeAssertion{}
	_ StructField   = structField{}
	_ Indirect      = indirect{}
	_ Transform     = transform{}
	_ PathStep = sliceIndex{}
	_ PathStep = mapIndex{}
	_ PathStep = typeAssertion{}
	_ PathStep = structField{}
	_ PathStep = indirect{}
	_ PathStep = transform{}
)
func isExported(id string) bool {
	r, _ := utf8.DecodeRuneInString(id)
	return unicode.IsUpper(r)
}