mirror of
https://github.com/kataras/iris.git
synced 2025-02-02 15:30:36 +01:00
_future
Ok we did convert a regular `func([]string) func(string)bool` to `func(anything...) func(string)bool` Former-commit-id: 1097e5d61663f1b14867e807ae53e2ccbb6401a8
This commit is contained in:
parent
00cfdf404a
commit
1ac6f08a97
|
@ -1,6 +1,7 @@
|
||||||
// I would be grateful if I had the chance to see the whole work-in-progress in a codebase when I started.
|
// I would be grateful if I had the chance to see the whole work-in-progress in a codebase when I started.
|
||||||
// You have the chance to learn faster nowdays, don't underestimate that, that's the only reason that this "_future" folder exists now.
|
// You have the chance to learn faster nowdays, don't underestimate that, that's the only reason that this "_future" folder exists now.
|
||||||
//
|
//
|
||||||
|
//
|
||||||
// The whole "router" package is a temp place to test my ideas and implementations for future iris' features.
|
// The whole "router" package is a temp place to test my ideas and implementations for future iris' features.
|
||||||
// Young developers can understand and see how ideas can be transform to real implementations on a software like Iris,
|
// Young developers can understand and see how ideas can be transform to real implementations on a software like Iris,
|
||||||
// watching the history of a "dirty" code can be useful for some of you.
|
// watching the history of a "dirty" code can be useful for some of you.
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
package router
|
package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -162,29 +164,105 @@ func addMacroFunc(macroName string, funcName string, v func([]string) _macrofn)
|
||||||
|
|
||||||
const global_macro = "any"
|
const global_macro = "any"
|
||||||
|
|
||||||
|
func macroFuncFrom(v interface{}) func(params []string) _macrofn {
|
||||||
|
// this is executed once on boot time, not at serve time:
|
||||||
|
vot := reflect.TypeOf(v)
|
||||||
|
numFields := vot.NumIn()
|
||||||
|
|
||||||
|
return func(params []string) _macrofn {
|
||||||
|
if len(params) != numFields {
|
||||||
|
panic("should accepts _numFields_ args")
|
||||||
|
}
|
||||||
|
var args []reflect.Value
|
||||||
|
|
||||||
|
// check for accepting arguments
|
||||||
|
for i := 0; i < numFields; i++ {
|
||||||
|
field := vot.In(i)
|
||||||
|
|
||||||
|
switch field.Kind() {
|
||||||
|
case reflect.Int:
|
||||||
|
val, err := strconv.Atoi(params[i])
|
||||||
|
if err != nil {
|
||||||
|
panic("invalid first parameter: " + err.Error())
|
||||||
|
}
|
||||||
|
args = append(args, reflect.ValueOf(val))
|
||||||
|
case reflect.String:
|
||||||
|
case reflect.Bool:
|
||||||
|
default:
|
||||||
|
panic("unsported type!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for the return type (only one ofc, which again is a function but it returns a boolean)
|
||||||
|
// which accepts one argument which is the parameter value.
|
||||||
|
if vot.NumOut() != 1 {
|
||||||
|
panic("expecting to return only one (func)")
|
||||||
|
}
|
||||||
|
rof := vot.Out(0)
|
||||||
|
if rof.Kind() != reflect.Func {
|
||||||
|
panic("expecting to return a function!")
|
||||||
|
}
|
||||||
|
|
||||||
|
returnRof := rof.Out(0)
|
||||||
|
if rof.NumOut() != 1 {
|
||||||
|
panic("expecting to return only one (bool)")
|
||||||
|
}
|
||||||
|
if returnRof.Kind() != reflect.Bool {
|
||||||
|
panic("expecting this func to return a boolean")
|
||||||
|
}
|
||||||
|
|
||||||
|
if rof.NumIn() != 1 {
|
||||||
|
panic("expecting this func to receive one arg")
|
||||||
|
}
|
||||||
|
|
||||||
|
vof := reflect.ValueOf(v).Call(args)[0].Interface().(func(string) bool)
|
||||||
|
//
|
||||||
|
|
||||||
|
// this is executed when a route requested:
|
||||||
|
return func(paramValue string, _ *iris.Context) bool {
|
||||||
|
return vof(paramValue)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMacros(t *testing.T) {
|
func TestMacros(t *testing.T) {
|
||||||
addMacro("int", fromRegexp("[1-9]+$"))
|
addMacro("int", fromRegexp("[1-9]+$"))
|
||||||
|
|
||||||
// {id:int range(42,49)}
|
// {id:int range(42,49)}
|
||||||
addMacroFunc("int", "range", func(params []string) _macrofn {
|
// addMacroFunc("int", "range", func(params []string) _macrofn {
|
||||||
// start: .Boot time, before .Listen
|
// // start: .Boot time, before .Listen
|
||||||
allowedParamsLen := 2
|
// allowedParamsLen := 2
|
||||||
// params: 42,49 (including first and second)
|
// // params: 42,49 (including first and second)
|
||||||
if len(params) != allowedParamsLen {
|
// if len(params) != allowedParamsLen {
|
||||||
panic("range accepts two parameters")
|
// panic("range accepts two parameters")
|
||||||
}
|
// }
|
||||||
|
|
||||||
min, err := strconv.Atoi(params[0])
|
// min, err := strconv.Atoi(params[0])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic("invalid first parameter: " + err.Error())
|
// panic("invalid first parameter: " + err.Error())
|
||||||
}
|
// }
|
||||||
max, err := strconv.Atoi(params[1])
|
// max, err := strconv.Atoi(params[1])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic("invalid second parameter: " + err.Error())
|
// panic("invalid second parameter: " + err.Error())
|
||||||
}
|
// }
|
||||||
// end
|
// // end
|
||||||
|
|
||||||
return func(paramValue string, _ *iris.Context) bool {
|
// return func(paramValue string, _ *iris.Context) bool {
|
||||||
|
// paramValueInt, err := strconv.Atoi(paramValue)
|
||||||
|
// if err != nil {
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// if paramValueInt >= min && paramValueInt <= max {
|
||||||
|
// return true
|
||||||
|
// }
|
||||||
|
// return false
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// result should be like that in the final feature implementation, using reflection BEFORE .Listen on .Boot time,
|
||||||
|
// so no performance cost(done) =>
|
||||||
|
addMacroFunc("int", "range", macroFuncFrom(func(min int, max int) func(string) bool {
|
||||||
|
return func(paramValue string) bool {
|
||||||
paramValueInt, err := strconv.Atoi(paramValue)
|
paramValueInt, err := strconv.Atoi(paramValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
|
@ -194,7 +272,7 @@ func TestMacros(t *testing.T) {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
|
|
||||||
addMacroFunc("int", "even", func(params []string) _macrofn {
|
addMacroFunc("int", "even", func(params []string) _macrofn {
|
||||||
return func(paramValue string, _ *iris.Context) bool {
|
return func(paramValue string, _ *iris.Context) bool {
|
||||||
|
@ -221,7 +299,6 @@ func TestMacros(t *testing.T) {
|
||||||
contents := params[0]
|
contents := params[0]
|
||||||
// we don't care about path's parameter here
|
// we don't care about path's parameter here
|
||||||
return func(_ string, ctx *iris.Context) bool {
|
return func(_ string, ctx *iris.Context) bool {
|
||||||
println("print markdown?: ")
|
|
||||||
ctx.Markdown(iris.StatusOK, contents)
|
ctx.Markdown(iris.StatusOK, contents)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,12 @@ func ParseParam(source string) (*ParamTmpl, error) {
|
||||||
// id:int min(1) max(5)
|
// id:int min(1) max(5)
|
||||||
// id:int range(1,5)!404 or !404, space doesn't matters on fail error code.
|
// id:int range(1,5)!404 or !404, space doesn't matters on fail error code.
|
||||||
cursor := 0
|
cursor := 0
|
||||||
|
// hasFuncs setted to true when we validate that we have macro's functions
|
||||||
|
// so we can check for parenthesis.
|
||||||
|
// We need that check because the user may add a regexp with parenthesis.
|
||||||
|
// Although this will not be recommended, user is better to create a macro for its regexp
|
||||||
|
// in order to use it everywhere and reduce code duplication.
|
||||||
|
hasFuncs := false
|
||||||
for i := 0; i < len(source); i++ {
|
for i := 0; i < len(source); i++ {
|
||||||
if source[i] == ParamNameSeperator {
|
if source[i] == ParamNameSeperator {
|
||||||
if i+1 >= len(source) {
|
if i+1 >= len(source) {
|
||||||
|
@ -100,6 +106,7 @@ func ParseParam(source string) (*ParamTmpl, error) {
|
||||||
// take the left part: int if it's the first
|
// take the left part: int if it's the first
|
||||||
// space after the param name
|
// space after the param name
|
||||||
if t.Macro.Name == t.Expression {
|
if t.Macro.Name == t.Expression {
|
||||||
|
hasFuncs = true
|
||||||
t.Macro.Name = source[cursor:i]
|
t.Macro.Name = source[cursor:i]
|
||||||
} // else we have one or more functions, skip.
|
} // else we have one or more functions, skip.
|
||||||
|
|
||||||
|
@ -107,7 +114,7 @@ func ParseParam(source string) (*ParamTmpl, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if source[i] == FuncStart {
|
if hasFuncs && source[i] == FuncStart {
|
||||||
// take the left part: range
|
// take the left part: range
|
||||||
funcName := source[cursor:i]
|
funcName := source[cursor:i]
|
||||||
t.Macro.Funcs = append(t.Macro.Funcs, MacroFuncTmpl{Name: funcName})
|
t.Macro.Funcs = append(t.Macro.Funcs, MacroFuncTmpl{Name: funcName})
|
||||||
|
@ -116,7 +123,7 @@ func ParseParam(source string) (*ParamTmpl, error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 1,5)
|
// 1,5)
|
||||||
if source[i] == FuncEnd {
|
if hasFuncs && source[i] == FuncEnd {
|
||||||
// check if we have end parenthesis but not start
|
// check if we have end parenthesis but not start
|
||||||
if len(t.Macro.Funcs) == 0 {
|
if len(t.Macro.Funcs) == 0 {
|
||||||
return nil, fmt.Errorf("missing start macro's '%s' function, on source '%s'", t.Macro.Name, source)
|
return nil, fmt.Errorf("missing start macro's '%s' function, on source '%s'", t.Macro.Name, source)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user