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  }