func getMethod(methodType reflect.Type, fn reflect.Value) *methodWrapper { if methodType.NumOut() != 1 { return nil } if methodType.Out(0) != typeOfError { return nil } if methodType.NumIn() == 2 { // Method needs two ins: receiver, *Conn. if methodType.In(1) != typeOfConn { return nil } return &methodWrapper{plain: true, fn: fn} } if methodType.NumIn() == 4 { // Method needs four ins: receiver, *Conn, request, *reply. if methodType.In(1) != typeOfConn { return nil } if methodType.In(3).Kind() != reflect.Ptr { return nil } return &methodWrapper{ plain: false, fn: fn, requestType: methodType.In(2), responseType: methodType.In(3).Elem()} } return nil }
func makeClosure(fv reflect.Value, ft reflect.Type) *function { fn := &function{ call: fv, } var rt = Void var at []Type if n := ft.NumOut(); n != 0 { rt = makeRetType(reflect.New(ft.Out(0))) } if n := ft.NumIn(); n != 0 { at = make([]Type, n) for i := 0; i != n; i++ { at[i] = makeArgType(reflect.Zero(ft.In(i))) } } fn.Interface = Prepare(rt, at...) if err := constructClosure(fn); err != nil { panic(err) } runtime.SetFinalizer(fn, destroyClosure) return fn }
// Add all necessary imports for the type, recursing as appropriate. func addImportsForType(imports importMap, t reflect.Type) { // Add any import needed for the type itself. addImportForType(imports, t) // Handle special cases where recursion is needed. switch t.Kind() { case reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice: addImportsForType(imports, t.Elem()) case reflect.Func: // Input parameters. for i := 0; i < t.NumIn(); i++ { addImportsForType(imports, t.In(i)) } // Return values. for i := 0; i < t.NumOut(); i++ { addImportsForType(imports, t.Out(i)) } case reflect.Map: addImportsForType(imports, t.Key()) addImportsForType(imports, t.Elem()) } }
// Note: Methods take the receiver as the first argument, which the want // signature doesn't include. func sigMatches(got, want reflect.Type) bool { nin := want.NumIn() if got.NumIn()-1 != nin { return false } nout := want.NumOut() if got.NumOut() != nout { return false } for i := 0; i < nin; i++ { if got.In(i+1) != want.In(i) { return false } } for i := 0; i < nout; i++ { if got.Out(i) != want.Out(i) { return false } } return true }
// Verifies whether a deep-copy function has a correct signature. func verifyDeepCopyFunctionSignature(ft reflect.Type) error { if ft.Kind() != reflect.Func { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 3 { return fmt.Errorf("expected three 'in' params, got $v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got %v", ft) } if ft.In(1).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) } if ft.In(1).Elem() != ft.In(0) { return fmt.Errorf("expected 'in' param 0 the same as param 1, got: %v", ft) } var forClonerType Cloner if expected := reflect.TypeOf(&forClonerType); ft.In(2) != expected { return fmt.Errorf("expected '%v' arg for 'in' param 2, got: '%v'", expected, ft.In(2)) } var forErrorType error // This convolution is necessary, otherwise TypeOf picks up on the fact // that forErrorType is nil errorType := reflect.TypeOf(&forErrorType).Elem() if ft.Out(0) != errorType { return fmt.Errorf("expected error return, got: %v", ft) } return nil }
func FormatFuncArguments(t reflect.Type) (decl string) { decl = "(" in := make([]string, t.NumIn()) for i := range in { in[i] = ValType(t.In(i)) } decl += strings.Join(in, ",") + ")" out := make([]string, t.NumOut()) if len(out) > 0 { for i := range out { out[i] = ValType(t.Out(i)) } s := strings.Join(out, ",") if len(out) != 1 { s = "(" + s + ")" } decl += " " + s } return }
func (p *MethodMetadata) IsEqual(t reflect.Type) bool { if t.ConvertibleTo(p.Method.Type) { return false } baseIndex := 0 if p.Method.Index >= 0 { baseIndex = 1 } if t.NumIn()+baseIndex != p.Method.Type.NumIn() { return false } for i := 0; i < p.Method.Type.NumIn()-baseIndex; i++ { if p.Method.Type.In(baseIndex+i) != t.In(i) { return false } } for i := 0; i < p.Method.Type.NumOut(); i++ { if p.Method.Type.Out(baseIndex+i) != t.Out(i) { return false } } return true }
func (ms *GobMarshaller) Prepare(name string, fn interface{}) (err error) { var ( fT reflect.Type ) // Gob needs to register type before encode/decode if fT = reflect.TypeOf(fn); fT.Kind() != reflect.Func { err = fmt.Errorf("fn is not a function but %v", fn) return } reg := func(v reflect.Value) (err error) { if !v.CanInterface() { err = fmt.Errorf("Can't convert to value in input of %v for name:%v", fn, name) return } gob.Register(v.Interface()) return } for i := 0; i < fT.NumIn(); i++ { // create a zero value of the type of parameters if err = reg(reflect.Zero(fT.In(i))); err != nil { return } } for i := 0; i < fT.NumOut(); i++ { if err = reg(reflect.Zero(fT.Out(i))); err != nil { return } } return }
func typeString_FuncOrMethod( name string, t reflect.Type, pkgPath string) (s string) { // Deal with input types. var in []string for i := 0; i < t.NumIn(); i++ { in = append(in, typeString(t.In(i), pkgPath)) } // And output types. var out []string for i := 0; i < t.NumOut(); i++ { out = append(out, typeString(t.Out(i), pkgPath)) } // Put it all together. s = fmt.Sprintf( "%s(%s) (%s)", name, strings.Join(in, ", "), strings.Join(out, ", ")) return }
func newTypeFromFactoryFunction(function interface{}, factoryType reflect.Type, parameters []interface{}) TypeFactory { if factoryType.NumOut() != 1 { return newInvalidType(fmt.Errorf("invalid number of return parameters: %d", factoryType.NumOut())) } kindOfGeneratedType := factoryType.Out(0).Kind() if kindOfGeneratedType != reflect.Interface && kindOfGeneratedType != reflect.Ptr { return newInvalidType(fmt.Errorf("return parameter is no interface or pointer but a %v", kindOfGeneratedType)) } if factoryType.IsVariadic() { if factoryType.NumIn() > len(parameters) { return newInvalidType(fmt.Errorf("invalid number of input parameters for variadic function: got %d but expected at least %d", len(parameters), factoryType.NumIn())) } } else { if factoryType.NumIn() != len(parameters) { return newInvalidType(fmt.Errorf("invalid number of input parameters: got %d but expected %d", len(parameters), factoryType.NumIn())) } } t := &typeFactory{ factory: reflect.ValueOf(function), factoryType: factoryType, } var err error t.factoryArguments, err = buildFactoryCallArguments(factoryType, parameters) if err != nil { return newInvalidType(err) } return t }
func InTypes(fnType reflect.Type) []reflect.Type { var types []reflect.Type for i := 0; i < fnType.NumIn(); i++ { types = append(types, fnType.In(i)) } return types }
func checkFunc(fnType reflect.Type) (bool, error) { var state State foundState := 0 nin := fnType.NumIn() for i := 0; i < nin; i++ { if fnType.In(i) == reflect.TypeOf(state) { foundState++ } else if fnType.In(i) == reflect.TypeOf(&state) { return false, fmt.Errorf("raw function can not use `*State' as arg, instead using `State'") } } wrongRawFunc := false if foundState > 1 { wrongRawFunc = true } else if foundState == 1 { nout := fnType.NumOut() if nin != 1 || nout != 1 { wrongRawFunc = true } else { if fnType.Out(0).Kind() != reflect.Int { wrongRawFunc = true } } } if wrongRawFunc { return false, fmt.Errorf("raw function must be type: `func(State) int'") } return true, nil }
// BuildArgs creates an args slice than can be used to make a f.Call(args) func BuildArgs(t crossdock.T, desc string, ft reflect.Type, give []interface{}, initialArgs int) (_ []reflect.Value, ok bool) { check := crossdock.Checks(t) wantIn := len(give) + initialArgs // +2 for ctx and reqMeta if !check.Equal(wantIn, ft.NumIn(), "%v: should accept %d arguments", desc, wantIn) { return nil, false } var args []reflect.Value for i, v := range give { var val reflect.Value vt := ft.In(i + initialArgs) if v == nil { // nil is an invalid argument to ValueOf. For nil, use the zero // value for that argument. val = reflect.Zero(vt) } else { val = reflect.ValueOf(v) } if !check.Equal(vt, val.Type(), "%v: argument %v type mismatch", desc, i) { return nil, false } args = append(args, val) } return args, true }
// Get all the parameters setup for invocation. func (method ApiMethod) createArguments(userId UserId, userName UserName, token Token, response http.ResponseWriter, request *http.Request) (bool, []reflect.Value) { var handlerType reflect.Type = reflect.TypeOf(method.handler) var numParams int = handlerType.NumIn() var apiParamIndex = 0 var paramValues []reflect.Value = make([]reflect.Value, numParams) for i := 0; i < numParams; i++ { var ParamType reflect.Type = handlerType.In(i) // The user id, token, request, and response get handled specially. if method.auth && ParamType.String() == "goapi.Token" { paramValues[i] = reflect.ValueOf(token) } else if method.auth && ParamType.String() == "goapi.UserId" { paramValues[i] = reflect.ValueOf(userId) } else if method.auth && ParamType.String() == "goapi.UserName" { paramValues[i] = reflect.ValueOf(userName) } else if ParamType.String() == "*http.Request" { paramValues[i] = reflect.ValueOf(request) } else if ParamType.String() == "http.ResponseWriter" { paramValues[i] = reflect.ValueOf(response) } else { // Normal param, fetch the next api parameter and pass it along. ok, val := method.fetchParam(apiParamIndex, request) if !ok { return false, []reflect.Value{} } paramValues[i] = val apiParamIndex++ } } return true, paramValues }
func args(f reflect.Type) []reflect.Type { in := make([]reflect.Type, f.NumIn()) for i := 0; i < f.NumIn(); i++ { in[i] = f.In(i) } return in }
// verifyHandler ensures that the given t is a function with the following signature: // func(json.Context, *ArgType)(*ResType, error) func verifyHandler(t reflect.Type) error { if t.NumIn() != 2 || t.NumOut() != 2 { return fmt.Errorf("handler should be of format func(json.Context, *ArgType) (*ResType, error)") } isStructPtr := func(t reflect.Type) bool { return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct } isMap := func(t reflect.Type) bool { return t.Kind() == reflect.Map && t.Key().Kind() == reflect.String } validateArgRes := func(t reflect.Type, name string) error { if !isStructPtr(t) && !isMap(t) { return fmt.Errorf("%v should be a pointer to a struct, or a map[string]interface{}", name) } return nil } if t.In(0) != typeOfContext { return fmt.Errorf("arg0 should be of type json.Context") } if err := validateArgRes(t.In(1), "second argument"); err != nil { return err } if err := validateArgRes(t.Out(0), "first return value"); err != nil { return err } if !t.Out(1).AssignableTo(typeOfError) { return fmt.Errorf("second return value should be an error") } return nil }
func genArgs(fnType reflect.Type, args []interface{}) []reflect.Value { expectNArgs := fnType.NumIn() actualNArgs := len(args) if expectNArgs != actualNArgs { panic(fmt.Sprintf("the function %s expect %d arguments, acctually get %d arguments", fnType, expectNArgs, actualNArgs)) } argsValues := make([]reflect.Value, expectNArgs) for i, arg := range args { argType := fnType.In(i) argValue := reflect.ValueOf(arg) if !argValue.IsValid() { argValue = reflect.Zero(argType) } actualType := argValue.Type() if argType != actualType && !actualType.Implements(argType) { // TODO: change %dth to %dst, %dnd, %drd, %dth. panic(fmt.Sprintf("the %dth argument on function %s gets wrong type: expect %v, actually get %v", i, fnType, argType, actualType)) } argsValues[i] = argValue } return argsValues }
//should the context be passed to the handler? func requiresContext(handlerType reflect.Type) bool { //fmt.Printf("type %v\n", handlerType) //if the method doesn't take arguments, no if handlerType.NumIn() == 0 { return false } //if the first argument is not a pointer, no a0 := handlerType.In(0) if a0.Kind() != reflect.Ptr { return false } //if the first argument is a context, yes if a0.Elem() == contextType { return true } //another case -- the first argument is a method receiver, and the //second argument is a web.Context if handlerType.NumIn() > 1 { a1 := handlerType.In(1) if a1.Kind() != reflect.Ptr { return false } if a1.Elem() == contextType { return true } } return false }
// t's Kind must be a reflect.Func. func funcArgsFromType(t reflect.Type) (in []*Parameter, variadic *Parameter, out []*Parameter, err error) { nin := t.NumIn() if t.IsVariadic() { nin-- } var p *Parameter for i := 0; i < nin; i++ { p, err = parameterFromType(t.In(i)) if err != nil { return } in = append(in, p) } if t.IsVariadic() { p, err = parameterFromType(t.In(nin).Elem()) if err != nil { return } variadic = p } for i := 0; i < t.NumOut(); i++ { p, err = parameterFromType(t.Out(i)) if err != nil { return } out = append(out, p) } return }
// Verifies whether a conversion function has a correct signature. func verifyConversionFunctionSignature(ft reflect.Type) error { if ft.Kind() != reflect.Func { return fmt.Errorf("expected func, got: %v", ft) } if ft.NumIn() != 3 { return fmt.Errorf("expected three 'in' params, got: %v", ft) } if ft.NumOut() != 1 { return fmt.Errorf("expected one 'out' param, got: %v", ft) } if ft.In(0).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 0, got: %v", ft) } if ft.In(1).Kind() != reflect.Ptr { return fmt.Errorf("expected pointer arg for 'in' param 1, got: %v", ft) } scopeType := Scope(nil) if e, a := reflect.TypeOf(&scopeType).Elem(), ft.In(2); e != a { return fmt.Errorf("expected '%v' arg for 'in' param 2, got '%v' (%v)", e, a, ft) } var forErrorType error // This convolution is necessary, otherwise TypeOf picks up on the fact // that forErrorType is nil. errorType := reflect.TypeOf(&forErrorType).Elem() if ft.Out(0) != errorType { return fmt.Errorf("expected error return, got: %v", ft) } return nil }
func GetMethodArgs(t reflect.Type) []reflect.Type { l := t.NumIn() - 1 in := make([]reflect.Type, l) for i := 0; i < l; i++ { in[i] = t.In(i + 1) } return in }
func GetFuncArgs(t reflect.Type) []reflect.Type { l := t.NumIn() in := make([]reflect.Type, l) for i := 0; i < l; i++ { in[i] = t.In(i) } return in }
func getInputTypeString(i int, ft reflect.Type) string { numInputs := ft.NumIn() if i == numInputs-1 && ft.IsVariadic() { return "..." + getTypeString(ft.In(i).Elem()) } return getTypeString(ft.In(i)) }
func funcIsBypass(t reflect.Type) bool { if t.NumIn() == 1 && t.NumOut() == 1 && t.In(0) == refTypeLStatePtr && t.Out(0) == refTypeInt { return true } if t.NumIn() == 2 && t.NumOut() == 1 && t.In(1) == refTypeLStatePtr && t.Out(0) == refTypeInt { return true } return false }
/** * get func params * * @param funcType * @param */ func (r *ReflectRouter) getFuncArgs(funcType reflect.Type, context *HttpContext) []reflect.Value { argsNum := funcType.NumIn() args := make([]reflect.Value, argsNum, argsNum) for i := 0; i < argsNum; i++ { in := funcType.In(i) typeString := in.String() var argsValue reflect.Value switch typeString { case "*http.Request": argsValue = reflect.ValueOf(context.Request) case "http.Request": argsValue = reflect.ValueOf(context.Request).Elem() case "*url.URL": argsValue = reflect.ValueOf(context.Request.URL) case "url.URL": argsValue = reflect.ValueOf(context.Request.URL).Elem() case "*leafveingo.HttpContext": argsValue = reflect.ValueOf(context) case "leafveingo.HttpContext": argsValue = reflect.ValueOf(context).Elem() case "[]uint8": body := context.RequestBody() if nil != body { argsValue = reflect.ValueOf(body) } else { argsValue = reflect.Zero(in) } case "http.ResponseWriter": argsValue = reflect.ValueOf(context.RespWrite) case "LVSession.HttpSession": session, _ := context.Session(false) if nil != session { argsValue = reflect.ValueOf(session) } else { argsValue = reflect.Zero(in) } default: val, err := context.PackStructFormByRefType(in) if nil == err { argsValue = val } else { context.LVServer().Log().Debug(err.Error()) } } if reflect.Invalid == argsValue.Kind() { argsValue = reflect.Zero(in) } args[i] = argsValue } return args }
func (f *FuncUtil) getArgumentTypes(t reflect.Type) []reflect.Type { if t.NumIn() == 0 { return nil } params := []reflect.Type{} for i := 0; i < t.NumIn(); i++ { params = append(params, t.In(i)) } return params }
func getInputs(ft reflect.Type) []reflect.Type { numIn := ft.NumIn() inputs := make([]reflect.Type, numIn) for i := 0; i < numIn; i++ { inputs[i] = ft.In(i) } return inputs }
// isPubSub tests whether the given method has as as first argument a context.Context // and returns the pair (Subscription, error) func isPubSub(methodType reflect.Type) bool { // numIn(0) is the receiver type if methodType.NumIn() < 2 || methodType.NumOut() != 2 { return false } return isContextType(methodType.In(1)) && isSubscriptionType(methodType.Out(0)) && isErrorType(methodType.Out(1)) }
func functionArgRetTypes(funt reflect.Type) (targs, tout []reflect.Type) { targs = make([]reflect.Type, funt.NumIn()) for i := range targs { targs[i] = funt.In(i) } tout = make([]reflect.Type, funt.NumOut()) for i := range tout { tout[i] = funt.Out(i) } return }
func assertValidFetcher(t reflect.Type) { if t.Kind() != reflect.Func { panic(fmt.Sprintf("rcache: Fetcher must be a function, got [%v]", t)) } if t.NumIn() != 1 { panic(fmt.Sprintf("rcache: Fetcher must be function with one arg, has %d [%v]", t.NumIn(), t)) } if t.NumOut() != 2 || t.Out(0) != byteArrayType || t.Out(1) != errorType { panic(fmt.Sprintf("rcache: Fetcher must be function that returns ([]byte, error), has %d [%v]", t.NumOut(), t)) } }