github.com/bytedance/go-tagexpr/v2@v2.9.8/tagexpr.go (about)

     1  // Package tagexpr is an interesting go struct tag expression syntax for field validation, etc.
     2  //
     3  // Copyright 2019 Bytedance Inc. All Rights Reserved.
     4  //
     5  // Licensed under the Apache License, Version 2.0 (the "License");
     6  // you may not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //	http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing, software
    12  // distributed under the License is distributed on an "AS IS" BASIS,
    13  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14  // See the License for the specific language governing permissions and
    15  // limitations under the License.
    16  package tagexpr
    17  
    18  import (
    19  	"errors"
    20  	"fmt"
    21  	"reflect"
    22  	"strconv"
    23  	"strings"
    24  	"sync"
    25  	"unsafe"
    26  
    27  	"github.com/andeya/ameda"
    28  )
    29  
    30  // Internally unified data types
    31  type (
    32  	Number  = float64
    33  	Null    = interface{}
    34  	Boolean = bool
    35  	String  = string
    36  )
    37  
    38  // VM struct tag expression interpreter
    39  type VM struct {
    40  	tagName   string
    41  	structJar map[uintptr]*structVM
    42  	rw        sync.RWMutex
    43  }
    44  
    45  // structVM tag expression set of struct
    46  type structVM struct {
    47  	vm                         *VM
    48  	name                       string
    49  	fields                     map[string]*fieldVM
    50  	fieldSelectorList          []string
    51  	fieldsWithIndirectStructVM []*fieldVM
    52  	exprs                      map[string]*Expr
    53  	exprSelectorList           []string
    54  	ifaceTagExprGetters        []func(unsafe.Pointer, string, func(*TagExpr, error) error) error
    55  	err                        error
    56  }
    57  
    58  // fieldVM tag expression set of struct field
    59  type fieldVM struct {
    60  	structField            reflect.StructField
    61  	ptrDeep                int
    62  	getPtr                 func(unsafe.Pointer) unsafe.Pointer
    63  	elemType               reflect.Type
    64  	elemKind               reflect.Kind
    65  	valueGetter            func(unsafe.Pointer) interface{}
    66  	reflectValueGetter     func(unsafe.Pointer, bool) reflect.Value
    67  	exprs                  map[string]*Expr
    68  	origin                 *structVM
    69  	mapKeyStructVM         *structVM
    70  	mapOrSliceElemStructVM *structVM
    71  	mapOrSliceIfaceKinds   [2]bool // [value, key/index]
    72  	fieldSelector          string
    73  	tagOp                  string
    74  }
    75  
    76  // New creates a tag expression interpreter that uses tagName as the tag name.
    77  // NOTE:
    78  //
    79  //	If no tagName is specified, no tag expression will be interpreted,
    80  //	but still can operate the various fields.
    81  func New(tagName ...string) *VM {
    82  	if len(tagName) == 0 {
    83  		tagName = append(tagName, "")
    84  	}
    85  	return &VM{
    86  		tagName:   tagName[0],
    87  		structJar: make(map[uintptr]*structVM, 256),
    88  	}
    89  }
    90  
    91  // MustRun is similar to Run, but panic when error.
    92  func (vm *VM) MustRun(structOrStructPtrOrReflectValue interface{}) *TagExpr {
    93  	te, err := vm.Run(structOrStructPtrOrReflectValue)
    94  	if err != nil {
    95  		panic(err)
    96  	}
    97  	return te
    98  }
    99  
   100  var (
   101  	unsupportNil        = errors.New("unsupport data: nil")
   102  	unsupportCannotAddr = errors.New("unsupport data: can not addr")
   103  )
   104  
   105  // Run returns the tag expression handler of the @structPtrOrReflectValue.
   106  // NOTE:
   107  //
   108  //	If the structure type has not been warmed up,
   109  //	it will be slower when it is first called.
   110  //
   111  // Disable new -d=checkptr behaviour for Go 1.14
   112  //
   113  //go:nocheckptr
   114  func (vm *VM) Run(structPtrOrReflectValue interface{}) (*TagExpr, error) {
   115  	var v reflect.Value
   116  	switch t := structPtrOrReflectValue.(type) {
   117  	case reflect.Value:
   118  		v = ameda.DereferenceValue(t)
   119  	default:
   120  		v = ameda.DereferenceValue(reflect.ValueOf(t))
   121  	}
   122  	if err := checkStructMapAddr(v); err != nil {
   123  		return nil, err
   124  	}
   125  
   126  	u := ameda.ValueFrom2(&v)
   127  	ptr := unsafe.Pointer(u.Pointer())
   128  	if ptr == nil {
   129  		return nil, unsupportNil
   130  	}
   131  
   132  	tid := u.RuntimeTypeID()
   133  	var err error
   134  	vm.rw.RLock()
   135  	s, ok := vm.structJar[tid]
   136  	vm.rw.RUnlock()
   137  	if !ok {
   138  		vm.rw.Lock()
   139  		s, ok = vm.structJar[tid]
   140  		if !ok {
   141  			s, err = vm.registerStructLocked(v.Type())
   142  			if err != nil {
   143  				vm.rw.Unlock()
   144  				return nil, err
   145  			}
   146  		}
   147  		vm.rw.Unlock()
   148  	}
   149  	if s.err != nil {
   150  		return nil, s.err
   151  	}
   152  	return s.newTagExpr(ptr, ""), nil
   153  }
   154  
   155  // RunAny returns the tag expression handler for the @v.
   156  // NOTE:
   157  //
   158  //	The @v can be structured data such as struct, map, slice, array, interface, reflcet.Value, etc.
   159  //	If the structure type has not been warmed up,
   160  //	it will be slower when it is first called.
   161  func (vm *VM) RunAny(v interface{}, fn func(*TagExpr, error) error) error {
   162  	vv, isReflectValue := v.(reflect.Value)
   163  	if !isReflectValue {
   164  		vv = reflect.ValueOf(v)
   165  	}
   166  	return vm.subRunAll(false, "", vv, fn)
   167  }
   168  
   169  // check type: struct{F map[T1]T2}
   170  func checkStructMapAddr(v reflect.Value) error {
   171  	if !v.IsValid() || v.CanAddr() || v.NumField() != 1 || v.Field(0).Kind() != reflect.Map {
   172  		return nil
   173  	}
   174  	return unsupportCannotAddr
   175  }
   176  
   177  func (vm *VM) subRunAll(omitNil bool, tePath string, value reflect.Value, fn func(*TagExpr, error) error) error {
   178  	rv := ameda.DereferenceInterfaceValue(value)
   179  	if !rv.IsValid() {
   180  		return nil
   181  	}
   182  	rt := ameda.DereferenceType(rv.Type())
   183  	rv = ameda.DereferenceValue(rv)
   184  	switch rt.Kind() {
   185  	case reflect.Struct:
   186  		if len(tePath) == 0 {
   187  			if err := checkStructMapAddr(rv); err != nil {
   188  				return err
   189  			}
   190  		}
   191  		u := ameda.ValueFrom2(&rv)
   192  		ptr := unsafe.Pointer(u.Pointer())
   193  		if ptr == nil {
   194  			if omitNil {
   195  				return nil
   196  			}
   197  			return fn(nil, unsupportNil)
   198  		}
   199  		return fn(vm.subRun(tePath, rt, u.RuntimeTypeID(), ptr))
   200  
   201  	case reflect.Slice, reflect.Array:
   202  		count := rv.Len()
   203  		if count == 0 {
   204  			return nil
   205  		}
   206  		switch ameda.DereferenceType(rv.Type().Elem()).Kind() {
   207  		case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
   208  			for i := count - 1; i >= 0; i-- {
   209  				err := vm.subRunAll(omitNil, tePath+"["+strconv.Itoa(i)+"]", rv.Index(i), fn)
   210  				if err != nil {
   211  					return err
   212  				}
   213  			}
   214  		default:
   215  			return nil
   216  		}
   217  
   218  	case reflect.Map:
   219  		if rv.Len() == 0 {
   220  			return nil
   221  		}
   222  		var canKey, canValue bool
   223  		rt := rv.Type()
   224  		switch ameda.DereferenceType(rt.Key()).Kind() {
   225  		case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
   226  			canKey = true
   227  		}
   228  		switch ameda.DereferenceType(rt.Elem()).Kind() {
   229  		case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
   230  			canValue = true
   231  		}
   232  		if !canKey && !canValue {
   233  			return nil
   234  		}
   235  		for _, key := range rv.MapKeys() {
   236  			if canKey {
   237  				err := vm.subRunAll(omitNil, tePath+"{k}", key, fn)
   238  				if err != nil {
   239  					return err
   240  				}
   241  			}
   242  			if canValue {
   243  				err := vm.subRunAll(omitNil, tePath+"{v for k="+key.String()+"}", rv.MapIndex(key), fn)
   244  				if err != nil {
   245  					return err
   246  				}
   247  			}
   248  		}
   249  	}
   250  	return nil
   251  }
   252  
   253  func (vm *VM) subRun(path string, t reflect.Type, tid uintptr, ptr unsafe.Pointer) (*TagExpr, error) {
   254  	var err error
   255  	vm.rw.RLock()
   256  	s, ok := vm.structJar[tid]
   257  	vm.rw.RUnlock()
   258  	if !ok {
   259  		vm.rw.Lock()
   260  		s, ok = vm.structJar[tid]
   261  		if !ok {
   262  			s, err = vm.registerStructLocked(t)
   263  			if err != nil {
   264  				vm.rw.Unlock()
   265  				return nil, err
   266  			}
   267  		}
   268  		vm.rw.Unlock()
   269  	}
   270  	if s.err != nil {
   271  		return nil, s.err
   272  	}
   273  	return s.newTagExpr(ptr, path), nil
   274  }
   275  
   276  func (vm *VM) registerStructLocked(structType reflect.Type) (*structVM, error) {
   277  	structType, err := vm.getStructType(structType)
   278  	if err != nil {
   279  		return nil, err
   280  	}
   281  	tid := ameda.RuntimeTypeID(structType)
   282  	s, had := vm.structJar[tid]
   283  	if had {
   284  		return s, s.err
   285  	}
   286  	s = vm.newStructVM()
   287  	s.name = structType.String()
   288  	vm.structJar[tid] = s
   289  	var numField = structType.NumField()
   290  	var structField reflect.StructField
   291  	var sub *structVM
   292  	for i := 0; i < numField; i++ {
   293  		structField = structType.Field(i)
   294  		field, ok, err := s.newFieldVM(structField)
   295  		if err != nil {
   296  			s.err = err
   297  			return nil, err
   298  		}
   299  		// skip omitted tag
   300  		if !ok {
   301  			continue
   302  		}
   303  		switch field.elemKind {
   304  		default:
   305  			field.setUnsupportGetter()
   306  			switch field.elemKind {
   307  			case reflect.Struct:
   308  				sub, err = vm.registerStructLocked(field.structField.Type)
   309  				if err != nil {
   310  					s.err = err
   311  					return nil, err
   312  				}
   313  				s.mergeSubStructVM(field, sub)
   314  			case reflect.Interface:
   315  				s.setIfaceTagExprGetter(field)
   316  			}
   317  		case reflect.Float32, reflect.Float64,
   318  			reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
   319  			reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   320  			field.setFloatGetter()
   321  		case reflect.String:
   322  			field.setStringGetter()
   323  		case reflect.Bool:
   324  			field.setBoolGetter()
   325  		case reflect.Array, reflect.Slice, reflect.Map:
   326  			err = vm.registerIndirectStructLocked(field)
   327  			if err != nil {
   328  				s.err = err
   329  				return nil, err
   330  			}
   331  		}
   332  	}
   333  	return s, nil
   334  }
   335  
   336  func (vm *VM) registerIndirectStructLocked(field *fieldVM) error {
   337  	field.setLengthGetter()
   338  	if field.tagOp == tagOmit {
   339  		return nil
   340  	}
   341  	a := make([]reflect.Type, 1, 2)
   342  	a[0] = derefType(field.elemType.Elem())
   343  	if field.elemKind == reflect.Map {
   344  		a = append(a, derefType(field.elemType.Key()))
   345  	}
   346  	for i, t := range a {
   347  		kind := t.Kind()
   348  		switch kind {
   349  		case reflect.Interface:
   350  			field.mapOrSliceIfaceKinds[i] = true
   351  			field.origin.fieldsWithIndirectStructVM = appendDistinct(field.origin.fieldsWithIndirectStructVM, field)
   352  		case reflect.Slice, reflect.Array, reflect.Map:
   353  			tt := t.Elem()
   354  			checkMap := kind == reflect.Map
   355  		F2:
   356  			for {
   357  				switch tt.Kind() {
   358  				case reflect.Slice, reflect.Array, reflect.Map, reflect.Ptr:
   359  					tt = tt.Elem()
   360  				case reflect.Struct:
   361  					_, err := vm.registerStructLocked(tt)
   362  					if err != nil {
   363  						return err
   364  					}
   365  					field.mapOrSliceIfaceKinds[i] = true
   366  					field.origin.fieldsWithIndirectStructVM = appendDistinct(field.origin.fieldsWithIndirectStructVM, field)
   367  					break F2
   368  				default:
   369  					break F2
   370  				}
   371  			}
   372  			if checkMap {
   373  				tt = t.Key()
   374  				checkMap = false
   375  				goto F2
   376  			}
   377  		case reflect.Struct:
   378  			s, err := vm.registerStructLocked(t)
   379  			if err != nil {
   380  				return err
   381  			}
   382  			if len(s.exprSelectorList) > 0 ||
   383  				len(s.ifaceTagExprGetters) > 0 ||
   384  				len(s.fieldsWithIndirectStructVM) > 0 {
   385  				if i == 0 {
   386  					field.mapOrSliceElemStructVM = s
   387  				} else {
   388  					field.mapKeyStructVM = s
   389  				}
   390  				field.origin.fieldsWithIndirectStructVM = appendDistinct(field.origin.fieldsWithIndirectStructVM, field)
   391  			}
   392  		}
   393  	}
   394  	return nil
   395  }
   396  
   397  func appendDistinct(a []*fieldVM, i *fieldVM) []*fieldVM {
   398  	has := false
   399  	for _, e := range a {
   400  		if e == i {
   401  			has = true
   402  			break
   403  		}
   404  	}
   405  	if !has {
   406  		return append(a, i)
   407  	}
   408  	return a
   409  }
   410  
   411  func (vm *VM) newStructVM() *structVM {
   412  	return &structVM{
   413  		vm:                         vm,
   414  		fields:                     make(map[string]*fieldVM, 32),
   415  		fieldSelectorList:          make([]string, 0, 32),
   416  		fieldsWithIndirectStructVM: make([]*fieldVM, 0, 32),
   417  		exprs:                      make(map[string]*Expr, 64),
   418  		exprSelectorList:           make([]string, 0, 64),
   419  	}
   420  }
   421  
   422  func (s *structVM) newFieldVM(structField reflect.StructField) (*fieldVM, bool, error) {
   423  	var tag = structField.Tag.Get(s.vm.tagName)
   424  	if tag == tagOmit {
   425  		return nil, false, nil
   426  	}
   427  	f := &fieldVM{
   428  		structField:   structField,
   429  		exprs:         make(map[string]*Expr, 8),
   430  		origin:        s,
   431  		fieldSelector: structField.Name,
   432  	}
   433  	err := f.parseExprs(tag)
   434  	if err != nil {
   435  		return nil, false, err
   436  	}
   437  	s.fields[f.fieldSelector] = f
   438  	s.fieldSelectorList = append(s.fieldSelectorList, f.fieldSelector)
   439  
   440  	var t = structField.Type
   441  	var ptrDeep int
   442  	for t.Kind() == reflect.Ptr {
   443  		t = t.Elem()
   444  		ptrDeep++
   445  	}
   446  	f.ptrDeep = ptrDeep
   447  
   448  	var offset = structField.Offset
   449  	f.getPtr = func(ptr unsafe.Pointer) unsafe.Pointer {
   450  		if ptr == nil {
   451  			return nil
   452  		}
   453  		return unsafe.Pointer(uintptr(ptr) + offset)
   454  	}
   455  
   456  	f.elemType = t
   457  	f.elemKind = t.Kind()
   458  	f.reflectValueGetter = func(ptr unsafe.Pointer, initZero bool) reflect.Value {
   459  		v := f.packRawFrom(ptr)
   460  		if initZero {
   461  			f.ensureInit(v)
   462  		}
   463  		return v
   464  	}
   465  
   466  	return f, true, nil
   467  }
   468  
   469  func (f *fieldVM) ensureInit(v reflect.Value) {
   470  	if safeIsNil(v) && v.CanSet() {
   471  		newField := reflect.New(f.elemType).Elem()
   472  		for i := 0; i < f.ptrDeep; i++ {
   473  			if newField.CanAddr() {
   474  				newField = newField.Addr()
   475  			} else {
   476  				newField2 := reflect.New(newField.Type())
   477  				newField2.Elem().Set(newField)
   478  				newField = newField2
   479  			}
   480  		}
   481  		v.Set(newField)
   482  	}
   483  }
   484  
   485  func (s *structVM) mergeSubStructVM(field *fieldVM, sub *structVM) {
   486  	field.origin = sub
   487  	fieldsWithIndirectStructVM := make(map[*fieldVM]struct{}, len(sub.fieldsWithIndirectStructVM))
   488  	for _, subField := range sub.fieldsWithIndirectStructVM {
   489  		fieldsWithIndirectStructVM[subField] = struct{}{}
   490  	}
   491  	for _, k := range sub.fieldSelectorList {
   492  		v := sub.fields[k]
   493  		f := s.newChildField(field, v, true)
   494  		if _, ok := fieldsWithIndirectStructVM[v]; ok {
   495  			s.fieldsWithIndirectStructVM = append(s.fieldsWithIndirectStructVM, f)
   496  			// TODO: maybe needed?
   497  			// delete(fieldsWithIndirectStructVM, v)
   498  		}
   499  	}
   500  	// TODO: maybe needed?
   501  	// for v := range fieldsWithIndirectStructVM {
   502  	// 	f := s.newChildField(field, v, false)
   503  	// 	s.fieldsWithIndirectStructVM = append(s.fieldsWithIndirectStructVM, f)
   504  	// }
   505  
   506  	for _, _subFn := range sub.ifaceTagExprGetters {
   507  		subFn := _subFn
   508  		s.ifaceTagExprGetters = append(s.ifaceTagExprGetters, func(ptr unsafe.Pointer, pathPrefix string, fn func(*TagExpr, error) error) error {
   509  			ptr = field.getElemPtr(ptr)
   510  			if ptr == nil {
   511  				return nil
   512  			}
   513  			var path string
   514  			if pathPrefix == "" {
   515  				path = field.fieldSelector
   516  			} else {
   517  				path = pathPrefix + FieldSeparator + field.fieldSelector
   518  			}
   519  			return subFn(ptr, path, fn)
   520  		})
   521  	}
   522  }
   523  
   524  func (s *structVM) newChildField(parent *fieldVM, child *fieldVM, toBind bool) *fieldVM {
   525  	f := &fieldVM{
   526  		structField:            child.structField,
   527  		exprs:                  make(map[string]*Expr, len(child.exprs)),
   528  		ptrDeep:                child.ptrDeep,
   529  		elemType:               child.elemType,
   530  		elemKind:               child.elemKind,
   531  		origin:                 child.origin,
   532  		mapKeyStructVM:         child.mapKeyStructVM,
   533  		mapOrSliceElemStructVM: child.mapOrSliceElemStructVM,
   534  		mapOrSliceIfaceKinds:   child.mapOrSliceIfaceKinds,
   535  		fieldSelector:          parent.fieldSelector + FieldSeparator + child.fieldSelector,
   536  	}
   537  	if parent.tagOp != tagOmit {
   538  		f.tagOp = child.tagOp
   539  	} else {
   540  		f.tagOp = parent.tagOp
   541  	}
   542  	f.getPtr = func(ptr unsafe.Pointer) unsafe.Pointer {
   543  		ptr = parent.getElemPtr(ptr)
   544  		if ptr == nil {
   545  			return nil
   546  		}
   547  		return child.getPtr(ptr)
   548  	}
   549  	if child.valueGetter != nil {
   550  		if parent.ptrDeep == 0 {
   551  			f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   552  				return child.valueGetter(parent.getPtr(ptr))
   553  			}
   554  			f.reflectValueGetter = func(ptr unsafe.Pointer, initZero bool) reflect.Value {
   555  				return child.reflectValueGetter(parent.getPtr(ptr), initZero)
   556  			}
   557  		} else {
   558  			f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   559  				newField := reflect.NewAt(parent.structField.Type, parent.getPtr(ptr))
   560  				for i := 0; i < parent.ptrDeep; i++ {
   561  					newField = newField.Elem()
   562  				}
   563  				if newField.IsNil() {
   564  					return nil
   565  				}
   566  				return child.valueGetter(unsafe.Pointer(newField.Pointer()))
   567  			}
   568  			f.reflectValueGetter = func(ptr unsafe.Pointer, initZero bool) reflect.Value {
   569  				newField := reflect.NewAt(parent.structField.Type, parent.getPtr(ptr))
   570  				if initZero {
   571  					parent.ensureInit(newField.Elem())
   572  				}
   573  				for i := 0; i < parent.ptrDeep; i++ {
   574  					newField = newField.Elem()
   575  				}
   576  				if (newField == reflect.Value{}) || (!initZero && newField.IsNil()) {
   577  					return reflect.Value{}
   578  				}
   579  				return child.reflectValueGetter(unsafe.Pointer(newField.Pointer()), initZero)
   580  			}
   581  		}
   582  	}
   583  
   584  	if toBind {
   585  		s.fields[f.fieldSelector] = f
   586  		s.fieldSelectorList = append(s.fieldSelectorList, f.fieldSelector)
   587  		if parent.tagOp != tagOmit {
   588  			for k, v := range child.exprs {
   589  				selector := parent.fieldSelector + FieldSeparator + k
   590  				f.exprs[selector] = v
   591  				s.exprs[selector] = v
   592  				s.exprSelectorList = append(s.exprSelectorList, selector)
   593  			}
   594  		}
   595  	}
   596  	return f
   597  }
   598  
   599  func (f *fieldVM) getElemPtr(ptr unsafe.Pointer) unsafe.Pointer {
   600  	ptr = f.getPtr(ptr)
   601  	for i := f.ptrDeep; ptr != nil && i > 0; i-- {
   602  		ptr = ptrElem(ptr)
   603  	}
   604  	return ptr
   605  }
   606  
   607  func (f *fieldVM) packRawFrom(ptr unsafe.Pointer) reflect.Value {
   608  	return reflect.NewAt(f.structField.Type, f.getPtr(ptr)).Elem()
   609  }
   610  
   611  func (f *fieldVM) packElemFrom(ptr unsafe.Pointer) reflect.Value {
   612  	return reflect.NewAt(f.elemType, f.getElemPtr(ptr)).Elem()
   613  }
   614  
   615  func (s *structVM) setIfaceTagExprGetter(f *fieldVM) {
   616  	if f.tagOp == tagOmit {
   617  		return
   618  	}
   619  	s.ifaceTagExprGetters = append(s.ifaceTagExprGetters, func(ptr unsafe.Pointer, pathPrefix string, fn func(*TagExpr, error) error) error {
   620  		v := f.packElemFrom(ptr)
   621  		if !v.IsValid() || v.IsNil() {
   622  			return nil
   623  		}
   624  		var path string
   625  		if pathPrefix == "" {
   626  			path = f.fieldSelector
   627  		} else {
   628  			path = pathPrefix + FieldSeparator + f.fieldSelector
   629  		}
   630  		return s.vm.subRunAll(f.tagOp == tagOmitNil, path, v, fn)
   631  	})
   632  }
   633  
   634  func (f *fieldVM) setFloatGetter() {
   635  	if f.ptrDeep == 0 {
   636  		f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   637  			ptr = f.getPtr(ptr)
   638  			if ptr == nil {
   639  				return nil
   640  			}
   641  			return getFloat64(f.elemKind, ptr)
   642  		}
   643  	} else {
   644  		f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   645  			v := f.packElemFrom(ptr)
   646  			if v.CanAddr() {
   647  				return getFloat64(f.elemKind, unsafe.Pointer(v.UnsafeAddr()))
   648  			}
   649  			return nil
   650  		}
   651  	}
   652  }
   653  
   654  func (f *fieldVM) setBoolGetter() {
   655  	if f.ptrDeep == 0 {
   656  		f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   657  			ptr = f.getPtr(ptr)
   658  			if ptr == nil {
   659  				return nil
   660  			}
   661  			return *(*bool)(ptr)
   662  		}
   663  	} else {
   664  		f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   665  			v := f.packElemFrom(ptr)
   666  			if v.IsValid() {
   667  				return v.Bool()
   668  			}
   669  			return nil
   670  		}
   671  	}
   672  }
   673  
   674  func (f *fieldVM) setStringGetter() {
   675  	if f.ptrDeep == 0 {
   676  		f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   677  			ptr = f.getPtr(ptr)
   678  			if ptr == nil {
   679  				return nil
   680  			}
   681  			return *(*string)(ptr)
   682  		}
   683  	} else {
   684  		f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   685  			v := f.packElemFrom(ptr)
   686  			if v.IsValid() {
   687  				return v.String()
   688  			}
   689  			return nil
   690  		}
   691  	}
   692  }
   693  
   694  func (f *fieldVM) setLengthGetter() {
   695  	f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   696  		v := f.packElemFrom(ptr)
   697  		if v.IsValid() {
   698  			return v.Interface()
   699  		}
   700  		return nil
   701  	}
   702  }
   703  
   704  func (f *fieldVM) setUnsupportGetter() {
   705  	f.valueGetter = func(ptr unsafe.Pointer) interface{} {
   706  		raw := f.packRawFrom(ptr)
   707  		if safeIsNil(raw) {
   708  			return nil
   709  		}
   710  		v := raw
   711  		for i := 0; i < f.ptrDeep; i++ {
   712  			v = v.Elem()
   713  		}
   714  		for v.Kind() == reflect.Interface {
   715  			v = v.Elem()
   716  		}
   717  		return anyValueGetter(raw, v)
   718  	}
   719  }
   720  
   721  func (vm *VM) getStructType(t reflect.Type) (reflect.Type, error) {
   722  	structType := t
   723  	for structType.Kind() == reflect.Ptr {
   724  		structType = structType.Elem()
   725  	}
   726  	if structType.Kind() != reflect.Struct {
   727  		return nil, fmt.Errorf("unsupport type: %s", t.String())
   728  	}
   729  	return structType, nil
   730  }
   731  
   732  func (s *structVM) newTagExpr(ptr unsafe.Pointer, path string) *TagExpr {
   733  	te := &TagExpr{
   734  		s:    s,
   735  		ptr:  ptr,
   736  		sub:  make(map[string]*TagExpr, 8),
   737  		path: strings.TrimPrefix(path, "."),
   738  	}
   739  	return te
   740  }
   741  
   742  // TagExpr struct tag expression evaluator
   743  type TagExpr struct {
   744  	s    *structVM
   745  	ptr  unsafe.Pointer
   746  	sub  map[string]*TagExpr
   747  	path string
   748  }
   749  
   750  // EvalFloat evaluates the value of the struct tag expression by the selector expression.
   751  // NOTE:
   752  //
   753  //	If the expression value type is not float64, return 0.
   754  func (t *TagExpr) EvalFloat(exprSelector string) float64 {
   755  	r, _ := t.Eval(exprSelector).(float64)
   756  	return r
   757  }
   758  
   759  // EvalString evaluates the value of the struct tag expression by the selector expression.
   760  // NOTE:
   761  //
   762  //	If the expression value type is not string, return "".
   763  func (t *TagExpr) EvalString(exprSelector string) string {
   764  	r, _ := t.Eval(exprSelector).(string)
   765  	return r
   766  }
   767  
   768  // EvalBool evaluates the value of the struct tag expression by the selector expression.
   769  // NOTE:
   770  //
   771  //	If the expression value is not 0, '' or nil, return true.
   772  func (t *TagExpr) EvalBool(exprSelector string) bool {
   773  	return FakeBool(t.Eval(exprSelector))
   774  }
   775  
   776  // FakeBool fakes any type as a boolean.
   777  func FakeBool(v interface{}) bool {
   778  	switch r := v.(type) {
   779  	case float64:
   780  		return r != 0
   781  	case float32:
   782  		return r != 0
   783  	case int:
   784  		return r != 0
   785  	case int8:
   786  		return r != 0
   787  	case int16:
   788  		return r != 0
   789  	case int32:
   790  		return r != 0
   791  	case int64:
   792  		return r != 0
   793  	case uint:
   794  		return r != 0
   795  	case uint8:
   796  		return r != 0
   797  	case uint16:
   798  		return r != 0
   799  	case uint32:
   800  		return r != 0
   801  	case uint64:
   802  		return r != 0
   803  	case string:
   804  		return r != ""
   805  	case bool:
   806  		return r
   807  	case nil, error:
   808  		return false
   809  	case []interface{}:
   810  		var bol = true
   811  		for _, v := range r {
   812  			bol = bol && FakeBool(v)
   813  		}
   814  		return bol
   815  	default:
   816  		vv := ameda.DereferenceValue(reflect.ValueOf(v))
   817  		if vv.IsValid() || vv.IsZero() {
   818  			return false
   819  		}
   820  		return true
   821  	}
   822  }
   823  
   824  // Field returns the field handler specified by the selector.
   825  func (t *TagExpr) Field(fieldSelector string) (fh *FieldHandler, found bool) {
   826  	f, ok := t.s.fields[fieldSelector]
   827  	if !ok {
   828  		return nil, false
   829  	}
   830  	return newFieldHandler(t, fieldSelector, f), true
   831  }
   832  
   833  // RangeFields loop through each field.
   834  // When fn returns false, interrupt traversal and return false.
   835  func (t *TagExpr) RangeFields(fn func(*FieldHandler) bool) bool {
   836  	if list := t.s.fieldSelectorList; len(list) > 0 {
   837  		fields := t.s.fields
   838  		for _, fieldSelector := range list {
   839  			if !fn(newFieldHandler(t, fieldSelector, fields[fieldSelector])) {
   840  				return false
   841  			}
   842  		}
   843  	}
   844  	return true
   845  }
   846  
   847  // Eval evaluates the value of the struct tag expression by the selector expression.
   848  // NOTE:
   849  //
   850  //	format: fieldName, fieldName.exprName, fieldName1.fieldName2.exprName1
   851  //	result types: float64, string, bool, nil
   852  func (t *TagExpr) Eval(exprSelector string) interface{} {
   853  	expr, ok := t.s.exprs[exprSelector]
   854  	if !ok {
   855  		// Compatible with single mode or the expression with the name @
   856  		if strings.HasSuffix(exprSelector, ExprNameSeparator) {
   857  			exprSelector = exprSelector[:len(exprSelector)-1]
   858  			if strings.HasSuffix(exprSelector, ExprNameSeparator) {
   859  				exprSelector = exprSelector[:len(exprSelector)-1]
   860  			}
   861  			expr, ok = t.s.exprs[exprSelector]
   862  		}
   863  		if !ok {
   864  			return nil
   865  		}
   866  	}
   867  	dir, base := splitFieldSelector(exprSelector)
   868  	targetTagExpr, err := t.checkout(dir)
   869  	if err != nil {
   870  		return nil
   871  	}
   872  	return expr.run(base, targetTagExpr)
   873  }
   874  
   875  // Range loop through each tag expression.
   876  // When fn returns false, interrupt traversal and return false.
   877  // NOTE:
   878  //
   879  //	eval result types: float64, string, bool, nil
   880  func (t *TagExpr) Range(fn func(*ExprHandler) error) error {
   881  	var err error
   882  	if list := t.s.exprSelectorList; len(list) > 0 {
   883  		for _, es := range list {
   884  			dir, base := splitFieldSelector(es)
   885  			targetTagExpr, err := t.checkout(dir)
   886  			if err != nil {
   887  				continue
   888  			}
   889  			err = fn(newExprHandler(t, targetTagExpr, base, es))
   890  			if err != nil {
   891  				return err
   892  			}
   893  		}
   894  	}
   895  
   896  	ptr := t.ptr
   897  
   898  	if list := t.s.fieldsWithIndirectStructVM; len(list) > 0 {
   899  		for _, f := range list {
   900  			v := f.packElemFrom(ptr)
   901  			if !v.IsValid() {
   902  				continue
   903  			}
   904  			omitNil := f.tagOp == tagOmitNil
   905  			mapKeyStructVM := f.mapKeyStructVM
   906  			mapOrSliceElemStructVM := f.mapOrSliceElemStructVM
   907  			valueIface := f.mapOrSliceIfaceKinds[0]
   908  			keyIface := f.mapOrSliceIfaceKinds[1]
   909  
   910  			if f.elemKind == reflect.Map &&
   911  				(mapOrSliceElemStructVM != nil || mapKeyStructVM != nil || valueIface || keyIface) {
   912  				keyPath := f.fieldSelector + "{k}"
   913  				for _, key := range v.MapKeys() {
   914  					if mapKeyStructVM != nil {
   915  						p := unsafe.Pointer(ameda.ValueFrom(derefValue(key)).Pointer())
   916  						if omitNil && p == nil {
   917  							continue
   918  						}
   919  						err = mapKeyStructVM.newTagExpr(p, keyPath).Range(fn)
   920  						if err != nil {
   921  							return err
   922  						}
   923  					} else if keyIface {
   924  						err = t.subRange(omitNil, keyPath, key, fn)
   925  						if err != nil {
   926  							return err
   927  						}
   928  					}
   929  					if mapOrSliceElemStructVM != nil {
   930  						p := unsafe.Pointer(ameda.ValueFrom(derefValue(v.MapIndex(key))).Pointer())
   931  						if omitNil && p == nil {
   932  							continue
   933  						}
   934  						err = mapOrSliceElemStructVM.newTagExpr(p, f.fieldSelector+"{v for k="+key.String()+"}").Range(fn)
   935  						if err != nil {
   936  							return err
   937  						}
   938  					} else if valueIface {
   939  						err = t.subRange(omitNil, f.fieldSelector+"{v for k="+key.String()+"}", v.MapIndex(key), fn)
   940  						if err != nil {
   941  							return err
   942  						}
   943  					}
   944  				}
   945  
   946  			} else if mapOrSliceElemStructVM != nil || valueIface {
   947  				// slice or array
   948  				for i := v.Len() - 1; i >= 0; i-- {
   949  					if mapOrSliceElemStructVM != nil {
   950  						p := unsafe.Pointer(ameda.ValueFrom(derefValue(v.Index(i))).Pointer())
   951  						if omitNil && p == nil {
   952  							continue
   953  						}
   954  						err = mapOrSliceElemStructVM.newTagExpr(p, f.fieldSelector+"["+strconv.Itoa(i)+"]").Range(fn)
   955  						if err != nil {
   956  							return err
   957  						}
   958  					} else if valueIface {
   959  						err = t.subRange(omitNil, f.fieldSelector+"["+strconv.Itoa(i)+"]", v.Index(i), fn)
   960  						if err != nil {
   961  							return err
   962  						}
   963  					}
   964  				}
   965  			}
   966  		}
   967  	}
   968  
   969  	if list := t.s.ifaceTagExprGetters; len(list) > 0 {
   970  		for _, getter := range list {
   971  			err = getter(ptr, "", func(te *TagExpr, err error) error {
   972  				if err != nil {
   973  					return err
   974  				}
   975  				return te.Range(fn)
   976  			})
   977  			if err != nil {
   978  				return err
   979  			}
   980  		}
   981  	}
   982  	return nil
   983  }
   984  
   985  func (t *TagExpr) subRange(omitNil bool, path string, value reflect.Value, fn func(*ExprHandler) error) error {
   986  	return t.s.vm.subRunAll(omitNil, path, value, func(te *TagExpr, err error) error {
   987  		if err != nil {
   988  			return err
   989  		}
   990  		return te.Range(fn)
   991  	})
   992  }
   993  
   994  var (
   995  	errFieldSelector = errors.New("field selector does not exist")
   996  	errOmitNil       = errors.New("omit nil")
   997  )
   998  
   999  func (t *TagExpr) checkout(fs string) (*TagExpr, error) {
  1000  	if fs == "" {
  1001  		return t, nil
  1002  	}
  1003  	subTagExpr, ok := t.sub[fs]
  1004  	if ok {
  1005  		if subTagExpr == nil {
  1006  			return nil, errOmitNil
  1007  		}
  1008  		return subTagExpr, nil
  1009  	}
  1010  	f, ok := t.s.fields[fs]
  1011  	if !ok {
  1012  		return nil, errFieldSelector
  1013  	}
  1014  	ptr := f.getElemPtr(t.ptr)
  1015  	if f.tagOp == tagOmitNil && ptr == nil {
  1016  		t.sub[fs] = nil
  1017  		return nil, errOmitNil
  1018  	}
  1019  	subTagExpr = f.origin.newTagExpr(ptr, t.path)
  1020  	t.sub[fs] = subTagExpr
  1021  	return subTagExpr, nil
  1022  }
  1023  
  1024  func (t *TagExpr) getValue(fieldSelector string, subFields []interface{}) (v interface{}) {
  1025  	f := t.s.fields[fieldSelector]
  1026  	if f == nil {
  1027  		return nil
  1028  	}
  1029  	if f.valueGetter == nil {
  1030  		return nil
  1031  	}
  1032  	v = f.valueGetter(t.ptr)
  1033  	if v == nil {
  1034  		return nil
  1035  	}
  1036  	if len(subFields) == 0 {
  1037  		return v
  1038  	}
  1039  	vv := reflect.ValueOf(v)
  1040  	var kind reflect.Kind
  1041  	for i, k := range subFields {
  1042  		kind = vv.Kind()
  1043  		for kind == reflect.Ptr || kind == reflect.Interface {
  1044  			vv = vv.Elem()
  1045  			kind = vv.Kind()
  1046  		}
  1047  		switch kind {
  1048  		case reflect.Slice, reflect.Array, reflect.String:
  1049  			if float, ok := k.(float64); ok {
  1050  				idx := int(float)
  1051  				if idx >= vv.Len() {
  1052  					return nil
  1053  				}
  1054  				vv = vv.Index(idx)
  1055  			} else {
  1056  				return nil
  1057  			}
  1058  		case reflect.Map:
  1059  			k := safeConvert(reflect.ValueOf(k), vv.Type().Key())
  1060  			if !k.IsValid() {
  1061  				return nil
  1062  			}
  1063  			vv = vv.MapIndex(k)
  1064  		case reflect.Struct:
  1065  			if float, ok := k.(float64); ok {
  1066  				idx := int(float)
  1067  				if idx < 0 || idx >= vv.NumField() {
  1068  					return nil
  1069  				}
  1070  				vv = vv.Field(idx)
  1071  			} else if str, ok := k.(string); ok {
  1072  				vv = vv.FieldByName(str)
  1073  			} else {
  1074  				return nil
  1075  			}
  1076  		default:
  1077  			if i < len(subFields)-1 {
  1078  				return nil
  1079  			}
  1080  		}
  1081  		if !vv.IsValid() {
  1082  			return nil
  1083  		}
  1084  	}
  1085  	raw := vv
  1086  	for vv.Kind() == reflect.Ptr || vv.Kind() == reflect.Interface {
  1087  		vv = vv.Elem()
  1088  	}
  1089  	return anyValueGetter(raw, vv)
  1090  }
  1091  
  1092  func safeConvert(v reflect.Value, t reflect.Type) reflect.Value {
  1093  	defer func() { recover() }()
  1094  	return v.Convert(t)
  1095  }
  1096  
  1097  var float64Type = reflect.TypeOf(float64(0))
  1098  
  1099  func splitFieldSelector(selector string) (dir, base string) {
  1100  	idx := strings.LastIndex(selector, ExprNameSeparator)
  1101  	if idx != -1 {
  1102  		selector = selector[:idx]
  1103  	}
  1104  	idx = strings.LastIndex(selector, FieldSeparator)
  1105  	if idx != -1 {
  1106  		return selector[:idx], selector[idx+1:]
  1107  	}
  1108  	return "", selector
  1109  }
  1110  
  1111  func getFloat64(kind reflect.Kind, p unsafe.Pointer) interface{} {
  1112  	switch kind {
  1113  	case reflect.Float32:
  1114  		return float64(*(*float32)(p))
  1115  	case reflect.Float64:
  1116  		return *(*float64)(p)
  1117  	case reflect.Int:
  1118  		return float64(*(*int)(p))
  1119  	case reflect.Int8:
  1120  		return float64(*(*int8)(p))
  1121  	case reflect.Int16:
  1122  		return float64(*(*int16)(p))
  1123  	case reflect.Int32:
  1124  		return float64(*(*int32)(p))
  1125  	case reflect.Int64:
  1126  		return float64(*(*int64)(p))
  1127  	case reflect.Uint:
  1128  		return float64(*(*uint)(p))
  1129  	case reflect.Uint8:
  1130  		return float64(*(*uint8)(p))
  1131  	case reflect.Uint16:
  1132  		return float64(*(*uint16)(p))
  1133  	case reflect.Uint32:
  1134  		return float64(*(*uint32)(p))
  1135  	case reflect.Uint64:
  1136  		return float64(*(*uint64)(p))
  1137  	case reflect.Uintptr:
  1138  		return float64(*(*uintptr)(p))
  1139  	}
  1140  	return nil
  1141  }
  1142  
  1143  func anyValueGetter(raw, elem reflect.Value) interface{} {
  1144  	if !elem.IsValid() || !raw.IsValid() {
  1145  		return nil
  1146  	}
  1147  	kind := elem.Kind()
  1148  	switch kind {
  1149  	case reflect.Float32, reflect.Float64,
  1150  		reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  1151  		reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1152  		if elem.CanAddr() {
  1153  			return getFloat64(kind, unsafe.Pointer(elem.UnsafeAddr()))
  1154  		}
  1155  		switch kind {
  1156  		case reflect.Float32, reflect.Float64:
  1157  			return elem.Float()
  1158  		case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1159  			return float64(elem.Int())
  1160  		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1161  			return float64(elem.Uint())
  1162  		}
  1163  	case reflect.String:
  1164  		return elem.String()
  1165  	case reflect.Bool:
  1166  		return elem.Bool()
  1167  	}
  1168  	if raw.CanInterface() {
  1169  		return raw.Interface()
  1170  	}
  1171  	return nil
  1172  }
  1173  
  1174  func safeIsNil(v reflect.Value) bool {
  1175  	if !v.IsValid() {
  1176  		return true
  1177  	}
  1178  	switch v.Kind() {
  1179  	case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr,
  1180  		reflect.UnsafePointer, reflect.Interface, reflect.Slice:
  1181  		return v.IsNil()
  1182  	}
  1183  	return false
  1184  }
  1185  
  1186  //go:nocheckptr
  1187  func ptrElem(ptr unsafe.Pointer) unsafe.Pointer {
  1188  	return unsafe.Pointer(*(*uintptr)(ptr))
  1189  }
  1190  
  1191  func derefType(t reflect.Type) reflect.Type {
  1192  	for t.Kind() == reflect.Ptr {
  1193  		t = t.Elem()
  1194  	}
  1195  	return t
  1196  }
  1197  
  1198  func derefValue(v reflect.Value) reflect.Value {
  1199  	for v.Kind() == reflect.Ptr {
  1200  		v = v.Elem()
  1201  	}
  1202  	return v
  1203  }