Skip to content

Commit 2ee66b0

Browse files
committed
fix(tagexpr): Fix bug in nested interface
Change-Id: Ibe1ac91234e056b775150af532d02920125958fe
1 parent a383cfc commit 2ee66b0

File tree

2 files changed

+140
-155
lines changed

2 files changed

+140
-155
lines changed

tagexpr.go

+136-153
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ type structVM struct {
4343
fieldsWithIndirectStructVM []*fieldVM
4444
exprs map[string]*Expr
4545
exprSelectorList []string
46-
ifaceTagExprGetters []func(unsafe.Pointer) (te *TagExpr, ok bool)
46+
ifaceTagExprGetters []func(unsafe.Pointer, func(*TagExpr) bool) bool
4747
}
4848

4949
// fieldVM tag expression set of struct field
@@ -77,6 +77,14 @@ func New(tagName ...string) *VM {
7777
}
7878
}
7979

80+
// MustWarmUp is similar to WarmUp, but panic when error.
81+
func (vm *VM) MustWarmUp(structOrStructPtrOrReflect ...interface{}) {
82+
err := vm.WarmUp(structOrStructPtrOrReflect...)
83+
if err != nil {
84+
panic(err)
85+
}
86+
}
87+
8088
// WarmUp preheating some interpreters of the struct type in batches,
8189
// to improve the performance of the vm.Run.
8290
func (vm *VM) WarmUp(structOrStructPtrOrReflect ...interface{}) error {
@@ -101,12 +109,13 @@ func (vm *VM) WarmUp(structOrStructPtrOrReflect ...interface{}) error {
101109
return nil
102110
}
103111

104-
// MustWarmUp is similar to WarmUp, but panic when error.
105-
func (vm *VM) MustWarmUp(structOrStructPtrOrReflect ...interface{}) {
106-
err := vm.WarmUp(structOrStructPtrOrReflect...)
112+
// MustRun is similar to Run, but panic when error.
113+
func (vm *VM) MustRun(structOrStructPtrOrReflectValue interface{}) *TagExpr {
114+
te, err := vm.Run(structOrStructPtrOrReflectValue)
107115
if err != nil {
108116
panic(err)
109117
}
118+
return te
110119
}
111120

112121
// Run returns the tag expression handler of the @structOrStructPtrOrReflectValue.
@@ -150,13 +159,88 @@ func (vm *VM) Run(structOrStructPtrOrReflectValue interface{}) (*TagExpr, error)
150159
return s.newTagExpr(ptr), nil
151160
}
152161

153-
// MustRun is similar to Run, but panic when error.
154-
func (vm *VM) MustRun(structOrStructPtrOrReflectValue interface{}) *TagExpr {
155-
te, err := vm.Run(structOrStructPtrOrReflectValue)
156-
if err != nil {
157-
panic(err)
162+
func (vm *VM) subRunAll(omitNil bool, value reflect.Value, fn func(*TagExpr) bool) bool {
163+
rv := goutil.DereferenceIfaceValue(value)
164+
rt := goutil.DereferenceType(rv.Type())
165+
rv = goutil.DereferenceValue(rv)
166+
switch rt.Kind() {
167+
case reflect.Struct:
168+
if omitNil && !rv.IsValid() {
169+
return true
170+
}
171+
te, err := vm.subRun(rt, tpack.RuntimeTypeID(rt), unsafe.Pointer(tpack.From(rv).Pointer()))
172+
if err != nil {
173+
return true
174+
}
175+
return fn(te)
176+
177+
case reflect.Slice, reflect.Array:
178+
count := rv.Len()
179+
if count == 0 {
180+
return true
181+
}
182+
switch goutil.DereferenceType(rv.Type().Elem()).Kind() {
183+
case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
184+
for i := count - 1; i >= 0; i-- {
185+
if !vm.subRunAll(omitNil, rv.Index(i), fn) {
186+
return false
187+
}
188+
}
189+
default:
190+
return true
191+
}
192+
193+
case reflect.Map:
194+
if rv.Len() == 0 {
195+
return true
196+
}
197+
var canKey, canValue bool
198+
rt := rv.Type()
199+
switch goutil.DereferenceType(rt.Key()).Kind() {
200+
case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
201+
canKey = true
202+
}
203+
switch goutil.DereferenceType(rt.Elem()).Kind() {
204+
case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
205+
canValue = true
206+
}
207+
if !canKey && !canValue {
208+
return true
209+
}
210+
for _, key := range rv.MapKeys() {
211+
if canKey {
212+
if !vm.subRunAll(omitNil, key, fn) {
213+
return false
214+
}
215+
}
216+
if canValue {
217+
if !vm.subRunAll(omitNil, rv.MapIndex(key), fn) {
218+
return false
219+
}
220+
}
221+
}
158222
}
159-
return te
223+
return true
224+
}
225+
226+
func (vm *VM) subRun(t reflect.Type, tid int32, ptr unsafe.Pointer) (*TagExpr, error) {
227+
var err error
228+
vm.rw.RLock()
229+
s, ok := vm.structJar[tid]
230+
vm.rw.RUnlock()
231+
if !ok {
232+
vm.rw.Lock()
233+
s, ok = vm.structJar[tid]
234+
if !ok {
235+
s, err = vm.registerStructLocked(t)
236+
if err != nil {
237+
vm.rw.Unlock()
238+
return nil, err
239+
}
240+
}
241+
vm.rw.Unlock()
242+
}
243+
return s.newTagExpr(ptr), nil
160244
}
161245

162246
func (vm *VM) registerStructLocked(structType reflect.Type) (*structVM, error) {
@@ -313,6 +397,35 @@ func (f *fieldVM) ensureInit(v reflect.Value) {
313397
}
314398
}
315399

400+
func (s *structVM) mergeSubStructVM(field *fieldVM, sub *structVM) {
401+
field.origin = sub
402+
nameSpace := field.structField.Name
403+
fieldsWithIndirectStructVM := make(map[*fieldVM]struct{}, len(sub.fieldsWithIndirectStructVM))
404+
for _, subField := range sub.fieldsWithIndirectStructVM {
405+
fieldsWithIndirectStructVM[subField] = struct{}{}
406+
}
407+
for _, k := range sub.fieldSelectorList {
408+
v := sub.fields[k]
409+
f := s.newChildField(field, v)
410+
fieldSelector := nameSpace + FieldSeparator + k
411+
s.fields[fieldSelector] = f
412+
s.fieldSelectorList = append(s.fieldSelectorList, fieldSelector)
413+
if _, ok := fieldsWithIndirectStructVM[v]; ok {
414+
s.fieldsWithIndirectStructVM = append(s.fieldsWithIndirectStructVM, f)
415+
}
416+
}
417+
for _, _subFn := range sub.ifaceTagExprGetters {
418+
subFn := _subFn
419+
s.ifaceTagExprGetters = append(s.ifaceTagExprGetters, func(ptr unsafe.Pointer, fn func(*TagExpr) bool) bool {
420+
ptr = field.getElemPtr(ptr)
421+
if ptr == nil {
422+
return true
423+
}
424+
return subFn(ptr, fn)
425+
})
426+
}
427+
}
428+
316429
func (s *structVM) newChildField(parent *fieldVM, child *fieldVM) *fieldVM {
317430
f := &fieldVM{
318431
structField: child.structField,
@@ -324,8 +437,6 @@ func (s *structVM) newChildField(parent *fieldVM, child *fieldVM) *fieldVM {
324437
mapKeyStructVM: child.mapKeyStructVM,
325438
mapOrSliceElemStructVM: child.mapOrSliceElemStructVM,
326439
mapOrSliceIfaceKinds: child.mapOrSliceIfaceKinds,
327-
// valueGetter: child.valueGetter,
328-
// reflectValueGetter: child.reflectValueGetter,
329440
}
330441

331442
f.getPtr = func(ptr unsafe.Pointer) unsafe.Pointer {
@@ -387,26 +498,6 @@ func (s *structVM) newChildField(parent *fieldVM, child *fieldVM) *fieldVM {
387498
return f
388499
}
389500

390-
func (s *structVM) mergeSubStructVM(field *fieldVM, sub *structVM) {
391-
field.origin = sub
392-
nameSpace := field.structField.Name
393-
fieldsWithIndirectStructVM := make(map[*fieldVM]struct{}, len(sub.fieldsWithIndirectStructVM))
394-
for _, subField := range sub.fieldsWithIndirectStructVM {
395-
fieldsWithIndirectStructVM[subField] = struct{}{}
396-
}
397-
// sub.ifaceTagExprGetters
398-
for _, k := range sub.fieldSelectorList {
399-
v := sub.fields[k]
400-
f := s.newChildField(field, v)
401-
fieldSelector := nameSpace + FieldSeparator + k
402-
s.fields[fieldSelector] = f
403-
s.fieldSelectorList = append(s.fieldSelectorList, fieldSelector)
404-
if _, ok := fieldsWithIndirectStructVM[v]; ok {
405-
s.fieldsWithIndirectStructVM = append(s.fieldsWithIndirectStructVM, f)
406-
}
407-
}
408-
}
409-
410501
func (f *fieldVM) getElemPtr(ptr unsafe.Pointer) unsafe.Pointer {
411502
ptr = f.getPtr(ptr)
412503
for i := f.ptrDeep; ptr != nil && i > 0; i-- {
@@ -427,44 +518,15 @@ func (s *structVM) setIfaceTagExprGetter(f *fieldVM) {
427518
if f.tagOp == tagOmit {
428519
return
429520
}
430-
s.ifaceTagExprGetters = append(s.ifaceTagExprGetters, func(ptr unsafe.Pointer) (*TagExpr, bool) {
521+
s.ifaceTagExprGetters = append(s.ifaceTagExprGetters, func(ptr unsafe.Pointer, fn func(*TagExpr) bool) bool {
431522
v := f.packElemFrom(ptr)
432523
if !v.IsValid() || v.IsNil() {
433-
return nil, false
434-
}
435-
te, ok := s.vm.runFromValue(v)
436-
if !ok {
437-
return nil, false
524+
return true
438525
}
439-
return te, true
526+
return s.vm.subRunAll(f.tagOp == tagOmitNil, v, fn)
440527
})
441528
}
442529

443-
func (vm *VM) runFromValue(v reflect.Value) (*TagExpr, bool) {
444-
u := tpack.From(v).UnderlyingElem()
445-
if u.Kind() != reflect.Struct {
446-
return nil, false
447-
}
448-
tid := u.RuntimeTypeID()
449-
var err error
450-
vm.rw.RLock()
451-
s, ok := vm.structJar[tid]
452-
vm.rw.RUnlock()
453-
if !ok {
454-
vm.rw.Lock()
455-
s, ok = vm.structJar[tid]
456-
if !ok {
457-
s, err = vm.registerStructLocked(v.Elem().Type())
458-
if err != nil {
459-
vm.rw.Unlock()
460-
return nil, false
461-
}
462-
}
463-
vm.rw.Unlock()
464-
}
465-
return s.newTagExpr(unsafe.Pointer(u.Pointer())), true
466-
}
467-
468530
func (f *fieldVM) setFloatGetter() {
469531
if f.ptrDeep == 0 {
470532
f.valueGetter = func(ptr unsafe.Pointer) interface{} {
@@ -690,17 +752,6 @@ func (t *TagExpr) Range(fn func(es ExprSelector, eval func() interface{}) bool)
690752
}
691753

692754
ptr := t.ptr
693-
if list := t.s.ifaceTagExprGetters; len(list) > 0 {
694-
var te *TagExpr
695-
var ok bool
696-
for _, getter := range list {
697-
if te, ok = getter(ptr); ok {
698-
if !te.Range(fn) {
699-
return false
700-
}
701-
}
702-
}
703-
}
704755

705756
if list := t.s.fieldsWithIndirectStructVM; len(list) > 0 {
706757
for _, f := range list {
@@ -759,91 +810,23 @@ func (t *TagExpr) Range(fn func(es ExprSelector, eval func() interface{}) bool)
759810
}
760811
}
761812
}
762-
return true
763-
}
764813

765-
func (t *TagExpr) subRange(omitNil bool, value reflect.Value, fn func(es ExprSelector, eval func() interface{}) bool) bool {
766-
rv := goutil.DereferenceIfaceValue(value)
767-
rt := goutil.DereferenceType(rv.Type())
768-
rv = goutil.DereferenceValue(rv)
769-
switch rt.Kind() {
770-
case reflect.Struct:
771-
if omitNil && !rv.IsValid() {
772-
return true
773-
}
774-
te, err := t.s.vm.subRun(rt, tpack.RuntimeTypeID(rt), unsafe.Pointer(tpack.From(rv).Pointer()))
775-
if err != nil {
776-
return false
777-
}
778-
return te.Range(fn)
779-
780-
case reflect.Slice, reflect.Array:
781-
count := rv.Len()
782-
if count == 0 {
783-
return true
784-
}
785-
switch goutil.DereferenceType(rv.Type().Elem()).Kind() {
786-
case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
787-
for i := count - 1; i >= 0; i-- {
788-
if !t.subRange(omitNil, rv.Index(i), fn) {
789-
return false
790-
}
791-
}
792-
default:
793-
return true
794-
}
795-
796-
case reflect.Map:
797-
if rv.Len() == 0 {
798-
return true
799-
}
800-
var canKey, canValue bool
801-
rt := rv.Type()
802-
switch goutil.DereferenceType(rt.Key()).Kind() {
803-
case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
804-
canKey = true
805-
}
806-
switch goutil.DereferenceType(rt.Elem()).Kind() {
807-
case reflect.Struct, reflect.Interface, reflect.Slice, reflect.Array, reflect.Map:
808-
canValue = true
809-
}
810-
if !canKey && !canValue {
811-
return true
812-
}
813-
for _, key := range rv.MapKeys() {
814-
if canKey {
815-
if !t.subRange(omitNil, key, fn) {
816-
return false
817-
}
818-
}
819-
if canValue {
820-
if !t.subRange(omitNil, rv.MapIndex(key), fn) {
821-
return false
822-
}
814+
if list := t.s.ifaceTagExprGetters; len(list) > 0 {
815+
for _, getter := range list {
816+
if !getter(ptr, func(te *TagExpr) bool {
817+
return te.Range(fn)
818+
}) {
819+
return false
823820
}
824821
}
825822
}
826823
return true
827824
}
828825

829-
func (vm *VM) subRun(t reflect.Type, tid int32, ptr unsafe.Pointer) (*TagExpr, error) {
830-
var err error
831-
vm.rw.RLock()
832-
s, ok := vm.structJar[tid]
833-
vm.rw.RUnlock()
834-
if !ok {
835-
vm.rw.Lock()
836-
s, ok = vm.structJar[tid]
837-
if !ok {
838-
s, err = vm.registerStructLocked(t)
839-
if err != nil {
840-
vm.rw.Unlock()
841-
return nil, err
842-
}
843-
}
844-
vm.rw.Unlock()
845-
}
846-
return s.newTagExpr(ptr), nil
826+
func (t *TagExpr) subRange(omitNil bool, value reflect.Value, fn func(es ExprSelector, eval func() interface{}) bool) bool {
827+
return t.s.vm.subRunAll(omitNil, value, func(te *TagExpr) bool {
828+
return te.Range(fn)
829+
})
847830
}
848831

849832
var (

0 commit comments

Comments
 (0)