-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathtag.go
111 lines (100 loc) · 2.3 KB
/
tag.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
package govalidator
import (
"strings"
)
type (
//Tag represents validation tag
Tag struct {
Checks []Check
Omitempty bool
Required bool
SkipPath bool
}
//Check represents validation check
Check struct {
Name string
Parameters []string
Message string
}
)
//ParseTag parses rule
func ParseTag(tagString string) *Tag {
tag := &Tag{}
elements := extractElements(tagString)
if len(elements) == 0 {
return tag
}
tag.Required = strings.Contains(strings.ToLower(tagString), "required")
tag.Omitempty = strings.Contains(strings.ToLower(tagString), "omitempty")
tag.SkipPath = strings.Contains(strings.ToLower(tagString), "skippath")
for _, element := range elements {
check := Check{}
pair := strings.Split(element, "=")
switch len(pair) {
case 2:
switch strings.ToLower(strings.TrimSpace(pair[0])) {
case "message":
check.Message = strings.TrimSpace(pair[1])
case "name":
check.Name, check.Parameters = extractNameWithParams(strings.TrimSpace(pair[1]))
default:
check.Name = pair[0]
check.Parameters = pair[1:]
}
case 1:
check.Name, check.Parameters = extractNameWithParams(strings.TrimSpace(element))
}
switch strings.ToLower(check.Name) {
case "omitempty", "skippath", "marker":
continue
}
tag.Checks = append(tag.Checks, check)
}
return tag
}
func extractElements(decoded string) []string {
var result []string
var fragment = ""
var inCall bool
for i, c := range decoded {
switch decoded[i] {
case ',', '|':
if inCall {
fragment += string(c)
continue
}
result = append(result, fragment)
fragment = ""
case '(':
fragment += string(c)
inCall = true
case ')':
fragment += string(c)
inCall = false
default:
fragment += string(c)
}
}
if fragment != "" {
result = append(result, fragment)
}
return result
}
var emptyArgs = []string{}
func extractNameWithParams(text string) (string, []string) {
index := strings.Index(text, "(")
if index == -1 {
return text, emptyArgs
}
name := text[:index]
argsFragment := text[index+1:]
index = strings.LastIndex(argsFragment, ")")
if index != -1 {
argsFragment = argsFragment[:index]
}
var params []string
for _, item := range strings.Split(argsFragment, ",") {
params = append(params, strings.TrimSpace(item))
}
return name, params
}