trpc.group/trpc-go/trpc-go@v1.0.3/internal/httprule/template.go (about) 1 // 2 // 3 // Tencent is pleased to support the open source community by making tRPC available. 4 // 5 // Copyright (C) 2023 THL A29 Limited, a Tencent company. 6 // All rights reserved. 7 // 8 // If you have downloaded a copy of the tRPC source code from Tencent, 9 // please note that tRPC source code is licensed under the Apache 2.0 License, 10 // A copy of the Apache 2.0 License is included in this file. 11 // 12 // 13 14 package httprule 15 16 import ( 17 "fmt" 18 "strings" 19 ) 20 21 // PathTemplate URL path template: 22 // 23 // Template = "/" Segments [ Verb ] ; 24 // Segments = Segment { "/" Segment } ; 25 // Segment = "*" | "**" | LITERAL | Variable ; 26 // Variable = "{" FieldPath [ "=" Segments ] "}" ; 27 // FieldPath = IDENT { "." IDENT } ; 28 // Verb = ":" LITERAL ; 29 type PathTemplate struct { 30 segments []segment 31 verb string 32 } 33 34 // segment type. 35 type segmentKind int 36 37 const ( 38 kindWildcard segmentKind = iota 39 kindDeepWildcard 40 kindLiteral 41 kindVariable 42 ) 43 44 // Segment = "*" | "**" | LITERAL | Variable 45 type segment interface { 46 fmt.Stringer 47 handle(*matcher) error 48 kind() segmentKind 49 fieldPath() []string 50 nestedSegments() []segment 51 } 52 53 var _ segment = wildcard{} 54 var _ segment = deepWildcard{} 55 var _ segment = literal("") 56 var _ segment = variable{} 57 58 // wildcard represents *. 59 type wildcard struct{} 60 61 // String implements segment. 62 func (wildcard) String() string { 63 return "*" 64 } 65 66 // fieldPath implements segment. 67 func (wildcard) fieldPath() []string { 68 return nil 69 } 70 71 // kind implements segment. 72 func (wildcard) kind() segmentKind { 73 return kindWildcard 74 } 75 76 // nestedSegments implements segment. 77 func (wildcard) nestedSegments() []segment { 78 return nil 79 } 80 81 // deepWildcard represents **. 82 type deepWildcard struct{} 83 84 // String implements segment. 85 func (deepWildcard) String() string { 86 return "**" 87 } 88 89 // fieldPath implements segment. 90 func (deepWildcard) fieldPath() []string { 91 return nil 92 } 93 94 // kind implements segment. 95 func (deepWildcard) kind() segmentKind { 96 return kindDeepWildcard 97 } 98 99 // nestedSegments implements segment. 100 func (deepWildcard) nestedSegments() []segment { 101 return nil 102 } 103 104 // literal, example: /foo. 105 type literal string 106 107 // String implements segment. 108 func (l literal) String() string { 109 return string(l) 110 } 111 112 // fieldPath implements segment. 113 func (literal) fieldPath() []string { 114 return nil 115 } 116 117 // kind implements segment. 118 func (literal) kind() segmentKind { 119 return kindLiteral 120 } 121 122 // nestedSegments implements segment. 123 func (literal) nestedSegments() []segment { 124 return nil 125 } 126 127 // variable is like {var=*},Variable = "{" FieldPath [ "=" Segments ] "}" 128 type variable struct { 129 fp []string // FieldPath = IDENT { "." IDENT } 130 segments []segment 131 } 132 133 // String imeplemts segment. 134 func (v variable) String() string { 135 ss := make([]string, len(v.segments)) 136 for i := range v.segments { 137 ss[i] = v.segments[i].String() 138 } 139 return fmt.Sprintf("{%s=%s}", strings.Join(v.fp, "."), strings.Join(ss, "/")) 140 } 141 142 // fieldPath implements segment. 143 func (v variable) fieldPath() []string { 144 return v.fp 145 } 146 147 // kind implements segment. 148 func (variable) kind() segmentKind { 149 return kindVariable 150 } 151 152 // nestedSegments implements segment. 153 func (v variable) nestedSegments() []segment { 154 return v.segments 155 } 156 157 // FieldPaths gets field paths. 158 func (tpl *PathTemplate) FieldPaths() [][]string { 159 var fps [][]string 160 for _, segment := range tpl.segments { 161 if fp := segment.fieldPath(); fp != nil { 162 fps = append(fps, fp) 163 } 164 } 165 return fps 166 }