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 }