-
Notifications
You must be signed in to change notification settings - Fork 0
/
path_segment.go
128 lines (98 loc) · 2.06 KB
/
path_segment.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
package axum
import (
"regexp"
"strings"
)
const (
varSegmentPattern = `^\{[a-zA-Z]+[a-zA-Z0-9_]*\}$`
constSegmentPattern = `^[a-zA-Z]+[a-zA-Z0-9_]*$`
)
const (
segmentTypeVar = 1
segmentTypeConst = 2
segmentTypeRegex = 3
)
type pathSegmentMatcher interface {
Match(string) bool
Type() int
}
type varMatcher struct{}
func (m *varMatcher) Match(_ string) bool {
return true
}
func (m *varMatcher) Type() int {
return segmentTypeVar
}
func newVarMatch() *varMatcher {
return &varMatcher{}
}
type constMatcher struct {
value string
}
func (m *constMatcher) Match(s string) bool {
return m.value == s
}
func (m *constMatcher) Type() int {
return segmentTypeConst
}
func newConstMatcher(segment string) *constMatcher {
return &constMatcher{
value: segment,
}
}
type regexMatcher struct {
regex *regexp.Regexp
}
func (m *regexMatcher) Match(s string) bool {
return m.regex.MatchString(s)
}
func (m *regexMatcher) Type() int {
return segmentTypeRegex
}
func newRegexMatcher(segment string) *regexMatcher {
return ®exMatcher{
regex: regexp.MustCompile(segment),
}
}
type pathSegment struct {
value string
matcher pathSegmentMatcher
arg string
}
func (seg *pathSegment) Match(segment string) bool {
result := seg.matcher.Match(segment)
if seg.matcher.Type() == segmentTypeVar {
key := seg.value[1 : len(seg.value)-1]
seg.arg = key + "=" + segment
}
return result
}
func newPathSegment(v string) *pathSegment {
path := &pathSegment{
value: v,
}
varRegex := regexp.MustCompile(varSegmentPattern)
constRegex := regexp.MustCompile(constSegmentPattern)
if varRegex.MatchString(v) {
path.matcher = newVarMatch()
} else if constRegex.MatchString(v) {
path.matcher = newConstMatcher(v)
} else {
path.matcher = newRegexMatcher(v)
}
return path
}
type pathSegments []*pathSegment
func (ps pathSegments) Match(path string) bool {
path = strings.Trim(path, "/")
segs := strings.Split(path, "/")
if len(segs) != len(ps) {
return false
}
for i, p := range ps {
if !p.Match(segs[i]) {
return false
}
}
return true
}