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()) } }
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 }
// 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 }
// 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 }
// unify attempts to satisfy a pair of types, where the `param` type is the // expected type of a function argument and the `input` type is the known // type of a function argument. The `param` type may be parametric (that is, // it may contain a type that is convertible to TypeVariable) but the // `input` type may *not* be parametric. // // Any failure to unify the two types results in a panic. // // The end result of unification is a type environment: a set of substitutions // from type variable to a Go type. func (tp typePair) unify(param, input reflect.Type) error { if tyname := tyvarName(input); len(tyname) > 0 { return tp.error("Type variables are not allowed in the types of " + "arguments.") } if tyname := tyvarName(param); len(tyname) > 0 { if cur, ok := tp.tyenv[tyname]; ok && cur != input { return tp.error("Type variable %s expected type '%s' but got '%s'.", tyname, cur, input) } else if !ok { tp.tyenv[tyname] = input } return nil } if param.Kind() != input.Kind() { return tp.error("Cannot unify different kinds of types '%s' and '%s'.", param, input) } switch param.Kind() { case reflect.Array: return tp.unify(param.Elem(), input.Elem()) case reflect.Chan: if param.ChanDir() != input.ChanDir() { return tp.error("Cannot unify '%s' with '%s' "+ "(channel directions are different: '%s' != '%s').", param, input, param.ChanDir(), input.ChanDir()) } return tp.unify(param.Elem(), input.Elem()) case reflect.Func: if param.NumIn() != input.NumIn() || param.NumOut() != input.NumOut() { return tp.error("Cannot unify '%s' with '%s'.", param, input) } for i := 0; i < param.NumIn(); i++ { if err := tp.unify(param.In(i), input.In(i)); err != nil { return err } } for i := 0; i < param.NumOut(); i++ { if err := tp.unify(param.Out(i), input.Out(i)); err != nil { return err } } case reflect.Map: if err := tp.unify(param.Key(), input.Key()); err != nil { return err } return tp.unify(param.Elem(), input.Elem()) case reflect.Ptr: return tp.unify(param.Elem(), input.Elem()) case reflect.Slice: return tp.unify(param.Elem(), input.Elem()) } // The only other container types are Interface and Struct. // I am unsure about what to do with interfaces. Mind is fuzzy. // Structs? I don't think it really makes much sense to use type // variables inside of them. return nil }
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 (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 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 }
func methSigMatches(got reflect.Type, _want interface{}) error { // Note: Methods take the receiver as the first argument, which the want // signature doesn't include. if got.NumIn() == 0 { // The receiver is missing! return fmt.Errorf("Method without reciever!") } want := reflect.TypeOf(_want) if got.NumIn()-1 != want.NumIn() { return fmt.Errorf("Method should have %d arguments, not %d", want.NumIn(), got.NumIn()-1) } if got.NumOut() != want.NumOut() { return fmt.Errorf("Method should have %d return values, not %d", want.NumOut(), got.NumOut()) } for i := 0; i < want.NumIn(); i++ { if got.In(i+1) != want.In(i) { return fmt.Errorf("Method argument %d should be %v, not %v", i+1, want.In(i), got.In(i+1)) } } for i := 0; i < want.NumOut(); i++ { if got.Out(i) != want.Out(i) { return fmt.Errorf("Method return value %d should be %v, not %v", i+1, want.Out(i), got.Out(i)) } } 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 }
func fixupArgs(t reflect.Type, v ...interface{}) []reflect.Value { res := make([]reflect.Value, len(v)) for ix, vv := range v { res[ix] = fixupArg(t.In(ix), vv) } return res }
// 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 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)) }
// safeNumericConvert converts numeric parameter val from js to the type that the function fn expects if its safe to do so. // This allows literals (int64) and the general js numeric form (float64) to be passed as parameters to go functions easily. func safeNumericConvert(fn reflect.Type, i int, val interface{}) reflect.Value { switch val.(type) { default: // Not a supported conversion return reflect.ValueOf(val) case float64, int64: // What type is the func expecting? var ptype reflect.Type switch { case fn.IsVariadic() && fn.NumIn() <= i+1: // This argument is variadic so use the variadics element type. ptype = fn.In(fn.NumIn() - 1).Elem() case fn.NumIn() > i: ptype = fn.In(i) } if f64, ok := val.(float64); ok { switch ptype.Kind() { case reflect.Float64: return reflect.ValueOf(val) case reflect.Float32: if reflect.Zero(ptype).OverflowFloat(f64) { // Not safe to convert return reflect.ValueOf(val) } return reflect.ValueOf(val).Convert(ptype) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: i64 := int64(f64) if float64(i64) != f64 { // Not safe to convert return reflect.ValueOf(val) } // The float represents an integer val = i64 default: // Not a supported conversion return reflect.ValueOf(val) } } i64 := val.(int64) switch ptype.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32: if !reflect.Zero(ptype).OverflowInt(i64) { return reflect.ValueOf(val).Convert(ptype) } case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: if i64 > 0 && !reflect.Zero(ptype).OverflowUint(uint64(i64)) { return reflect.ValueOf(val).Convert(ptype) } } } // Not a supported conversion return reflect.ValueOf(val) }
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 }
func (me *MethodInvoker) decipherInputs(mt reflect.Type) { me.inpCount = mt.NumIn() - 1 // skip the first param (me) me.inpParams = make([]string, mt.NumIn()-1) for i := 1; i < mt.NumIn(); i++ { pt := mt.In(i) me.inpParams[i-1] = getSymbolFromType(pt) } }
// 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)) }