mirror of
https://github.com/kataras/iris.git
synced 2025-12-24 05:17:03 +00:00
Conversion once at macros and their functions, internal changes required
Former-commit-id: 7b778cccfb7c0e30ca5e8106017ada065993aba5
This commit is contained in:
@@ -12,14 +12,51 @@ import (
|
||||
// EvaluatorFunc is the signature for both param types and param funcs.
|
||||
// It should accepts the param's value as string
|
||||
// and return true if validated otherwise false.
|
||||
type EvaluatorFunc func(paramValue string) bool
|
||||
// type EvaluatorFunc func(paramValue string) bool
|
||||
// type BinderFunc func(paramValue string) interface{}
|
||||
|
||||
// NewEvaluatorFromRegexp accepts a regexp "expr" expression
|
||||
// and returns an EvaluatorFunc based on that regexp.
|
||||
// the regexp is compiled before return.
|
||||
type (
|
||||
ParamEvaluator func(paramValue string) (interface{}, bool)
|
||||
// FuncEvaluator interface{} // i.e func(paramValue int) bool
|
||||
)
|
||||
|
||||
var goodEvaluatorFuncs = []reflect.Type{
|
||||
reflect.TypeOf(func(string) (interface{}, bool) { return nil, false }),
|
||||
reflect.TypeOf(ParamEvaluator(func(string) (interface{}, bool) { return nil, false })),
|
||||
}
|
||||
|
||||
func goodParamFunc(typ reflect.Type) bool {
|
||||
if typ.Kind() == reflect.Func { // it should be a func which returns a func (see below check).
|
||||
if typ.NumOut() == 1 {
|
||||
typOut := typ.Out(0)
|
||||
if typOut.Kind() != reflect.Func {
|
||||
return false
|
||||
}
|
||||
|
||||
if typOut.NumOut() == 2 { // if it's a type of EvaluatorFunc, used for param evaluator.
|
||||
for _, fType := range goodEvaluatorFuncs {
|
||||
if typOut == fType {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if typOut.NumIn() == 1 && typOut.NumOut() == 1 { // if it's a type of func(paramValue [int,string...]) bool, used for param funcs.
|
||||
return typOut.Out(0).Kind() == reflect.Bool
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Regexp accepts a regexp "expr" expression
|
||||
// and returns its MatchString.
|
||||
// The regexp is compiled before return.
|
||||
//
|
||||
// Returns a not-nil error on regexp compile failure.
|
||||
func NewEvaluatorFromRegexp(expr string) (EvaluatorFunc, error) {
|
||||
func Regexp(expr string) (func(string) bool, error) {
|
||||
if expr == "" {
|
||||
return nil, fmt.Errorf("empty regex expression")
|
||||
}
|
||||
@@ -37,36 +74,16 @@ func NewEvaluatorFromRegexp(expr string) (EvaluatorFunc, error) {
|
||||
return r.MatchString, nil
|
||||
}
|
||||
|
||||
// MustNewEvaluatorFromRegexp same as NewEvaluatorFromRegexp
|
||||
// MustRegexp same as Regexp
|
||||
// but it panics on the "expr" parse failure.
|
||||
func MustNewEvaluatorFromRegexp(expr string) EvaluatorFunc {
|
||||
r, err := NewEvaluatorFromRegexp(expr)
|
||||
func MustRegexp(expr string) func(string) bool {
|
||||
r, err := Regexp(expr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
var (
|
||||
goodParamFuncReturnType = reflect.TypeOf(func(string) bool { return false })
|
||||
goodParamFuncReturnType2 = reflect.TypeOf(EvaluatorFunc(func(string) bool { return false }))
|
||||
)
|
||||
|
||||
func goodParamFunc(typ reflect.Type) bool {
|
||||
// should be a func
|
||||
// which returns a func(string) bool
|
||||
if typ.Kind() == reflect.Func {
|
||||
if typ.NumOut() == 1 {
|
||||
typOut := typ.Out(0)
|
||||
if typOut == goodParamFuncReturnType || typOut == goodParamFuncReturnType2 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// goodParamFuncName reports whether the function name is a valid identifier.
|
||||
func goodParamFuncName(name string) bool {
|
||||
if name == "" {
|
||||
@@ -85,7 +102,7 @@ func goodParamFuncName(name string) bool {
|
||||
|
||||
// the convertBuilderFunc return value is generating at boot time.
|
||||
// convertFunc converts an interface to a valid full param function.
|
||||
func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
|
||||
func convertBuilderFunc(fn interface{}) ParamFuncBuilder {
|
||||
|
||||
typFn := reflect.TypeOf(fn)
|
||||
if !goodParamFunc(typFn) {
|
||||
@@ -94,7 +111,7 @@ func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
|
||||
|
||||
numFields := typFn.NumIn()
|
||||
|
||||
return func(args []string) EvaluatorFunc {
|
||||
return func(args []string) reflect.Value {
|
||||
if len(args) != numFields {
|
||||
// no variadics support, for now.
|
||||
panic("args should be the same len as numFields")
|
||||
@@ -179,24 +196,25 @@ func convertBuilderFunc(fn interface{}) ParamEvaluatorBuilder {
|
||||
|
||||
argValue := reflect.ValueOf(val)
|
||||
if expected, got := field.Kind(), argValue.Kind(); expected != got {
|
||||
panic(fmt.Sprintf("fields should have the same type: [%d] expected %s but got %s", i, expected, got))
|
||||
panic(fmt.Sprintf("func's input arguments should have the same type: [%d] expected %s but got %s", i, expected, got))
|
||||
}
|
||||
|
||||
argValues = append(argValues, argValue)
|
||||
}
|
||||
|
||||
evalFn := reflect.ValueOf(fn).Call(argValues)[0].Interface()
|
||||
evalFn := reflect.ValueOf(fn).Call(argValues)[0]
|
||||
|
||||
var evaluator EvaluatorFunc
|
||||
// check for typed and not typed
|
||||
if _v, ok := evalFn.(EvaluatorFunc); ok {
|
||||
evaluator = _v
|
||||
} else if _v, ok = evalFn.(func(string) bool); ok {
|
||||
evaluator = _v
|
||||
}
|
||||
return func(paramValue string) bool {
|
||||
return evaluator(paramValue)
|
||||
}
|
||||
// var evaluator EvaluatorFunc
|
||||
// // check for typed and not typed
|
||||
// if _v, ok := evalFn.(EvaluatorFunc); ok {
|
||||
// evaluator = _v
|
||||
// } else if _v, ok = evalFn.(func(string) bool); ok {
|
||||
// evaluator = _v
|
||||
// }
|
||||
// return func(paramValue interface{}) bool {
|
||||
// return evaluator(paramValue)
|
||||
// }
|
||||
return evalFn
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,16 +236,16 @@ type (
|
||||
master bool
|
||||
trailing bool
|
||||
|
||||
Evaluator EvaluatorFunc
|
||||
Evaluator ParamEvaluator
|
||||
funcs []ParamFunc
|
||||
}
|
||||
|
||||
// ParamEvaluatorBuilder is a func
|
||||
// ParamFuncBuilder is a func
|
||||
// which accepts a param function's arguments (values)
|
||||
// and returns an EvaluatorFunc, its job
|
||||
// and returns a function as value, its job
|
||||
// is to make the macros to be registered
|
||||
// by user at the most generic possible way.
|
||||
ParamEvaluatorBuilder func([]string) EvaluatorFunc
|
||||
ParamFuncBuilder func([]string) reflect.Value // the func
|
||||
|
||||
// ParamFunc represents the parsed
|
||||
// parameter function, it holds
|
||||
@@ -236,13 +254,13 @@ type (
|
||||
// the evaluator func.
|
||||
ParamFunc struct {
|
||||
Name string
|
||||
Func ParamEvaluatorBuilder
|
||||
Func ParamFuncBuilder
|
||||
}
|
||||
)
|
||||
|
||||
// NewMacro creates and returns a Macro that can be used as a registry for
|
||||
// a new customized parameter type and its functions.
|
||||
func NewMacro(indent, alias string, master, trailing bool, evaluator EvaluatorFunc) *Macro {
|
||||
func NewMacro(indent, alias string, master, trailing bool, evaluator ParamEvaluator) *Macro {
|
||||
return &Macro{
|
||||
indent: indent,
|
||||
alias: alias,
|
||||
@@ -287,7 +305,7 @@ func (m *Macro) RegisterFunc(funcName string, fn interface{}) *Macro {
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Macro) registerFunc(funcName string, fullFn ParamEvaluatorBuilder) {
|
||||
func (m *Macro) registerFunc(funcName string, fullFn ParamFuncBuilder) {
|
||||
if !goodParamFuncName(funcName) {
|
||||
return
|
||||
}
|
||||
@@ -305,7 +323,7 @@ func (m *Macro) registerFunc(funcName string, fullFn ParamEvaluatorBuilder) {
|
||||
})
|
||||
}
|
||||
|
||||
func (m *Macro) getFunc(funcName string) ParamEvaluatorBuilder {
|
||||
func (m *Macro) getFunc(funcName string) ParamFuncBuilder {
|
||||
for _, fn := range m.funcs {
|
||||
if fn.Name == funcName {
|
||||
if fn.Func == nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package macro
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -64,9 +65,25 @@ func TestGoodParamFuncName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func testEvaluatorRaw(t *testing.T, macroEvaluator *Macro, input string, pass bool, i int) {
|
||||
if got := macroEvaluator.Evaluator(input); pass != got {
|
||||
t.Fatalf("%s - tests[%d] - expecting %v but got %v", t.Name(), i, pass, got)
|
||||
func testEvaluatorRaw(t *testing.T, macroEvaluator *Macro, input string, expectedType reflect.Kind, pass bool, i int) {
|
||||
if macroEvaluator.Evaluator == nil && pass {
|
||||
return // if not evaluator defined then it should allow everything.
|
||||
}
|
||||
value, passed := macroEvaluator.Evaluator(input)
|
||||
if pass != passed {
|
||||
t.Fatalf("%s - tests[%d] - expecting[pass] %v but got %v", t.Name(), i, pass, passed)
|
||||
}
|
||||
|
||||
if !passed {
|
||||
return
|
||||
}
|
||||
|
||||
if value == nil && expectedType != reflect.Invalid {
|
||||
t.Fatalf("%s - tests[%d] - expecting[value] to not be nil", t.Name(), i)
|
||||
}
|
||||
|
||||
if v := reflect.ValueOf(value); v.Kind() != expectedType {
|
||||
t.Fatalf("%s - tests[%d] - expecting[value.Kind] %v but got %v", t.Name(), i, expectedType, v.Kind())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,30 +101,32 @@ func TestStringEvaluatorRaw(t *testing.T) {
|
||||
} // 0
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, String, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, String, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNumberEvaluatorRaw(t *testing.T) {
|
||||
func TestIntEvaluatorRaw(t *testing.T) {
|
||||
x64 := strconv.IntSize == 64
|
||||
|
||||
tests := []struct {
|
||||
pass bool
|
||||
input string
|
||||
}{
|
||||
{false, "astring"}, // 0
|
||||
{false, "astringwith_numb3rS_and_symbol$"}, // 1
|
||||
{true, "32321"}, // 2
|
||||
{true, "18446744073709551615"}, // 3
|
||||
{true, "-18446744073709551615"}, // 4
|
||||
{true, "-18446744073709553213213213213213121615"}, // 5
|
||||
{false, "42 18446744073709551615"}, // 6
|
||||
{false, "--42"}, // 7
|
||||
{false, "+42"}, // 8
|
||||
{false, "main.css"}, // 9
|
||||
{false, "/assets/main.css"}, // 10
|
||||
{false, "astring"}, // 0
|
||||
{false, "astringwith_numb3rS_and_symbol$"}, // 1
|
||||
{true, "32321"}, // 2
|
||||
{x64, "9223372036854775807" /*max int64*/}, // 3
|
||||
{x64, "-9223372036854775808" /*min int64 */}, // 4
|
||||
{false, "-18446744073709553213213213213213121615"}, // 5
|
||||
{false, "42 18446744073709551615"}, // 6
|
||||
{false, "--42"}, // 7
|
||||
{false, "+42"}, // 8
|
||||
{false, "main.css"}, // 9
|
||||
{false, "/assets/main.css"}, // 10
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Number, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Int, tt.input, reflect.Int, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +151,7 @@ func TestInt64EvaluatorRaw(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Int64, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Int64, tt.input, reflect.Int64, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +180,7 @@ func TestUint8EvaluatorRaw(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Uint8, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Uint8, tt.input, reflect.Uint8, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,7 +205,7 @@ func TestUint64EvaluatorRaw(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Uint64, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Uint64, tt.input, reflect.Uint64, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,7 +222,7 @@ func TestAlphabeticalEvaluatorRaw(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, Alphabetical, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Alphabetical, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,7 +239,7 @@ func TestFileEvaluatorRaw(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
testEvaluatorRaw(t, File, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, File, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -238,7 +257,7 @@ func TestPathEvaluatorRaw(t *testing.T) {
|
||||
}
|
||||
|
||||
for i, tt := range pathTests {
|
||||
testEvaluatorRaw(t, Path, tt.input, tt.pass, i)
|
||||
testEvaluatorRaw(t, Path, tt.input, reflect.String, tt.pass, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,8 +289,7 @@ func TestConvertBuilderFunc(t *testing.T) {
|
||||
}
|
||||
|
||||
evalFunc := convertBuilderFunc(fn)
|
||||
|
||||
if !evalFunc([]string{"1", "[name1,name2]"})("ok") {
|
||||
if !evalFunc([]string{"1", "[name1,name2]"}).Call([]reflect.Value{reflect.ValueOf("ok")})[0].Interface().(bool) {
|
||||
t.Fatalf("failed, it should fail already")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,233 +10,205 @@ import (
|
||||
var (
|
||||
// String type
|
||||
// Allows anything (single path segment, as everything except the `Path`).
|
||||
String = NewMacro("string", "", true, false, func(string) bool { return true }).
|
||||
RegisterFunc("regexp", func(expr string) EvaluatorFunc {
|
||||
return MustNewEvaluatorFromRegexp(expr)
|
||||
String = NewMacro("string", "", true, false, nil). // if nil allows everything.
|
||||
RegisterFunc("regexp", func(expr string) func(string) bool {
|
||||
return MustRegexp(expr)
|
||||
}).
|
||||
// checks if param value starts with the 'prefix' arg
|
||||
RegisterFunc("prefix", func(prefix string) EvaluatorFunc {
|
||||
RegisterFunc("prefix", func(prefix string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return strings.HasPrefix(paramValue, prefix)
|
||||
}
|
||||
}).
|
||||
// checks if param value ends with the 'suffix' arg
|
||||
RegisterFunc("suffix", func(suffix string) EvaluatorFunc {
|
||||
RegisterFunc("suffix", func(suffix string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return strings.HasSuffix(paramValue, suffix)
|
||||
}
|
||||
}).
|
||||
// checks if param value contains the 's' arg
|
||||
RegisterFunc("contains", func(s string) EvaluatorFunc {
|
||||
RegisterFunc("contains", func(s string) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return strings.Contains(paramValue, s)
|
||||
}
|
||||
}).
|
||||
// checks if param value's length is at least 'min'
|
||||
RegisterFunc("min", func(min int) EvaluatorFunc {
|
||||
RegisterFunc("min", func(min int) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return len(paramValue) >= min
|
||||
}
|
||||
}).
|
||||
// checks if param value's length is not bigger than 'max'
|
||||
RegisterFunc("max", func(max int) EvaluatorFunc {
|
||||
RegisterFunc("max", func(max int) func(string) bool {
|
||||
return func(paramValue string) bool {
|
||||
return max >= len(paramValue)
|
||||
}
|
||||
})
|
||||
|
||||
simpleNumberEvalutator = MustNewEvaluatorFromRegexp("^-?[0-9]+$")
|
||||
// Number or int type
|
||||
// both positive and negative numbers, any number of digits.
|
||||
Number = NewMacro("number", "int", false, false, simpleNumberEvalutator).
|
||||
simpleNumberEval = MustRegexp("^-?[0-9]+$")
|
||||
// Int or int type
|
||||
// both positive and negative numbers, actual value can be min-max int64 or min-max int32 depends on the arch.
|
||||
Int = NewMacro("int", "number", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !simpleNumberEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
v, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return v, true
|
||||
}).
|
||||
// checks if the param value's int representation is
|
||||
// bigger or equal than 'min'
|
||||
RegisterFunc("min", func(min int) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= min
|
||||
RegisterFunc("min", func(min int) func(int) bool {
|
||||
return func(paramValue int) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max int) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n <= max
|
||||
RegisterFunc("max", func(max int) func(int) bool {
|
||||
return func(paramValue int) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max int) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.Atoi(paramValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n < min || n > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max int) func(int) bool {
|
||||
return func(paramValue int) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
// Int64 as int64 type
|
||||
// -9223372036854775808 to 9223372036854775807.
|
||||
Int64 = NewMacro("int64", "long", false, false, func(paramValue string) bool {
|
||||
if !simpleNumberEvalutator(paramValue) {
|
||||
return false
|
||||
Int64 = NewMacro("int64", "long", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !simpleNumberEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
_, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
// if err == strconv.ErrRange...
|
||||
return err == nil
|
||||
v, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil { // if err == strconv.ErrRange...
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
}).
|
||||
// checks if the param value's int64 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min int64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= min
|
||||
RegisterFunc("min", func(min int64) func(int64) bool {
|
||||
return func(paramValue int64) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int64 representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max int64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n <= max
|
||||
RegisterFunc("max", func(max int64) func(int64) bool {
|
||||
return func(paramValue int64) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's int64 representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max int64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseInt(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n < min || n > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max int64) func(int64) bool {
|
||||
return func(paramValue int64) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
uint8Eval = MustRegexp("^([0-9]|[1-8][0-9]|9[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")
|
||||
// Uint8 as uint8 type
|
||||
// 0 to 255.
|
||||
Uint8 = NewMacro("uint8", "", false, false, MustNewEvaluatorFromRegexp("^([0-9]|[1-8][0-9]|9[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$")).
|
||||
Uint8 = NewMacro("uint8", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !uint8Eval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
v, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return uint8(v), true
|
||||
}).
|
||||
// checks if the param value's uint8 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min uint8) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return uint8(n) >= min
|
||||
RegisterFunc("min", func(min uint8) func(uint8) bool {
|
||||
return func(paramValue uint8) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint8 representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max uint8) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return uint8(n) <= max
|
||||
RegisterFunc("max", func(max uint8) func(uint8) bool {
|
||||
return func(paramValue uint8) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint8 representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max uint8) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 8)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if v := uint8(n); v < min || v > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max uint8) func(uint8) bool {
|
||||
return func(paramValue uint8) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
// Uint64 as uint64 type
|
||||
// 0 to 18446744073709551615.
|
||||
Uint64 = NewMacro("uint64", "", false, false, func(paramValue string) bool {
|
||||
if !simpleNumberEvalutator(paramValue) {
|
||||
return false
|
||||
Uint64 = NewMacro("uint64", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !simpleNumberEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
_, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
return err == nil
|
||||
v, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
}).
|
||||
// checks if the param value's uint64 representation is
|
||||
// bigger or equal than 'min'.
|
||||
RegisterFunc("min", func(min uint64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n >= min
|
||||
RegisterFunc("min", func(min uint64) func(uint64) bool {
|
||||
return func(paramValue uint64) bool {
|
||||
return paramValue >= min
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint64 representation is
|
||||
// smaller or equal than 'max'.
|
||||
RegisterFunc("max", func(max uint64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return n <= max
|
||||
RegisterFunc("max", func(max uint64) func(uint64) bool {
|
||||
return func(paramValue uint64) bool {
|
||||
return paramValue <= max
|
||||
}
|
||||
}).
|
||||
// checks if the param value's uint64 representation is
|
||||
// between min and max, including 'min' and 'max'.
|
||||
RegisterFunc("range", func(min, max uint64) EvaluatorFunc {
|
||||
return func(paramValue string) bool {
|
||||
n, err := strconv.ParseUint(paramValue, 10, 64)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if n < min || n > max {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
RegisterFunc("range", func(min, max uint64) func(uint64) bool {
|
||||
return func(paramValue uint64) bool {
|
||||
return !(paramValue < min || paramValue > max)
|
||||
}
|
||||
})
|
||||
|
||||
// Bool or boolean as bool type
|
||||
// a string which is "1" or "t" or "T" or "TRUE" or "true" or "True"
|
||||
// or "0" or "f" or "F" or "FALSE" or "false" or "False".
|
||||
Bool = NewMacro("bool", "boolean", false, false, func(paramValue string) bool {
|
||||
Bool = NewMacro("bool", "boolean", false, false, func(paramValue string) (interface{}, bool) {
|
||||
// a simple if statement is faster than regex ^(true|false|True|False|t|0|f|FALSE|TRUE)$
|
||||
// in this case.
|
||||
_, err := strconv.ParseBool(paramValue)
|
||||
return err == nil
|
||||
v, err := strconv.ParseBool(paramValue)
|
||||
if err != nil {
|
||||
return nil, false
|
||||
}
|
||||
return v, true
|
||||
})
|
||||
|
||||
alphabeticalEval = MustRegexp("^[a-zA-Z ]+$")
|
||||
// Alphabetical letter type
|
||||
// letters only (upper or lowercase)
|
||||
Alphabetical = NewMacro("alphabetical", "", false, false, MustNewEvaluatorFromRegexp("^[a-zA-Z ]+$"))
|
||||
Alphabetical = NewMacro("alphabetical", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !alphabeticalEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
return paramValue, true
|
||||
})
|
||||
|
||||
fileEval = MustRegexp("^[a-zA-Z0-9_.-]*$")
|
||||
// File type
|
||||
// letters (upper or lowercase)
|
||||
// numbers (0-9)
|
||||
@@ -244,7 +216,12 @@ var (
|
||||
// dash (-)
|
||||
// point (.)
|
||||
// no spaces! or other character
|
||||
File = NewMacro("file", "", false, false, MustNewEvaluatorFromRegexp("^[a-zA-Z0-9_.-]*$"))
|
||||
File = NewMacro("file", "", false, false, func(paramValue string) (interface{}, bool) {
|
||||
if !fileEval(paramValue) {
|
||||
return nil, false
|
||||
}
|
||||
return paramValue, true
|
||||
})
|
||||
// Path type
|
||||
// anything, should be the last part
|
||||
//
|
||||
@@ -252,11 +229,11 @@ var (
|
||||
// types because I want to give the opportunity to the user
|
||||
// to organise the macro functions based on wildcard or single dynamic named path parameter.
|
||||
// Should be living in the latest path segment of a route path.
|
||||
Path = NewMacro("path", "", false, true, func(string) bool { return true })
|
||||
Path = NewMacro("path", "", false, true, nil)
|
||||
|
||||
Defaults = &Macros{
|
||||
String,
|
||||
Number,
|
||||
Int,
|
||||
Int64,
|
||||
Uint8,
|
||||
Uint64,
|
||||
@@ -268,7 +245,7 @@ var (
|
||||
|
||||
type Macros []*Macro
|
||||
|
||||
func (ms *Macros) Register(indent, alias string, isMaster, isTrailing bool, evaluator EvaluatorFunc) *Macro {
|
||||
func (ms *Macros) Register(indent, alias string, isMaster, isTrailing bool, evaluator ParamEvaluator) *Macro {
|
||||
macro := NewMacro(indent, alias, isMaster, isTrailing, evaluator)
|
||||
if ms.register(macro) {
|
||||
return macro
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package macro
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/kataras/iris/core/router/macro/interpreter/ast"
|
||||
"github.com/kataras/iris/core/router/macro/interpreter/parser"
|
||||
)
|
||||
@@ -27,8 +29,8 @@ type TemplateParam struct {
|
||||
Name string `json:"name"`
|
||||
Index int `json:"index"`
|
||||
ErrCode int `json:"errCode"`
|
||||
TypeEvaluator EvaluatorFunc `json:"-"`
|
||||
Funcs []EvaluatorFunc `json:"-"`
|
||||
TypeEvaluator ParamEvaluator `json:"-"`
|
||||
Funcs []reflect.Value `json:"-"`
|
||||
}
|
||||
|
||||
// Parse takes a full route path and a macro map (macro map contains the macro types with their registered param functions)
|
||||
@@ -74,7 +76,7 @@ func Parse(src string, macros Macros) (*Template, error) {
|
||||
}
|
||||
|
||||
evalFn := tmplFn(paramfn.Args)
|
||||
if evalFn == nil {
|
||||
if evalFn.IsNil() || !evalFn.IsValid() || evalFn.Kind() != reflect.Func {
|
||||
continue
|
||||
}
|
||||
tmplParam.Funcs = append(tmplParam.Funcs, evalFn)
|
||||
|
||||
Reference in New Issue
Block a user