github.com/ovechkin-dm/go-dyno@v0.0.23/proxy/proxy.go (about) 1 package proxy 2 3 import ( 4 "errors" 5 "reflect" 6 "unsafe" 7 ) 8 9 func Create[T any](handler func(m *MethodInfo, values []reflect.Value) []reflect.Value) (T, error) { 10 ifaceInstance := new(T) 11 v := reflect.ValueOf(ifaceInstance).Elem() 12 ifaceValue := (*IFaceValue)(unsafe.Pointer(&v)) 13 if v.Type().Kind() != reflect.Interface { 14 return *ifaceInstance, errors.New("cannot create proxy for non-interface type") 15 } 16 numMethods := v.NumMethod() 17 18 var ds = &DynamicStruct{ 19 IFaceValue: v, 20 IFaceValueSource: ifaceValue, 21 } 22 sv := reflect.ValueOf(ds) 23 st := (*refValue)(unsafe.Pointer(&sv)).typ 24 instancePtr := unsafe.Pointer(ds) 25 ifaceValue.Ptr.Word = instancePtr 26 27 arr := make([]int64, unsafe.Sizeof(itab{})) 28 ds.arr = arr 29 ntab := (*itab)(unsafe.Pointer(&arr[0])) 30 ntab.ityp = ifaceValue.Typ 31 ntab.typ = uintptr(unsafe.Pointer(st)) 32 ifaceValue.Ptr.Itab = ntab 33 34 ds.methods = make([]*methodContext, numMethods) 35 for i := 0; i < numMethods; i++ { 36 methodCtx := createMethod(v, ds, handler, i) 37 ifaceValue.Ptr.Itab.fun[i] = unsafe.Pointer(reflect.ValueOf(methods[i]).Pointer()) 38 ds.methods[i] = methodCtx 39 } 40 41 return *ifaceInstance, nil 42 } 43 44 func createMethod( 45 ifaceValue reflect.Value, 46 d *DynamicStruct, 47 handler func(m *MethodInfo, values []reflect.Value) []reflect.Value, num int, 48 ) *methodContext { 49 methodValue := ifaceValue.Method(num) 50 tp := methodValue.Type() 51 inArgs := make([]reflect.Type, 0) 52 outArgs := make([]reflect.Type, 0) 53 inArgs = append(inArgs, reflect.TypeOf(d)) 54 for nin := 0; nin < tp.NumIn(); nin++ { 55 inArgs = append(inArgs, tp.In(nin)) 56 } 57 for nout := 0; nout < tp.NumOut(); nout++ { 58 outArgs = append(outArgs, tp.Out(nout)) 59 } 60 ftype := reflect.FuncOf(inArgs, outArgs, tp.IsVariadic()) 61 methodInfo := &MethodInfo{ 62 Num: num, 63 ReflectValue: methodValue, 64 Name: ifaceValue.Type().Method(num).Name, 65 Type: ifaceValue.Type().Method(num), 66 } 67 hf := func(values []reflect.Value) []reflect.Value { 68 withoutReceiver := values[1:] 69 return handler(methodInfo, withoutReceiver) 70 } 71 rv := reflect.MakeFunc(ftype, hf) 72 ptr := (*refValue)(unsafe.Pointer(&rv)) 73 mfi := (*makeFuncImpl)(ptr.ptr) 74 result := &methodContext{ 75 fn: mfi, 76 tp: tp, 77 rv: rv, 78 } 79 return result 80 }