@@ -50,7 +50,7 @@ type fieldVM struct {
50
50
elemType reflect.Type
51
51
elemKind reflect.Kind
52
52
zeroValue interface {}
53
- host * structVM
53
+ origin * structVM
54
54
valueGetter func (uintptr ) interface {}
55
55
reflectValueGetter func (uintptr ) reflect.Value
56
56
}
@@ -157,6 +157,7 @@ func (vm *VM) registerStructLocked(structType reflect.Type) (*structVM, error) {
157
157
if err != nil {
158
158
return nil , err
159
159
}
160
+ field .origin = sub
160
161
s .copySubFields (field , sub )
161
162
case reflect .Interface :
162
163
s .setIfaceTagExprGetter (field )
@@ -188,7 +189,7 @@ func (vm *VM) newStructVM() *structVM {
188
189
func (s * structVM ) newFieldVM (structField reflect.StructField ) (* fieldVM , error ) {
189
190
f := & fieldVM {
190
191
StructField : structField ,
191
- host : s ,
192
+ origin : s ,
192
193
}
193
194
err := f .parseExprs (structField .Tag .Get (s .vm .tagName ))
194
195
if err != nil {
@@ -219,7 +220,7 @@ func (s *structVM) copySubFields(field *fieldVM, sub *structVM) {
219
220
reflectValueGetter := v .reflectValueGetter
220
221
f := & fieldVM {
221
222
StructField : v .StructField ,
222
- host : v . host ,
223
+ origin : v . origin ,
223
224
}
224
225
if valueGetter != nil {
225
226
if ptrDeep == 0 {
@@ -262,16 +263,20 @@ func (s *structVM) copySubFields(field *fieldVM, sub *structVM) {
262
263
}
263
264
}
264
265
266
+ func (f * fieldVM ) elemPtr (ptr uintptr ) uintptr {
267
+ ptr = ptr + f .Offset
268
+ for i := f .ptrDeep ; i > 0 ; i -- {
269
+ ptr = uintptrElem (ptr )
270
+ }
271
+ return ptr
272
+ }
273
+
265
274
func (f * fieldVM ) packRawFrom (ptr uintptr ) reflect.Value {
266
275
return reflect .NewAt (f .Type , unsafe .Pointer (ptr + f .Offset )).Elem ()
267
276
}
268
277
269
278
func (f * fieldVM ) packElemFrom (ptr uintptr ) reflect.Value {
270
- v := f .packRawFrom (ptr )
271
- for i := 0 ; i < f .ptrDeep ; i ++ {
272
- v = v .Elem ()
273
- }
274
- return v
279
+ return reflect .NewAt (f .elemType , unsafe .Pointer (f .elemPtr (ptr ))).Elem ()
275
280
}
276
281
277
282
func (s * structVM ) setIfaceTagExprGetter (f * fieldVM ) {
@@ -400,8 +405,8 @@ func (f *fieldVM) parseExprs(tag string) error {
400
405
return err
401
406
}
402
407
selector := f .Name
403
- f .host .exprs [selector ] = expr
404
- f .host .selectorList = append (f .host .selectorList , selector )
408
+ f .origin .exprs [selector ] = expr
409
+ f .origin .selectorList = append (f .origin .selectorList , selector )
405
410
return nil
406
411
}
407
412
var subtag * string
@@ -421,14 +426,14 @@ func (f *fieldVM) parseExprs(tag string) error {
421
426
default :
422
427
selector = f .Name + "@" + selector
423
428
}
424
- if _ , had := f .host .exprs [selector ]; had {
429
+ if _ , had := f .origin .exprs [selector ]; had {
425
430
return fmt .Errorf ("duplicate expression name: %s" , selector )
426
431
}
427
432
exprStr = strings .TrimSpace ((* subtag )[idx + 1 :])
428
433
if exprStr != "" {
429
434
if expr , err := parseExpr (exprStr ); err == nil {
430
- f .host .exprs [selector ] = expr
431
- f .host .selectorList = append (f .host .selectorList , selector )
435
+ f .origin .exprs [selector ] = expr
436
+ f .origin .selectorList = append (f .origin .selectorList , selector )
432
437
} else {
433
438
return err
434
439
}
@@ -459,6 +464,7 @@ func (s *structVM) newTagExpr(ptr uintptr) *TagExpr {
459
464
te := & TagExpr {
460
465
s : s ,
461
466
ptr : ptr ,
467
+ sub : make (map [string ]* TagExpr , 8 ),
462
468
}
463
469
return te
464
470
}
@@ -467,6 +473,7 @@ func (s *structVM) newTagExpr(ptr uintptr) *TagExpr {
467
473
type TagExpr struct {
468
474
s * structVM
469
475
ptr uintptr
476
+ sub map [string ]* TagExpr
470
477
}
471
478
472
479
// EvalFloat evaluate the value of the struct tag expression by the selector expression.
@@ -527,7 +534,12 @@ func (t *TagExpr) Eval(exprSelector string) interface{} {
527
534
return nil
528
535
}
529
536
}
530
- return expr .run (getFieldSelector (exprSelector ), t )
537
+ dir , base := splitFieldSelector (exprSelector )
538
+ targetTagExpr , err := t .checkout (dir )
539
+ if err != nil {
540
+ return nil
541
+ }
542
+ return expr .run (base , targetTagExpr )
531
543
}
532
544
533
545
// Range loop through each tag expression
@@ -538,7 +550,12 @@ func (t *TagExpr) Range(fn func(exprSelector string, eval func() interface{}) bo
538
550
exprs := t .s .exprs
539
551
for _ , exprSelector := range list {
540
552
if ! fn (exprSelector , func () interface {} {
541
- return exprs [exprSelector ].run (getFieldSelector (exprSelector ), t )
553
+ dir , base := splitFieldSelector (exprSelector )
554
+ targetTagExpr , err := t .checkout (dir )
555
+ if err != nil {
556
+ return nil
557
+ }
558
+ return exprs [exprSelector ].run (base , targetTagExpr )
542
559
}) {
543
560
return
544
561
}
@@ -574,9 +591,28 @@ func (t *TagExpr) Field(fieldSelector string) interface{} {
574
591
return nil
575
592
}
576
593
577
- func (t * TagExpr ) getValue (field string , subFields []interface {}) (v interface {}) {
578
- f , ok := t .s .fields [field ]
594
+ var errFieldSelector = errors .New ("field selector does not exist" )
595
+
596
+ func (t * TagExpr ) checkout (fs string ) (* TagExpr , error ) {
597
+ if fs == "" {
598
+ return t , nil
599
+ }
600
+ subTagExpr , ok := t .sub [fs ]
601
+ if ok {
602
+ return subTagExpr , nil
603
+ }
604
+ f , ok := t .s .fields [fs ]
579
605
if ! ok {
606
+ return nil , errFieldSelector
607
+ }
608
+ subTagExpr = f .origin .newTagExpr (f .elemPtr (t .ptr ))
609
+ t .sub [fs ] = subTagExpr
610
+ return subTagExpr , nil
611
+ }
612
+
613
+ func (t * TagExpr ) getValue (fieldSelector string , subFields []interface {}) (v interface {}) {
614
+ f := t .s .fields [fieldSelector ]
615
+ if f == nil {
580
616
return nil
581
617
}
582
618
if f .valueGetter == nil {
@@ -649,12 +685,16 @@ func safeConvert(v reflect.Value, t reflect.Type) reflect.Value {
649
685
650
686
var float64Type = reflect .TypeOf (float64 (0 ))
651
687
652
- func getFieldSelector (selector string ) string {
653
- idx := strings .Index (selector , "@" )
654
- if idx == - 1 {
655
- return selector
688
+ func splitFieldSelector (selector string ) (dir , base string ) {
689
+ idx := strings .LastIndex (selector , "@" )
690
+ if idx != - 1 {
691
+ selector = selector [:idx ]
692
+ }
693
+ idx = strings .LastIndex (selector , "." )
694
+ if idx != - 1 {
695
+ return selector [:idx ], selector [idx + 1 :]
656
696
}
657
- return selector [: idx ]
697
+ return "" , selector
658
698
}
659
699
660
700
func getFloat64 (kind reflect.Kind , ptr uintptr ) interface {} {
@@ -732,3 +772,7 @@ func safeIsNil(v reflect.Value) bool {
732
772
}
733
773
return false
734
774
}
775
+
776
+ func uintptrElem (ptr uintptr ) uintptr {
777
+ return * (* uintptr )(unsafe .Pointer (ptr ))
778
+ }
0 commit comments