示例#1
0
/*
RenderViewBindURLArgs creates a View where renderFunc is called from View.Render
with Context.URLArgs converted to function arguments.
The first renderFunc argument can be of type *Context, but this is optional.
All further arguments will be converted from the corresponding Context.URLArgs
string to their actual type.
Conversion to integer, float, string and bool arguments are supported.
If there are more URLArgs than function args, then supernumerous URLArgs will
be ignored.
If there are less URLArgs than function args, then the function args will
receive their types zero value.
The result of renderFunc can be empty or of type error.

Example:

	view.RenderViewBindURLArgs(func(i int, b bool) {
		ctx.Response.Printf("ctx.URLArgs[0]: %d, ctx.URLArgs[1]: %b", i, b)
	})
*/
func RenderViewBindURLArgs(renderFunc interface{}) RenderView {
	v := reflect.ValueOf(renderFunc)
	t := v.Type()
	if t.Kind() != reflect.Func {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc must be a function, got %T", renderFunc))
	}
	passContext := false
	if t.NumIn() > 0 {
		passContext = t.In(0) == reflect.TypeOf((*Context)(nil))
		if !passContext && !reflection.CanStringToValueOfType(t.In(0)) {
			panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's first argument must type must be of type *view.Context or convertible from string, got %s", t.In(0)))
		}
	}
	for i := 1; i < t.NumIn(); i++ {
		if !reflection.CanStringToValueOfType(t.In(i)) {
			panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's argument #%d must type must be convertible from string, got %s", i, t.In(i)))
		}
	}
	switch t.NumOut() {
	case 0:
	case 1:
		if t.Out(0) != reflection.TypeOfError {
			panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's result must be of type error, got %s", t.Out(0)))
		}
	default:
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc must have zero or one results, got %d", t.NumOut()))
	}
	return RenderView(
		func(ctx *Context) error {
			args := make([]reflect.Value, t.NumIn())
			for i := 0; i < t.NumIn(); i++ {
				if i == 0 && passContext {
					args[0] = reflect.ValueOf(ctx)
				} else {
					iu := i
					if passContext {
						iu--
					}
					if iu < len(ctx.URLArgs) {
						val, err := reflection.StringToValueOfType(ctx.URLArgs[iu], t.In(i))
						if err != nil {
							return err
						}
						args[i] = reflect.ValueOf(val)
					} else {
						args[i] = reflect.Zero(t.In(i))
					}
				}
			}
			results := v.Call(args)
			if t.NumOut() == 1 {
				err, _ := results[0].Interface().(error)
				return err
			}
			return nil
		},
	)
}
示例#2
0
func DynamicViewBindURLArgs(viewFunc interface{}) DynamicView {
	v := reflect.ValueOf(viewFunc)
	t := v.Type()
	if t.Kind() != reflect.Func {
		panic(fmt.Errorf("DynamicViewBindURLArgs: viewFunc must be a function, got %T", viewFunc))
	}
	if t.NumIn() == 0 {
		panic(fmt.Errorf("DynamicViewBindURLArgs: viewFunc has no arguments, needs at least one *view.Response"))
	}
	if t.In(0) != reflect.TypeOf((*Response)(nil)) {
		panic(fmt.Errorf("DynamicViewBindURLArgs: viewFunc's first argument must type must be *view.Response, got %s", t.In(0)))
	}
	if t.NumOut() != 2 {
		panic(fmt.Errorf("DynamicViewBindURLArgs: viewFunc must have two results, got %d", t.NumOut()))
	}
	if t.Out(0) != reflect.TypeOf((*View)(nil)).Elem() {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's first result must be of type view.View, got %s", t.Out(0)))
	}
	if t.Out(1) != reflection.TypeOfError {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's second result must be of type error, got %s", t.Out(1)))
	}
	return DynamicView(
		func(ctx *Context) (view View, err error) {
			if len(ctx.URLArgs) != t.NumIn()-1 {
				panic(fmt.Errorf("DynamicViewBindURLArgs: number of response URL args does not match viewFunc's arg count"))
			}
			args := make([]reflect.Value, t.NumIn())
			args[0] = reflect.ValueOf(ctx)
			for i, urlArg := range ctx.URLArgs {
				val, err := reflection.StringToValueOfType(urlArg, t.In(i+1))
				if err != nil {
					return nil, err
				}
				args[i+1] = reflect.ValueOf(val)
			}
			results := v.Call(args)
			if results[0].Interface() != nil {
				view = results[0].Interface().(View)
			}
			if results[1].Interface() != nil {
				err = results[1].Interface().(error)
			}
			return view, err
		},
	)
}
示例#3
0
func RenderViewBindURLArgs(renderFunc interface{}) RenderView {
	v := reflect.ValueOf(renderFunc)
	t := v.Type()
	if t.Kind() != reflect.Func {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc must be a function, got %T", renderFunc))
	}
	if t.NumIn() == 0 {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc has no arguments, needs at least one *view.Response"))
	}
	if t.In(0) != reflect.TypeOf((*Response)(nil)) {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's first argument must type must be *view.Response, got %s", t.In(0)))
	}
	if t.NumOut() != 1 {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc must have one result, got %d", t.NumOut()))
	}
	if t.Out(0) != reflection.TypeOfError {
		panic(fmt.Errorf("RenderViewBindURLArgs: renderFunc's result must be of type error, got %s", t.Out(0)))
	}
	return RenderView(
		func(ctx *Context) error {
			if len(ctx.URLArgs) != t.NumIn()-1 {
				panic(fmt.Errorf("RenderViewBindURLArgs: number of response URL args does not match renderFunc's arg count"))
			}
			args := make([]reflect.Value, t.NumIn())
			args[0] = reflect.ValueOf(ctx)
			for i, urlArg := range ctx.URLArgs {
				val, err := reflection.StringToValueOfType(urlArg, t.In(i+1))
				if err != nil {
					return err
				}
				args[i+1] = reflect.ValueOf(val)
			}
			return v.Call(args)[0].Interface().(error)
		},
	)
}
示例#4
0
/*
DynamicViewBindURLArgs creates a View where getViewFunc is called from View.Render
with Context.URLArgs converted to function arguments.
The first getViewFunc argument can be of type *Context, but this is optional.
All further arguments will be converted from the corresponding Context.URLArgs
string to their actual type.
Conversion to integer, float, string and bool arguments are supported.
If there are more URLArgs than function args, then supernumerous URLArgs will
be ignored.
If there are less URLArgs than function args, then the function args will
receive their types zero value.
The first result value of getViewFunc has to be of type View,
the second result is optional and of type error.

Example:

	view.DynamicViewBindURLArgs(func(i int, b bool) view.View {
		return view.Printf("ctx.URLArgs[0]: %d, ctx.URLArgs[1]: %b", i, b)
	})
*/
func DynamicViewBindURLArgs(getViewFunc interface{}) DynamicView {
	v := reflect.ValueOf(getViewFunc)
	t := v.Type()
	if t.Kind() != reflect.Func {
		panic(fmt.Errorf("DynamicViewBindURLArgs: getViewFunc must be a function, got %T", getViewFunc))
	}
	passContext := false
	if t.NumIn() > 0 {
		passContext = t.In(0) == reflect.TypeOf((*Context)(nil))
		if !passContext && !reflection.CanStringToValueOfType(t.In(0)) {
			panic(fmt.Errorf("DynamicViewBindURLArgs: getViewFunc's first argument must type must be of type *view.Context or convertible from string, got %s", t.In(0)))
		}
	}
	for i := 1; i < t.NumIn(); i++ {
		if !reflection.CanStringToValueOfType(t.In(i)) {
			panic(fmt.Errorf("DynamicViewBindURLArgs: getViewFunc's argument #%d must type must be convertible from string, got %s", i, t.In(i)))
		}
	}
	switch t.NumOut() {
	case 2:
		if t.Out(1) != reflection.TypeOfError {
			panic(fmt.Errorf("DynamicViewBindURLArgs: getViewFunc's second result must be of type error, got %s", t.Out(1)))
		}
		fallthrough
	case 1:
		if t.Out(0) != reflect.TypeOf((*View)(nil)).Elem() {
			panic(fmt.Errorf("DynamicViewBindURLArgs: getViewFunc's first result must be of type view.View, got %s", t.Out(0)))
		}
	default:
		panic(fmt.Errorf("DynamicViewBindURLArgs: getViewFunc must have one or two results, got %d", t.NumOut()))
	}
	return DynamicView(
		func(ctx *Context) (view View, err error) {
			args := make([]reflect.Value, t.NumIn())
			for i := 0; i < t.NumIn(); i++ {
				if i == 0 && passContext {
					args[0] = reflect.ValueOf(ctx)
				} else {
					iu := i
					if passContext {
						iu--
					}
					if iu < len(ctx.URLArgs) {
						val, err := reflection.StringToValueOfType(ctx.URLArgs[iu], t.In(i))
						if err != nil {
							return nil, err
						}
						args[i] = reflect.ValueOf(val)
					} else {
						args[i] = reflect.Zero(t.In(i))
					}
				}
			}
			results := v.Call(args)
			if t.NumOut() == 2 {
				err, _ = results[1].Interface().(error)
			}
			view, _ = results[0].Interface().(View)
			return view, err
		},
	)
}