Пример #1
0
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
}
Пример #2
0
// 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())
	}
}
Пример #3
0
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
}
Пример #4
0
// 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
}
Пример #5
0
// 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
}
Пример #6
0
// 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
}
Пример #7
0
// 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
}
Пример #8
0
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
}
Пример #9
0
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
}
Пример #10
0
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
}
Пример #11
0
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
}
Пример #12
0
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
}
Пример #13
0
// 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
}
Пример #14
0
// 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
}
Пример #15
0
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
}
Пример #16
0
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
}
Пример #18
0
//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
}
Пример #19
0
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
}
Пример #20
0
// 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
}
Пример #21
0
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
}
Пример #22
0
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
}
Пример #23
0
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))
}
Пример #24
0
// 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)
}
Пример #25
0
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
}
Пример #26
0
/**
 *	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
}
Пример #27
0
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
}
Пример #28
0
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
}
Пример #29
0
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)
	}
}
Пример #30
0
// 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))
}