forked from kataras/iris
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ast.go
215 lines (198 loc) 路 5.33 KB
/
ast.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package ast
import (
"fmt"
"reflect"
"strconv"
)
// ParamType is a specific uint8 type
// which holds the parameter types' type.
type ParamType uint8
const (
// ParamTypeUnExpected is an unexpected parameter type.
ParamTypeUnExpected ParamType = iota
// ParamTypeString is the string type.
// If parameter type is missing then it defaults to String type.
// Allows anything
// Declaration: /mypath/{myparam:string} or /mypath{myparam}
ParamTypeString
// ParamTypeInt is the integer, a number type.
// Allows only positive numbers (0-9)
// Declaration: /mypath/{myparam:int}
ParamTypeInt
// ParamTypeLong is the integer, a number type.
// Allows only positive numbers (0-9)
// Declaration: /mypath/{myparam:long}
ParamTypeLong
// ParamTypeBoolean is the bool type.
// Allows only "1" or "t" or "T" or "TRUE" or "true" or "True"
// or "0" or "f" or "F" or "FALSE" or "false" or "False".
// Declaration: /mypath/{myparam:boolean}
ParamTypeBoolean
// ParamTypeAlphabetical is the alphabetical/letter type type.
// Allows letters only (upper or lowercase)
// Declaration: /mypath/{myparam:alphabetical}
ParamTypeAlphabetical
// ParamTypeFile is the file single path type.
// Allows:
// letters (upper or lowercase)
// numbers (0-9)
// underscore (_)
// dash (-)
// point (.)
// no spaces! or other character
// Declaration: /mypath/{myparam:file}
ParamTypeFile
// ParamTypePath is the multi path (or wildcard) type.
// Allows anything, should be the last part
// Declaration: /mypath/{myparam:path}
ParamTypePath
)
func (pt ParamType) String() string {
for k, v := range paramTypes {
if v == pt {
return k
}
}
return "unexpected"
}
// Not because for a single reason
// a string may be a
// ParamTypeString or a ParamTypeFile
// or a ParamTypePath or ParamTypeAlphabetical.
//
// func ParamTypeFromStd(k reflect.Kind) ParamType {
// Kind returns the std kind of this param type.
func (pt ParamType) Kind() reflect.Kind {
switch pt {
case ParamTypeAlphabetical:
fallthrough
case ParamTypeFile:
fallthrough
case ParamTypePath:
fallthrough
case ParamTypeString:
return reflect.String
case ParamTypeInt:
return reflect.Int
case ParamTypeLong:
return reflect.Int64
case ParamTypeBoolean:
return reflect.Bool
}
return reflect.Invalid // 0
}
// ValidKind will return true if at least one param type is supported
// for this std kind.
func ValidKind(k reflect.Kind) bool {
switch k {
case reflect.String:
fallthrough
case reflect.Int:
fallthrough
case reflect.Int64:
fallthrough
case reflect.Bool:
return true
default:
return false
}
}
// Assignable returns true if the "k" standard type
// is assignabled to this ParamType.
func (pt ParamType) Assignable(k reflect.Kind) bool {
return pt.Kind() == k
}
var paramTypes = map[string]ParamType{
"string": ParamTypeString,
"int": ParamTypeInt,
"long": ParamTypeLong,
"boolean": ParamTypeBoolean,
"alphabetical": ParamTypeAlphabetical,
"file": ParamTypeFile,
"path": ParamTypePath,
// could be named also:
// "tail":
// "wild"
// "wildcard"
}
// LookupParamType accepts the string
// representation of a parameter type.
// Available:
// "string"
// "int"
// "long"
// "alphabetical"
// "file"
// "path"
func LookupParamType(ident string) ParamType {
if typ, ok := paramTypes[ident]; ok {
return typ
}
return ParamTypeUnExpected
}
// LookupParamTypeFromStd accepts the string representation of a standard go type.
// It returns a ParamType, but it may differs for example
// the alphabetical, file, path and string are all string go types, so
// make sure that caller resolves these types before this call.
//
// string matches to string
// int matches to int
// int64 matches to long
// bool matches to boolean
func LookupParamTypeFromStd(goType string) ParamType {
switch goType {
case "string":
return ParamTypeString
case "int":
return ParamTypeInt
case "int64":
return ParamTypeLong
case "bool":
return ParamTypeBoolean
default:
return ParamTypeUnExpected
}
}
// ParamStatement is a struct
// which holds all the necessary information about a macro parameter.
// It holds its type (string, int, alphabetical, file, path),
// its source ({param:type}),
// its name ("param"),
// its attached functions by the user (min, max...)
// and the http error code if that parameter
// failed to be evaluated.
type ParamStatement struct {
Src string // the original unparsed source, i.e: {id:int range(1,5) else 404}
Name string // id
Type ParamType // int
Funcs []ParamFunc // range
ErrorCode int // 404
}
// ParamFuncArg represents a single parameter function's argument
type ParamFuncArg interface{}
// ParamFuncArgToInt converts and returns
// any type of "a", to an integer.
func ParamFuncArgToInt(a ParamFuncArg) (int, error) {
switch a.(type) {
case int:
return a.(int), nil
case string:
return strconv.Atoi(a.(string))
case int64:
return int(a.(int64)), nil
default:
return -1, fmt.Errorf("unexpected function argument type: %q", a)
}
}
// ParamFunc holds the name of a parameter's function
// and its arguments (values)
// A param func is declared with:
// {param:int range(1,5)},
// the range is the
// param function name
// the 1 and 5 are the two param function arguments
// range(1,5)
type ParamFunc struct {
Name string // range
Args []ParamFuncArg // [1,5]
}