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