util.go (1314B)
1 package bun 2 3 import "reflect" 4 5 func indirect(v reflect.Value) reflect.Value { 6 switch v.Kind() { 7 case reflect.Interface: 8 return indirect(v.Elem()) 9 case reflect.Ptr: 10 return v.Elem() 11 default: 12 return v 13 } 14 } 15 16 func walk(v reflect.Value, index []int, fn func(reflect.Value)) { 17 v = reflect.Indirect(v) 18 switch v.Kind() { 19 case reflect.Slice: 20 sliceLen := v.Len() 21 for i := 0; i < sliceLen; i++ { 22 visitField(v.Index(i), index, fn) 23 } 24 default: 25 visitField(v, index, fn) 26 } 27 } 28 29 func visitField(v reflect.Value, index []int, fn func(reflect.Value)) { 30 v = reflect.Indirect(v) 31 if len(index) > 0 { 32 v = v.Field(index[0]) 33 if v.Kind() == reflect.Ptr && v.IsNil() { 34 return 35 } 36 walk(v, index[1:], fn) 37 } else { 38 fn(v) 39 } 40 } 41 42 func typeByIndex(t reflect.Type, index []int) reflect.Type { 43 for _, x := range index { 44 switch t.Kind() { 45 case reflect.Ptr: 46 t = t.Elem() 47 case reflect.Slice: 48 t = indirectType(t.Elem()) 49 } 50 t = t.Field(x).Type 51 } 52 return indirectType(t) 53 } 54 55 func indirectType(t reflect.Type) reflect.Type { 56 if t.Kind() == reflect.Ptr { 57 t = t.Elem() 58 } 59 return t 60 } 61 62 func sliceElemType(v reflect.Value) reflect.Type { 63 elemType := v.Type().Elem() 64 if elemType.Kind() == reflect.Interface && v.Len() > 0 { 65 return indirect(v.Index(0).Elem()).Type() 66 } 67 return indirectType(elemType) 68 }