github.com/ydb-platform/ydb-go-sdk/v3@v3.57.0/trace/traceutil.go (about) 1 package trace 2 3 import ( 4 "reflect" 5 ) 6 7 // Stub is a helper function that stubs all functional fields of x with given 8 // f. 9 func Stub(x interface{}, f func(name string, args ...interface{})) { 10 (FieldStubber{ 11 OnCall: f, 12 }).Stub(reflect.ValueOf(x)) 13 } 14 15 func ClearContext(x interface{}) interface{} { 16 p := reflect.ValueOf(x).Index(0) 17 t := p.Elem().Type() 18 f, has := t.FieldByName("Context") 19 if has && f.Type.Kind() == reflect.Interface { 20 x := reflect.New(t) 21 x.Elem().Set(p.Elem()) 22 c := x.Elem().FieldByName(f.Name) 23 c.Set(reflect.Zero(c.Type())) 24 p.Set(x) 25 } 26 27 return p.Interface() 28 } 29 30 // FieldStubber contains options of filling all struct functional fields. 31 type FieldStubber struct { 32 // OnStub is an optional callback that is called when field getting 33 // stubbed. 34 OnStub func(name string) 35 36 // OnCall is an optional callback that will be called for each stubbed 37 // field getting called. 38 OnCall func(name string, args ...interface{}) 39 } 40 41 // Stub fills in given x struct. 42 func (f FieldStubber) Stub(x reflect.Value) { 43 var ( 44 v = x.Elem() 45 t = v.Type() 46 ) 47 for i := 0; i < t.NumField(); i++ { 48 var ( 49 fx = v.Field(i) 50 ft = fx.Type() 51 ) 52 if ft.Kind() != reflect.Func { 53 continue 54 } 55 name := t.Field(i).Name 56 if f.OnStub != nil { 57 f.OnStub(name) 58 } 59 out := []reflect.Value{} 60 for i := 0; i < ft.NumOut(); i++ { 61 ti := reflect.New(ft.Out(i)).Elem() 62 out = append(out, ti) 63 } 64 fn := reflect.MakeFunc(ft, func(args []reflect.Value) []reflect.Value { 65 if f.OnCall == nil { 66 return out 67 } 68 params := make([]interface{}, len(args)) 69 for i, arg := range args { 70 params[i] = arg.Interface() 71 } 72 f.OnCall(name, params...) 73 74 return out 75 }) 76 fx.Set(fn) 77 } 78 }