123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- 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)
- }
- 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
- }
|