...
1 package httprule
2
3 import (
4 "github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
5 )
6
7 const (
8 opcodeVersion = 1
9 )
10
11
12 type Template struct {
13
14 Version int
15
16 OpCodes []int
17
18 Pool []string
19
20 Verb string
21
22 Fields []string
23
24 Template string
25 }
26
27
28
29 type Compiler interface {
30 Compile() Template
31 }
32
33 type op struct {
34
35 code utilities.OpCode
36
37
38
39 str string
40
41
42 num int
43 }
44
45 func (w wildcard) compile() []op {
46 return []op{
47 {code: utilities.OpPush},
48 }
49 }
50
51 func (w deepWildcard) compile() []op {
52 return []op{
53 {code: utilities.OpPushM},
54 }
55 }
56
57 func (l literal) compile() []op {
58 return []op{
59 {
60 code: utilities.OpLitPush,
61 str: string(l),
62 },
63 }
64 }
65
66 func (v variable) compile() []op {
67 var ops []op
68 for _, s := range v.segments {
69 ops = append(ops, s.compile()...)
70 }
71 ops = append(ops, op{
72 code: utilities.OpConcatN,
73 num: len(v.segments),
74 }, op{
75 code: utilities.OpCapture,
76 str: v.path,
77 })
78
79 return ops
80 }
81
82 func (t template) Compile() Template {
83 var rawOps []op
84 for _, s := range t.segments {
85 rawOps = append(rawOps, s.compile()...)
86 }
87
88 var (
89 ops []int
90 pool []string
91 fields []string
92 )
93 consts := make(map[string]int)
94 for _, op := range rawOps {
95 ops = append(ops, int(op.code))
96 if op.str == "" {
97 ops = append(ops, op.num)
98 } else {
99
100 if op.str == eof {
101 op.str = ""
102 }
103 if _, ok := consts[op.str]; !ok {
104 consts[op.str] = len(pool)
105 pool = append(pool, op.str)
106 }
107 ops = append(ops, consts[op.str])
108 }
109 if op.code == utilities.OpCapture {
110 fields = append(fields, op.str)
111 }
112 }
113 return Template{
114 Version: opcodeVersion,
115 OpCodes: ops,
116 Pool: pool,
117 Verb: t.verb,
118 Fields: fields,
119 Template: t.template,
120 }
121 }
122
View as plain text